diff options
1042 files changed, 37825 insertions, 12361 deletions
diff --git a/AUTHORS.md b/AUTHORS.md index 752300cb5b..3d7a6adf60 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -70,12 +70,14 @@ name is available. Joshua Grams (JoshuaGrams) Juan Linietsky (reduz) Julian Murgia (StraToN) + Justo Delgado (mrcdk) Kostadin Damyanov (Max-Might) Leon Krause (eska014) Marc Gilleron (Zylann) Marcelo Fernandez (marcelofg55) Mariano Javier Suligoy (MarianoGnu) Mario Schlack (hurikhan) + Martin Sjursen (binbitten) Masoud BH (masoudbh3) Matthias Hölzl (hoelzl) Max Hilbrunner (mhilbrunner) @@ -85,8 +87,10 @@ name is available. Ovnuniarchos Patrick (firefly2442) Paul Batty (Paulb23) + Paul Joannon (paulloz) Pawel Kowal (pkowal1982) Pedro J. Estébanez (RandomShaper) + Pieter-Jan Briers (PJB3005) Poommetee Ketson (Noshyaar) PrzemysÅ‚aw GoÅ‚Ä…b (n-pigeon) Ralf Hölzemer (rollenrolm) diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..533968886e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,140 @@ +# Changelog + +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/). + +## [3.0] - 2018-01-29 + +### Added + +- Physically-based renderer using OpenGL ES 3.0. + - Uses the Disney PBR model, with clearcoat, sheen and anisotropy parameters available. + - Uses a forward renderer, supporting multi-sample anti-aliasing (MSAA). + - Parallax occlusion mapping. + - Reflection probes. + - Screen-space reflections. + - Real-time global illumination using voxel cone tracing (GIProbe). + - Proximity fade and distance fade (useful for creating soft particles and various effects). + - [Lightmapper](https://godotengine.org/article/introducing-new-last-minute-lightmapper) for lower-end desktop and mobile platforms, as an alternative to GIProbe. +- New SpatialMaterial resource, replacing FixedMaterial. + - Multiple passes can now be specified (with an optional "grow" property), allowing for effects such as cel shading. +- Brand new 3D post-processing system. + - Depth of field (near and far). + - Fog, supporting light transmittance, sun-oriented fog, depth fog and height fog. + - Tonemapping and Auto-exposure. + - Screen-space ambient occlusion. + - Multi-stage glow and bloom, supporting optional bicubic upscaling for better quality. + - Color grading and various adjustments. +- Rewritten audio engine from scratch. + - Supports audio routing with arbitrary number of channels, including Area-based audio redirection ([video](https://youtu.be/K2XOBaJ5OQ0)). + - More than a dozen of audio effects included. +- Rewritten 3D physics using [Bullet](http://bulletphysics.org/). +- UDP-based high-level networking API using [ENet](http://enet.bespin.org/). +- IPv6 support for all of the engine's networking APIs. +- Visual scripting. +- Rewritten import system. + - Assets are now referenced with their source files, then imported in a transparent manner by the engine. + - Imported assets are now cached in a `.import` directory, making distribution and versioning easier. + - Support for ETC2 compression. + - Support for uncompressed Targa (.tga) textures, allowing for faster importing. +- Rewritten export system. + - GPU-based texture compression can now be tweaked per-target. + - Support for exporting resource packs to build DLC / content addons. +- Improved GDScript. + - Pattern matching using the `match` keyword. + - `$` shorthand for `get_node()`. + - Setters and getters for node properties. + - Underscores in number literals are now allowed for improved readability (for example,`1_000_000`). + - Improved performance (+20% to +40%, based on various benchmarks). +- [Feature tags](http://docs.godotengine.org/en/latest/learning/workflow/export/feature_tags.html) in the Project Settings, for custom per-platform settings. +- Full support for the [glTF 2.0](https://www.khronos.org/gltf/) 3D interchange format. +- Freelook and fly navigation to the 3D editor. +- Built-in editor logging (logging standard output to a file), disabled by default. +- Improved, more intuitive file chooser in the editor. +- Smoothed out 3D editor zooming, panning and movement. +- Toggleable rendering information box in the 3D editor viewport. + - FPS display can also be enabled in the editor viewport. +- Ability to render the 3D editor viewport at half resolution to achieve better performance. +- GDNative for binding languages like C++ to Godot as dynamic libraries. + - Community bindings for [D](https://github.com/GodotNativeTools/godot-d), [Nim](https://github.com/pragmagic/godot-nim) and [Python](https://github.com/touilleMan/godot-python) are available. +- Editor settings and export templates are now versioned, making it easier to use several Godot versions on the same system. +- Optional soft shadows for 2D rendering. +- HDR sky support. +- Ability to toggle V-Sync while the project is running. +- Panorama sky support (sphere maps). +- Support for WebM videos (VP8/VP9 with Vorbis/Opus). +- Exporting to HTML5 using WebAssembly. +- C# support using Mono. + - The Mono module is disabled by default, and needs to be compiled in at build-time. + - The latest Mono version (5.4) can be used, fully supporting C# 7.0. +- Support for rasterizing SVG to images on-the-fly, using the nanosvg library. + - Editor icons are now in SVG format, making them better-looking at non-integer scales. + - Due to the library used, only simpler SVGs are well-supported, more complex SVGs may not render correctly. +- Support for oversampling DynamicFonts, keeping them sharp when scaled to high resolutions. +- Improved StyleBoxFlat. + - Border widths can now be set per-corner. + - Support for anti-aliased rounded and beveled corners. + - Support for soft drop shadows. +- VeryLoDPI (75%) and MiDPI (150%) scaling modes for the editor. +- Improved internationalization support for projects. + - Language changes are now effective without reloading the current scene. +- Implemented missing features in the HTML5 platform. + - Cursor style changes. + - Cursor capturing and hiding. +- Improved styling and presentation of HTML5 exports. + - A spinner is now displayed during loading. +- Rewritten the 2D and 3D particle systems. + - Particles are now GPU-based, allowing their use in much higher quantities than before. + - Meshes can now be used as particles. + - Particles can now be emitted from a mesh's shape. + - Properties can now be modified over time using an editable curve. + - Custom particle shaders can now be used. +- New editor theme, with customizable base color, highlight color and contrast. + - A light editor theme option is now available, with icons suited to light backgrounds. + - Alternative dark gray and Arc colors are available out of the box. +- New adaptive text editor theme, adjusting automatically based on the editor colors. +- Support for macOS trackpad gestures in the editor. +- Exporting to macOS now creates a `.dmg` disk image if exporting from an editor running on macOS. + - Signing the macOS export now is possible if running macOS (requires a valid code signing certificate). +- Exporting to Windows now changes the exported project's icon using `rcedit` (requires WINE if exporting from Linux or macOS). +- Improved build system. + - Support for compiling using Visual Studio 2017. + - [SCons](http://scons.org/) 3.0 and Python 3 are now supported (SCons 2.5 and Python 2.7 still work). + - Link-time optimization can now be enabled by passing `use_lto=yes` to the SCons command line. + - Produces faster and sometimes smaller binaries. + - Currently only supported with GCC and MSVC. + - Added a progress percentage when compiling Godot. + - `.zip` archives are automatically created when compiling HTML5 export templates. +- Easier and more powerful way to create editor plugins with EditorPlugin and related APIs. + +### Changed + +- Increased the default low-processor-usage mode FPS limit (60 → 125). + - This makes the editor smoother and more responsive. +- Increased the default 3D editor camera's field of view (55 → 70). +- Increased the default 3D Camera node's field of view (65 → 70). +- Changed the default editor font (Droid Sans → [Noto Sans](https://www.google.com/get/noto/)). +- Changed the default script editor font (Source Code Pro → [Hack](http://sourcefoundry.org/hack/)) +- Renamed `engine.cfg` to `project.godot`. + - This allows users to open a project by double-clicking the file if Godot is associated to `.godot` files. +- Some methods from the `OS` singleton were moved to the new `Engine` singleton. +- Switched from [GLEW](http://glew.sourceforge.net/) to [GLAD](http://glad.dav1d.de/) for OpenGL wrapping. +- Changed the SCons build flag for simple logs (`colored=yes` → `verbose=no`). +- The HTML5 platform now uses WebGL 2.0 (instead of 1.0). +- Redesigned the Godot logo to be more legible at small sizes. + +### Deprecated + +- `opacity` and `self_opacity` are replaced by `modulate` and `self_modulate` in all 2D nodes, allowing for full color changes in addition to opacity changes. + +### Removed + +- Skybox support. + - Replaced with panorama skies, which are easier to import. +- Opus audio codec support. + - This is due to the way the new audio engine is designed. +- HTML5 export using asm.js. + - Only WebAssembly is supported now, since all browsers supporting WebGL 2.0 also support WebAssembly. + +[3.0]: https://github.com/godotengine/godot/compare/2.1-stable...3.0-stable @@ -18,6 +18,7 @@ generous deed immortalized in the next stable release of Godot Engine. Gamblify <https://www.gamblify.com> GameDev.TV <https://www.gamedev.tv> + Skirmish <https://skirmish.io> ## Mini sponsors @@ -26,16 +27,17 @@ generous deed immortalized in the next stable release of Godot Engine. Christian Uldall Pedersen Christopher Igoe Christoph Woinke + codetrotter E Hewert Hein-Pieter van Braam Jamal Alyafei Jay Sistar - Jordan M Lucas Matthieu Huvé Nathan Warden Neal Gompa (Conan Kudo) Pascal Julien Ruslan Mustakov + Sébastien Manin Slobodan Milnovic Stephan Lanfermann Stoney Meyerhoeffer @@ -62,7 +64,9 @@ generous deed immortalized in the next stable release of Godot Engine. Josep G. Camarasa Kris Michael Libre-Dépanne + Mike King Ranoller + Rob Messick Svenne Krap Timothy Hagberg @@ -77,18 +81,21 @@ generous deed immortalized in the next stable release of Godot Engine. Garrett Dockins Guilherme Felipe de C. G. da Silva Harman Bains + Henrique Alves Karsten Bock Laurence Bannister + Rami Robert Willes Robin Arys ScottMakesGames Testus Maximus Thomas Bjarnelöf + Wojciech Chojnacki Xavier Tan Zaq Poi + Alexey Dyadchenko Amanda Haldy - Andreas Haas Arnaud Verstuyf Chris Brown Chris Wilson @@ -96,27 +103,28 @@ generous deed immortalized in the next stable release of Godot Engine. D Daniel Eliasinski Eric Monson - Ezra Theunissen flesk François Cantin + G Barnes GGGames.org Heath Hayes Jeppe Zapp Jeremi Biernacki joe513 + Jordan M Lucas Juraj Móza Justin Arnold Justo Delgado Baudà Leandro Voltolino Lisandro Lorea Markus Wiesner + Marty Plumbo + Marvin Nick Nikitin Pablo Cholaky - Paolo Munoz Patrick Schnorbus Pete Goodwin - Rami - Ryan Estes + Phyronnaz Ted Travis Womack Trent McPheron @@ -125,6 +133,7 @@ generous deed immortalized in the next stable release of Godot Engine. 1D_Inc Adam Carr + Adam Smeltzer Alder Stefano Alessandro Senese Ãlvaro DomÃnguez López @@ -139,10 +148,12 @@ generous deed immortalized in the next stable release of Godot Engine. Benjamin Beshara Ben Vercammen Blair Allen + Bryan Crow Bryanna M Bryan Stevenson Carwyn Edwards Casey Foote + Chris Chapin Christian Baune Christian Winter Collin Shooltz @@ -152,25 +163,28 @@ generous deed immortalized in the next stable release of Godot Engine. Daniel Mircea David Cravens David May - Diego Moreira Guimarães Dominik Wetzel Eric Martini Fabian Becker fengjiongmax Francesco Lisi - Fredy Romero Sam G3Dev sà rl Geequlim Gerrit Großkopf + Gerrit Procee Gilberto K. Otubo Guldoman HeartBeast Heribert Hirth Hunter Jones + ialex32x Jaime Ruiz-Borau Vizárraga Jed Rose Jeff Hungerford + Joel Fivat + Johannes du Randt Jonas Yamazaki + Jonathan Martin Jonathan Nieto Jonathon Josh 'Cheeseness' Bush @@ -178,6 +192,7 @@ generous deed immortalized in the next stable release of Godot Engine. Judd JuDelCo Julian Murgia + Justin Luk KC Chan Kevin Boyer Kevin Kamper Meejach Petersen @@ -189,12 +204,13 @@ generous deed immortalized in the next stable release of Godot Engine. Martin Novák Matthew Fitzpatrick Matthias Hölzl - Maurice Meysel Max R.R. Collada memoryruins mhilbrunner Michael Dürwald Michael Gringauz + Michael Labbe + Mikael Olsson MoM monokrome Moritz Laass @@ -203,6 +219,7 @@ generous deed immortalized in the next stable release of Godot Engine. Niclas Eriksen Nik Lee Niko Leopold + nivardus Noi Sek Oleg Tyshchenko Pablo Seibelt @@ -212,6 +229,7 @@ generous deed immortalized in the next stable release of Godot Engine. Patric Vormstein Paul Mason PaweÅ‚ Kowal + Pedro Luz Pierre-Igor Berthet Pietro Vertechi Piotr Kaczmarski @@ -223,12 +241,14 @@ generous deed immortalized in the next stable release of Godot Engine. Sasori Olkof Scott D. Yelich Sootstone - Stephen Traskal Theo Cranmore + Thibault Barbaroux Thomas Bell Thomas Herzog & Xananax Tom Larrow + Tyler Stafos UltyX + Victor Holt Wout Standaert Yu He diff --git a/SConstruct b/SConstruct index b8d3427690..7a8db10931 100644 --- a/SConstruct +++ b/SConstruct @@ -65,7 +65,7 @@ platform_arg = ARGUMENTS.get("platform", ARGUMENTS.get("p", False)) if (os.name == "posix"): pass elif (os.name == "nt"): - if (os.getenv("VCINSTALLDIR") == None or platform_arg == "android" or platform_arg == "javascript"): + if platform_arg == "android" or platform_arg == "javascript" or ARGUMENTS.get("use_mingw", False): custom_tools = ['mingw'] env_base = Environment(tools=custom_tools) @@ -92,6 +92,7 @@ env_base.use_ptrcall = False env_base.split_drivers = False 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 @@ -145,7 +146,7 @@ opts = Variables(customs, ARGUMENTS) # Target build options opts.Add('arch', "Platform-dependent architecture (arm/arm64/x86/x64/mips/etc)", '') -opts.Add(EnumVariable('bits', "Target platform bits", 'default', ('default', '32', '64', 'fat'))) +opts.Add(EnumVariable('bits', "Target platform bits", 'default', ('default', '32', '64'))) opts.Add('p', "Platform (alias for 'platform')", '') opts.Add('platform', "Target platform (%s)" % ('|'.join(platform_list), ), '') opts.Add(EnumVariable('target', "Compilation target", 'debug', ('debug', 'release_debug', 'release'))) @@ -240,14 +241,13 @@ sys.modules.pop('detect') """ if (env_base['target'] == 'debug'): - env_base.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC']) - env_base.Append(CPPFLAGS=['-DSCI_NAMESPACE']) + env_base.Append(CPPDEFINES=['DEBUG_MEMORY_ALLOC', 'SCI_NAMESPACE']) if (env_base['no_editor_splash']): - env_base.Append(CPPFLAGS=['-DNO_EDITOR_SPLASH']) + env_base.Append(CPPDEFINES=['NO_EDITOR_SPLASH']) if not env_base['deprecated']: - env_base.Append(CPPFLAGS=['-DDISABLE_DEPRECATED']) + env_base.Append(CPPDEFINES=['DISABLE_DEPRECATED']) env_base.platforms = {} @@ -329,9 +329,7 @@ if selected_platform in platform_list: if (env["warnings"] == 'yes'): print("WARNING: warnings=yes is deprecated; assuming warnings=all") - env.msvc = 0 - if (os.name == "nt" and os.getenv("VCINSTALLDIR") and (platform_arg == "windows" or platform_arg == "uwp")): # MSVC, needs to stand out of course - env.msvc = 1 + if env.msvc: disable_nonessential_warnings = ['/wd4267', '/wd4244', '/wd4305', '/wd4800'] # Truncations, narrowing conversions... if (env["warnings"] == 'extra'): env.Append(CCFLAGS=['/Wall']) # Implies /W4 @@ -353,7 +351,7 @@ if selected_platform in platform_list: env.Append(CCFLAGS=['-Wall', '-Wno-unused']) else: # 'no' env.Append(CCFLAGS=['-w']) - + env.Append(CCFLAGS=['-Werror=return-type']) #env['platform_libsuffix'] = env['LIBSUFFIX'] suffix = "." + selected_platform @@ -363,7 +361,7 @@ if selected_platform in platform_list: print("Tools can only be built with targets 'debug' and 'release_debug'.") sys.exit(255) suffix += ".opt" - env.Append(CCFLAGS=['-DNDEBUG']) + env.Append(CPPDEFINES=['NDEBUG']) elif (env["target"] == "release_debug"): if env["tools"]: @@ -382,8 +380,6 @@ if selected_platform in platform_list: suffix += ".32" elif (env["bits"] == "64"): suffix += ".64" - elif (env["bits"] == "fat"): - suffix += ".fat" suffix += env.extra_suffix @@ -422,31 +418,32 @@ if selected_platform in platform_list: env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"] if (env.use_ptrcall): - env.Append(CPPFLAGS=['-DPTRCALL_ENABLED']) + env.Append(CPPDEFINES=['PTRCALL_ENABLED']) # to test 64 bits compiltion # env.Append(CPPFLAGS=['-m64']) if env['tools']: - env.Append(CPPFLAGS=['-DTOOLS_ENABLED']) + env.Append(CPPDEFINES=['TOOLS_ENABLED']) if env['disable_3d']: - env.Append(CPPFLAGS=['-D_3D_DISABLED']) + env.Append(CPPDEFINES=['_3D_DISABLED']) if env['gdscript']: - env.Append(CPPFLAGS=['-DGDSCRIPT_ENABLED']) + env.Append(CPPDEFINES=['GDSCRIPT_ENABLED']) if env['disable_advanced_gui']: - env.Append(CPPFLAGS=['-DADVANCED_GUI_DISABLED']) + env.Append(CPPDEFINES=['ADVANCED_GUI_DISABLED']) if env['minizip']: - env.Append(CPPFLAGS=['-DMINIZIP_ENABLED']) + env.Append(CPPDEFINES=['MINIZIP_ENABLED']) if env['xml']: - env.Append(CPPFLAGS=['-DXML_ENABLED']) + env.Append(CPPDEFINES=['XML_ENABLED']) if not env['verbose']: methods.no_verbose(sys, env) if (not env["platform"] == "server"): # FIXME: detect GLES3 - env.Append( BUILDERS = { 'GLES3_GLSL' : env.Builder(action = methods.build_gles3_headers, suffix = 'glsl.gen.h',src_suffix = '.glsl') } ) + env.Append( BUILDERS = { 'GLES3_GLSL' : env.Builder(action = methods.build_gles3_headers, suffix = 'glsl.gen.h', src_suffix = '.glsl') } ) + env.Append( BUILDERS = { 'GLES2_GLSL' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.gen.h', src_suffix = '.glsl') } ) scons_cache_path = os.environ.get("SCONS_CACHE") if scons_cache_path != None: @@ -480,10 +477,7 @@ if selected_platform in platform_list: if ("check_c_headers" in env): for header in env["check_c_headers"]: if (conf.CheckCHeader(header[0])): - if (env.msvc): - env.Append(CCFLAGS=['/D' + header[1]]) - else: - env.Append(CCFLAGS=['-D' + header[1]]) + env.AppendUnique(CPPDEFINES=[header[1]]) else: @@ -494,127 +488,118 @@ else: print("\nPlease run scons again with argument: platform=<string>") -screen = sys.stdout -node_count = 0 -node_count_max = 0 -node_count_interval = 1 -node_pruning = 8 # Number of nodes to process before prunning the cache -if ('env' in locals()): +# The following only makes sense when the env is defined, and assumes it is +if 'env' in locals(): + screen = sys.stdout + # Progress reporting is not available in non-TTY environments since it + # messes with the output (for example, when writing to a file) + show_progress = (env['progress'] and sys.stdout.isatty()) + node_count = 0 + node_count_max = 0 + node_count_interval = 1 node_count_fname = str(env.Dir('#')) + '/.scons_node_count' -# Progress reporting is not available in non-TTY environments since it -# messes with the output (for example, when writing to a file) -if sys.stdout.isatty(): - show_progress = env['progress'] -else: - show_progress = False - -import time, math - -class cache_progress: - # The default is 1 GB cache and 12 hours half life - def __init__(self, path = None, limit = 1073741824, half_life = 43200): - global node_pruning - self.path = path - self.limit = limit - self.exponent_scale = math.log(2) / half_life - if env['verbose'] and path != None: - screen.write('Current cache limit is ' + self.convert_size(limit) + ' (used: ' + self.convert_size(self.get_size(path)) + ')\n') - self.pruning = node_pruning - self.delete(self.file_list()) - - def __call__(self, node, *args, **kw): - global node_count, node_count_max, node_count_interval, node_count_fname, node_pruning, show_progress - if show_progress: - # Print the progress percentage - node_count += node_count_interval - if (node_count_max > 0 and node_count <= node_count_max): - screen.write('\r[%3d%%] ' % (node_count * 100 / node_count_max)) - screen.flush() - elif (node_count_max > 0 and node_count > node_count_max): - screen.write('\r[100%] ') - screen.flush() - else: - screen.write('\r[Initial build] ') - screen.flush() - # Prune if the number of nodes processed is 'node_pruning' or bigger - self.pruning -= node_count_interval - if self.pruning <= 0: - self.pruning = node_pruning + + import time, math + + class cache_progress: + # The default is 1 GB cache and 12 hours half life + def __init__(self, path = None, limit = 1073741824, half_life = 43200): + self.path = path + self.limit = limit + self.exponent_scale = math.log(2) / half_life + if env['verbose'] and path != None: + screen.write('Current cache limit is ' + self.convert_size(limit) + ' (used: ' + self.convert_size(self.get_size(path)) + ')\n') self.delete(self.file_list()) - def delete(self, files): - if len(files) == 0: - return - if env['verbose']: - # Utter something - screen.write('\rPurging %d %s from cache...\n' % (len(files), len(files) > 1 and 'files' or 'file')) - map(os.remove, files) - - def file_list(self): - if self.path == None: - # Nothing to do - return [] - # Gather a list of (filename, (size, atime)) within the - # cache directory - file_stat = [(x, os.stat(x)[6:8]) for x in glob.glob(os.path.join(self.path, '*', '*'))] - if file_stat == []: - # Nothing to do - return [] - # Weight the cache files by size (assumed to be roughly - # proportional to the recompilation time) times an exponential - # decay since the ctime, and return a list with the entries - # (filename, size, weight). - current_time = time.time() - file_stat = [(x[0], x[1][0], (current_time - x[1][1])) for x in file_stat] - # Sort by the most resently accessed files (most sensible to keep) first - file_stat.sort(key=lambda x: x[2]) - # Search for the first entry where the storage limit is - # reached - sum, mark = 0, None - for i,x in enumerate(file_stat): - sum += x[1] - if sum > self.limit: - mark = i - break - if mark == None: - return [] - else: - return [x[0] for x in file_stat[mark:]] - - def convert_size(self, size_bytes): - if size_bytes == 0: - return "0 bytes" - size_name = ("bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") - i = int(math.floor(math.log(size_bytes, 1024))) - p = math.pow(1024, i) - s = round(size_bytes / p, 2) - return "%s %s" % (int(s) if i == 0 else s, size_name[i]) - - def get_size(self, start_path = '.'): - total_size = 0 - for dirpath, dirnames, filenames in os.walk(start_path): - for f in filenames: - fp = os.path.join(dirpath, f) - total_size += os.path.getsize(fp) - return total_size - -def progress_finish(target, source, env): - global node_count, progressor - with open(node_count_fname, 'w') as f: - f.write('%d\n' % node_count) - progressor.delete(progressor.file_list()) - -try: - with open(node_count_fname) as f: - node_count_max = int(f.readline()) -except: - pass -cache_directory = os.environ.get("SCONS_CACHE") -# Simple cache pruning, attached to SCons' progress callback. Trim the -# cache directory to a size not larger than cache_limit. -cache_limit = float(os.getenv("SCONS_CACHE_LIMIT", 1024)) * 1024 * 1024 -progressor = cache_progress(cache_directory, cache_limit) -Progress(progressor, interval = node_count_interval) - -progress_finish_command = Command('progress_finish', [], progress_finish) -AlwaysBuild(progress_finish_command) + def __call__(self, node, *args, **kw): + global node_count, node_count_max, node_count_interval, node_count_fname, show_progress + if show_progress: + # Print the progress percentage + node_count += node_count_interval + if (node_count_max > 0 and node_count <= node_count_max): + screen.write('\r[%3d%%] ' % (node_count * 100 / node_count_max)) + screen.flush() + elif (node_count_max > 0 and node_count > node_count_max): + screen.write('\r[100%] ') + screen.flush() + else: + screen.write('\r[Initial build] ') + screen.flush() + + def delete(self, files): + if len(files) == 0: + return + if env['verbose']: + # Utter something + screen.write('\rPurging %d %s from cache...\n' % (len(files), len(files) > 1 and 'files' or 'file')) + [os.remove(f) for f in files] + + def file_list(self): + if self.path == None: + # Nothing to do + return [] + # Gather a list of (filename, (size, atime)) within the + # cache directory + file_stat = [(x, os.stat(x)[6:8]) for x in glob.glob(os.path.join(self.path, '*', '*'))] + if file_stat == []: + # Nothing to do + return [] + # Weight the cache files by size (assumed to be roughly + # proportional to the recompilation time) times an exponential + # decay since the ctime, and return a list with the entries + # (filename, size, weight). + current_time = time.time() + file_stat = [(x[0], x[1][0], (current_time - x[1][1])) for x in file_stat] + # Sort by the most resently accessed files (most sensible to keep) first + file_stat.sort(key=lambda x: x[2]) + # Search for the first entry where the storage limit is + # reached + sum, mark = 0, None + for i,x in enumerate(file_stat): + sum += x[1] + if sum > self.limit: + mark = i + break + if mark == None: + return [] + else: + return [x[0] for x in file_stat[mark:]] + + def convert_size(self, size_bytes): + if size_bytes == 0: + return "0 bytes" + size_name = ("bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") + i = int(math.floor(math.log(size_bytes, 1024))) + p = math.pow(1024, i) + s = round(size_bytes / p, 2) + return "%s %s" % (int(s) if i == 0 else s, size_name[i]) + + def get_size(self, start_path = '.'): + total_size = 0 + for dirpath, dirnames, filenames in os.walk(start_path): + for f in filenames: + fp = os.path.join(dirpath, f) + total_size += os.path.getsize(fp) + return total_size + + def progress_finish(target, source, env): + global node_count, progressor + with open(node_count_fname, 'w') as f: + f.write('%d\n' % node_count) + progressor.delete(progressor.file_list()) + + try: + with open(node_count_fname) as f: + node_count_max = int(f.readline()) + except: + pass + + cache_directory = os.environ.get("SCONS_CACHE") + # Simple cache pruning, attached to SCons' progress callback. Trim the + # cache directory to a size not larger than cache_limit. + cache_limit = float(os.getenv("SCONS_CACHE_LIMIT", 1024)) * 1024 * 1024 + progressor = cache_progress(cache_directory, cache_limit) + Progress(progressor, interval = node_count_interval) + + progress_finish_command = Command('progress_finish', [], progress_finish) + AlwaysBuild(progress_finish_command) diff --git a/core/SCsub b/core/SCsub index 1545bc8aeb..383aaf0e12 100644 --- a/core/SCsub +++ b/core/SCsub @@ -18,9 +18,8 @@ gd_cpp = '#include "project_settings.h"\n' gd_cpp += gd_inc gd_cpp += "void ProjectSettings::register_global_defaults() {\n" + gd_call + "\n}\n" -f = open("global_defaults.gen.cpp", "w") -f.write(gd_cpp) -f.close() +with open("global_defaults.gen.cpp", "w") as f: + f.write(gd_cpp) # Generate AES256 script encryption key @@ -47,9 +46,8 @@ if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ): txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0" print("Invalid AES256 encryption key, not 64 bits hex: " + e) -f = open("script_encryption_key.gen.cpp", "w") -f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n") -f.close() +with open("script_encryption_key.gen.cpp", "w") as f: + f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n") # Add required thirdparty code. Header paths are hardcoded, we don't need to append diff --git a/core/array.cpp b/core/array.cpp index c53fea1f28..0ddac1662c 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -266,6 +266,20 @@ Array &Array::sort_custom(Object *p_obj, const StringName &p_function) { return *this; } +void Array::shuffle() { + + const int n = _p->array.size(); + if (n < 2) + return; + Variant *data = _p->array.ptrw(); + for (int i = n - 1; i >= 1; i--) { + const int j = Math::rand() % (i + 1); + const Variant tmp = data[j]; + data[j] = data[i]; + data[i] = tmp; + } +} + template <typename Less> _FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) { diff --git a/core/array.h b/core/array.h index 7c6fc59048..684a8e265d 100644 --- a/core/array.h +++ b/core/array.h @@ -71,6 +71,7 @@ public: Array &sort(); Array &sort_custom(Object *p_obj, const StringName &p_function); + void shuffle(); int bsearch(const Variant &p_value, bool p_before = true); int bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before = true); Array &invert(); diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index b57b24ee7d..20adf7ff02 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -205,6 +205,22 @@ String _OS::get_clipboard() const { return OS::get_singleton()->get_clipboard(); } +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); +} + +int _OS::get_audio_driver_count() const { + return OS::get_singleton()->get_audio_driver_count(); +} + +String _OS::get_audio_driver_name(int p_driver) const { + return OS::get_singleton()->get_audio_driver_name(p_driver); +} + void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) { OS::VideoMode vm; @@ -1015,6 +1031,11 @@ void _OS::_bind_methods() { //ClassDB::bind_method(D_METHOD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0)); //ClassDB::bind_method(D_METHOD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0)); + ClassDB::bind_method(D_METHOD("get_video_driver_count"), &_OS::get_video_driver_count); + ClassDB::bind_method(D_METHOD("get_video_driver_name"), &_OS::get_video_driver_name); + ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count); + ClassDB::bind_method(D_METHOD("get_audio_driver_name"), &_OS::get_audio_driver_name); + ClassDB::bind_method(D_METHOD("get_screen_count"), &_OS::get_screen_count); ClassDB::bind_method(D_METHOD("get_current_screen"), &_OS::get_current_screen); ClassDB::bind_method(D_METHOD("set_current_screen", "screen"), &_OS::set_current_screen); @@ -1514,6 +1535,17 @@ bool _File::is_open() const { return f != NULL; } +String _File::get_path() const { + + ERR_FAIL_COND_V(!f, ""); + return f->get_path(); +} + +String _File::get_path_absolute() const { + + ERR_FAIL_COND_V(!f, ""); + return f->get_path_absolute(); +} void _File::seek(int64_t p_position) { @@ -1803,6 +1835,8 @@ void _File::_bind_methods() { ClassDB::bind_method(D_METHOD("open", "path", "flags"), &_File::open); ClassDB::bind_method(D_METHOD("close"), &_File::close); + ClassDB::bind_method(D_METHOD("get_path"), &_File::get_path); + ClassDB::bind_method(D_METHOD("get_path_absolute"), &_File::get_path_absolute); ClassDB::bind_method(D_METHOD("is_open"), &_File::is_open); ClassDB::bind_method(D_METHOD("seek", "position"), &_File::seek); ClassDB::bind_method(D_METHOD("seek_end", "position"), &_File::seek_end, DEFVAL(0)); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 734b57937a..c40abd51f6 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -146,6 +146,12 @@ public: bool is_video_mode_resizable(int p_screen = 0) const; 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 int get_audio_driver_count() const; + virtual String get_audio_driver_name(int p_driver) const; + virtual int get_screen_count() const; virtual int get_current_screen() const; virtual void set_current_screen(int p_screen); @@ -409,6 +415,9 @@ public: void close(); ///< close a file bool is_open() const; ///< true when file is open + String get_path() const; /// returns the path for the current open file + String get_path_absolute() const; /// returns the absolute path for the current open file + void seek(int64_t p_position); ///< seek to a given position void seek_end(int64_t p_position = 0); ///< seek from the end of file int64_t get_position() const; ///< get position in the file diff --git a/core/class_db.cpp b/core/class_db.cpp index afcc8de0f2..291dc87e1c 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -33,18 +33,9 @@ #include "os/mutex.h" #include "version.h" -#ifdef NO_THREADS - -#define OBJTYPE_RLOCK -#define OBJTYPE_WLOCK - -#else - #define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock); #define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock); -#endif - #ifdef DEBUG_METHODS_ENABLED MethodDefinition D_METHOD(const char *p_name) { @@ -347,7 +338,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { OBJTYPE_RLOCK; #ifdef DEBUG_METHODS_ENABLED - uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_NAME)); + uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG)); List<StringName> names; @@ -895,15 +886,9 @@ void ClassDB::add_property_group(StringName p_class, const String &p_name, const void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) { -#ifndef NO_THREADS lock->read_lock(); -#endif - ClassInfo *type = classes.getptr(p_class); - -#ifndef NO_THREADS lock->read_unlock(); -#endif ERR_FAIL_COND(!type); @@ -1380,10 +1365,7 @@ RWLock *ClassDB::lock = NULL; void ClassDB::init() { -#ifndef NO_THREADS - lock = RWLock::create(); -#endif } void ClassDB::cleanup() { @@ -1406,10 +1388,7 @@ void ClassDB::cleanup() { resource_base_extensions.clear(); compat_classes.clear(); -#ifndef NO_THREADS - memdelete(lock); -#endif } // diff --git a/core/color.cpp b/core/color.cpp index a0568d26ed..b2f5889166 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -400,6 +400,59 @@ String Color::to_html(bool p_alpha) const { return txt; } +Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) { + + p_h = Math::fmod(p_h * 360.0f, 360.0f); + if (p_h < 0.0) + p_h += 360.0f; + + const float h_ = p_h / 60.0f; + const float c = p_v * p_s; + const float x = c * (1.0f - Math::abs(Math::fmod(h_, 2.0f) - 1.0f)); + float r, g, b; + + switch ((int)h_) { + case 0: { + r = c; + g = x; + b = 0; + } break; + case 1: { + r = x; + g = c; + b = 0; + } break; + case 2: { + r = 0; + g = c; + b = x; + } break; + case 3: { + r = 0; + g = x; + b = c; + } break; + case 4: { + r = x; + g = 0; + b = c; + } break; + case 5: { + r = c; + g = 0; + b = x; + } break; + default: { + r = 0; + g = 0; + b = 0; + } break; + } + + const float m = p_v - c; + return Color(m + r, m + g, m + b, p_a); +} + float Color::gray() const { return (r + g + b) / 3.0; diff --git a/core/color.h b/core/color.h index 9af8fb0a78..a2015a34d6 100644 --- a/core/color.h +++ b/core/color.h @@ -190,6 +190,7 @@ struct Color { static bool html_is_valid(const String &p_color); static Color named(const String &p_name); String to_html(bool p_alpha = true) const; + Color from_hsv(float p_h, float p_s, float p_v, float p_a); _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys operator String() const; diff --git a/core/command_queue_mt.cpp b/core/command_queue_mt.cpp index 6bb3135757..a39c920dfa 100644 --- a/core/command_queue_mt.cpp +++ b/core/command_queue_mt.cpp @@ -105,6 +105,7 @@ CommandQueueMT::CommandQueueMT(bool p_sync) { read_ptr = 0; write_ptr = 0; + dealloc_ptr = 0; mutex = Mutex::create(); for (int i = 0; i < SYNC_SEMAPHORES; i++) { diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h index cecc9e405d..3942b961d3 100644 --- a/core/command_queue_mt.h +++ b/core/command_queue_mt.h @@ -55,7 +55,7 @@ #define _COMMA_11 , #define _COMMA_12 , -// 1-based comma separed list of ITEMs +// 1-based comma separated list of ITEMs #define COMMA_SEP_LIST(ITEM, LENGTH) _COMMA_SEP_LIST_##LENGTH(ITEM) #define _COMMA_SEP_LIST_12(ITEM) \ _COMMA_SEP_LIST_11(ITEM) \ @@ -95,7 +95,7 @@ ITEM(1) #define _COMMA_SEP_LIST_0(ITEM) -// 1-based semicolon separed list of ITEMs +// 1-based semicolon separated list of ITEMs #define SEMIC_SEP_LIST(ITEM, LENGTH) _SEMIC_SEP_LIST_##LENGTH(ITEM) #define _SEMIC_SEP_LIST_12(ITEM) \ _SEMIC_SEP_LIST_11(ITEM); \ @@ -135,7 +135,7 @@ ITEM(1) #define _SEMIC_SEP_LIST_0(ITEM) -// 1-based space separed list of ITEMs +// 1-based space separated list of ITEMs #define SPACE_SEP_LIST(ITEM, LENGTH) _SPACE_SEP_LIST_##LENGTH(ITEM) #define _SPACE_SEP_LIST_12(ITEM) \ _SPACE_SEP_LIST_11(ITEM) \ diff --git a/core/compressed_translation.h b/core/compressed_translation.h index 400fa4491b..ccc47d0bf6 100644 --- a/core/compressed_translation.h +++ b/core/compressed_translation.h @@ -38,7 +38,7 @@ class PHashTranslation : public Translation { GDCLASS(PHashTranslation, Translation); //this translation uses a sort of modified perfect hash algorithm - //it requieres hashing strings twice and then does a binary search, + //it requires hashing strings twice and then does a binary search, //so it's slower, but at the same time it has an extreemly high chance //of catching untranslated strings diff --git a/core/error_macros.h b/core/error_macros.h index 1f9164a99b..b8d0c7e0c3 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -33,7 +33,7 @@ #include "typedefs.h" /** - * Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability + * Error macros. Unlike exceptions and asserts, these macros try to maintain consistency and stability * inside the code. It is recommended to always return processable data, so in case of an error, the * engine can stay working well. * In most cases, bugs and/or invalid data are not fatal and should never allow a perfectly running application diff --git a/core/global_constants.cpp b/core/global_constants.cpp index a24bf03c9a..04810afe73 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -580,7 +580,7 @@ void register_global_constants() { BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR_ARRAY", Variant::POOL_COLOR_ARRAY); BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX); - //comparation + //comparison BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_EQUAL", Variant::OP_EQUAL); BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_NOT_EQUAL", Variant::OP_NOT_EQUAL); BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_LESS", Variant::OP_LESS); diff --git a/core/input_map.cpp b/core/input_map.cpp index a9ea1d9545..bd03d61196 100644 --- a/core/input_map.cpp +++ b/core/input_map.cpp @@ -282,6 +282,16 @@ void InputMap::load_default() { key->set_scancode(KEY_PAGEDOWN); action_add_event("ui_page_down", key); + add_action("ui_home"); + key.instance(); + key->set_scancode(KEY_HOME); + action_add_event("ui_home", key); + + add_action("ui_end"); + key.instance(); + key->set_scancode(KEY_END); + action_add_event("ui_end", key); + //set("display/window/handheld/orientation", "landscape"); } diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 1a16d0f61c..efb4c7a073 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -88,7 +88,11 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o } } } - cd->files.insert(path.get_file()); + String filename = path.get_file(); + // Don't add as a file if the path points to a directoryy + if (!filename.empty()) { + cd->files.insert(filename); + } } } diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index a9eb9466b7..4d72f744e1 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -298,7 +298,7 @@ Error HTTPClient::poll() { case StreamPeerTCP::STATUS_CONNECTED: { if (ssl) { Ref<StreamPeerSSL> ssl = StreamPeerSSL::create(); - Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, ssl_verify_host ? conn_host : String()); + Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, conn_host); if (err != OK) { close(); status = STATUS_SSL_HANDSHAKE_ERROR; diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 7261363ad6..6d979d10eb 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -211,7 +211,7 @@ IP_Address::IP_Address(const String &p_string) { clear(); if (p_string == "*") { - // Wildcard (not a vaild IP) + // Wildcard (not a valid IP) wildcard = true; } else if (p_string.find(":") >= 0) { diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 9e21287780..2ebe8d6df7 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -813,7 +813,7 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) { while (r_len % 4) { r_len++; //pad if (buf) { - buf++; + *(buf++) = 0; } } } diff --git a/core/make_binders.py b/core/make_binders.py index 1e581f8ce3..6a7602cd5d 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -265,10 +265,8 @@ def run(target, source, env): else: text += t - f = open(target[0].path, "w") - f.write(text) - f.close() + with open(target[0].path, "w") as f: + f.write(text) - f = open(target[1].path, "w") - f.write(text_ext) - f.close() + with open(target[1].path, "w") as f: + f.write(text_ext) diff --git a/core/map.h b/core/map.h index 5ff269c26b..700d4b8693 100644 --- a/core/map.h +++ b/core/map.h @@ -197,7 +197,7 @@ private: if (node->right != _data._nil) { node = node->right; - while (node->left != _data._nil) { /* returns the minium of the right subtree of node */ + while (node->left != _data._nil) { /* returns the minimum of the right subtree of node */ node = node->left; } return node; @@ -219,7 +219,7 @@ private: if (node->left != _data._nil) { node = node->left; - while (node->right != _data._nil) { /* returns the minium of the left subtree of node */ + while (node->right != _data._nil) { /* returns the minimum of the left subtree of node */ node = node->right; } return node; diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp index d2e4101999..3767d298a1 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -98,11 +98,6 @@ real_t Vector2::cross(const Vector2 &p_other) const { return x * p_other.y - y * p_other.x; } -Vector2 Vector2::cross(real_t p_other) const { - - return Vector2(p_other * y, -p_other * x); -} - Vector2 Vector2::floor() const { return Vector2(Math::floor(x), Math::floor(y)); diff --git a/core/math/math_2d.h b/core/math/math_2d.h index 8928349a44..e7188da85b 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -104,7 +104,6 @@ struct Vector2 { real_t dot(const Vector2 &p_other) const; real_t cross(const Vector2 &p_other) const; - Vector2 cross(real_t p_other) const; Vector2 project(const Vector2 &p_vec) const; Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const; @@ -304,7 +303,7 @@ struct Rect2 { inline real_t distance_to(const Vector2 &p_point) const { - real_t dist; + real_t dist = 0.0; bool inside = true; if (p_point.x < position.x) { diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index f060a8e4ab..5c8512d8bd 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -177,18 +177,3 @@ float Math::random(float from, float to) { float ret = (float)r / (float)RANDOM_MAX; return (ret) * (to - from) + from; } - -int Math::wrapi(int value, int min, int max) { - --max; - int rng = max - min + 1; - value = ((value - min) % rng); - if (value < 0) - return max + 1 + value; - else - return min + value; -} - -float Math::wrapf(float value, float min, float max) { - float rng = max - min; - return min + (value - min) - (rng * floor((value - min) / rng)); -} diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index e15abc6b50..26e87f009b 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -209,8 +209,18 @@ public: static _ALWAYS_INLINE_ double round(double p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); } static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); } - static int wrapi(int value, int min, int max); - static float wrapf(float value, float min, float max); + static _ALWAYS_INLINE_ int wrapi(int value, int min, int max) { + int rng = max - min; + return min + ((((value - min) % rng) + rng) % rng); + } + static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) { + double rng = max - min; + return min + (value - min) - (rng * Math::floor((value - min) / rng)); + } + static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) { + float rng = max - min; + return min + (value - min) - (rng * Math::floor((value - min) / rng)); + } // double only, as these functions are mainly used by the editor and not performance-critical, static double ease(double p_x, double p_c); diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp index 5bae74ac7e..563ba7268f 100644 --- a/core/math/triangulate.cpp +++ b/core/math/triangulate.cpp @@ -51,7 +51,8 @@ real_t Triangulate::get_area(const Vector<Vector2> &contour) { bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay, real_t Bx, real_t By, real_t Cx, real_t Cy, - real_t Px, real_t Py) + real_t Px, real_t Py, + bool include_edges) { real_t ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; @@ -74,10 +75,14 @@ bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay, cCROSSap = cx * apy - cy * apx; bCROSScp = bx * cpy - by * cpx; - return ((aCROSSbp > 0.0) && (bCROSScp > 0.0) && (cCROSSap > 0.0)); + if (include_edges) { + return ((aCROSSbp > 0.0) && (bCROSScp > 0.0) && (cCROSSap > 0.0)); + } else { + return ((aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0)); + } }; -bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V) { +bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V, bool relaxed) { int p; real_t Ax, Ay, Bx, By, Cx, Cy, Px, Py; const Vector2 *contour = &p_contour[0]; @@ -91,13 +96,20 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in Cx = contour[V[w]].x; Cy = contour[V[w]].y; - if (CMP_EPSILON > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) return false; + // It can happen that the triangulation ends up with three aligned vertices to deal with. + // In this scenario, making the check below strict may reject the possibility of + // forming a last triangle with these aligned vertices, preventing the triangulatiom + // from completing. + // To avoid that we allow zero-area triangles if all else failed. + float threshold = relaxed ? -CMP_EPSILON : CMP_EPSILON; + + if (threshold > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) return false; for (p = 0; p < n; p++) { if ((p == u) || (p == v) || (p == w)) continue; Px = contour[V[p]].x; Py = contour[V[p]].y; - if (is_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) return false; + if (is_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py, relaxed)) return false; } return true; @@ -121,6 +133,8 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul for (int v = 0; v < n; v++) V[v] = (n - 1) - v; + bool relaxed = false; + int nv = n; /* remove nv-2 Vertices, creating 1 triangle every time */ @@ -129,8 +143,20 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul for (int v = nv - 1; nv > 2;) { /* if we loop, it is probably a non-simple polygon */ if (0 >= (count--)) { - //** Triangulate: ERROR - probable bad polygon! - return false; + if (relaxed) { + //** Triangulate: ERROR - probable bad polygon! + return false; + } else { + // There may be aligned vertices that the strict + // checks prevent from triangulating. In this situation + // we are better off adding flat triangles than + // failing, so we relax the checks and try one last + // round. + // Only relaxing the constraints as a last resort avoids + // degenerate triangles when they aren't necessary. + count = 2 * nv; + relaxed = true; + } } /* three consecutive vertices in current polygon, <u,v,w> */ @@ -141,7 +167,7 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul int w = v + 1; if (nv <= w) w = 0; /* next */ - if (snip(contour, u, v, w, nv, V)) { + if (snip(contour, u, v, w, nv, V, relaxed)) { int a, b, c, s, t; /* true names of the vertices */ diff --git a/core/math/triangulate.h b/core/math/triangulate.h index e336dc5756..b1a583d0c5 100644 --- a/core/math/triangulate.h +++ b/core/math/triangulate.h @@ -51,10 +51,11 @@ public: static bool is_inside_triangle(real_t Ax, real_t Ay, real_t Bx, real_t By, real_t Cx, real_t Cy, - real_t Px, real_t Py); + real_t Px, real_t Py, + bool include_edges); private: - static bool snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V); + static bool snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V, bool relaxed); }; #endif diff --git a/core/message_queue.cpp b/core/message_queue.cpp index 3ceafe1a30..25ee6eafae 100644 --- a/core/message_queue.cpp +++ b/core/message_queue.cpp @@ -278,7 +278,7 @@ void MessageQueue::flush() { while (read_pos < buffer_end) { - //lock on each interation, so a call can re-add itself to the message queue + //lock on each iteration, so a call can re-add itself to the message queue Message *message = (Message *)&buffer[read_pos]; diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index 1941b82602..330a9153ef 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -301,8 +301,8 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err); if (err) { - - ERR_FAIL_COND_V(err, err); + ERR_PRINTS("Failed to open " + p_from); + return err; } FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); @@ -310,7 +310,8 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { fsrc->close(); memdelete(fsrc); - ERR_FAIL_COND_V(err, err); + ERR_PRINTS("Failed to open " + p_to); + return err; } fsrc->seek_end(0); diff --git a/core/os/file_access.h b/core/os/file_access.h index 5d10c1a9aa..c4635fdfbb 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -89,6 +89,9 @@ public: virtual void close() = 0; ///< close a file virtual bool is_open() const = 0; ///< true when file is open + virtual String get_path() const { return ""; } /// returns the path for the current open file + virtual String get_path_absolute() const { return ""; } /// returns the absolute path for the current open file + virtual void seek(size_t p_position) = 0; ///< seek to a given position virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file virtual size_t get_position() const = 0; ///< get position in the file diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index 12060f31df..b9607632f7 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -962,6 +962,11 @@ Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, return ev; } +String InputEventMagnifyGesture::as_text() const { + + return "InputEventMagnifyGesture : factor=" + rtos(get_factor()) + ", position=(" + String(get_position()) + ")"; +} + void InputEventMagnifyGesture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_factor", "factor"), &InputEventMagnifyGesture::set_factor); @@ -999,6 +1004,11 @@ Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, con return ev; } +String InputEventPanGesture::as_text() const { + + return "InputEventPanGesture : delta=(" + String(get_delta()) + "), position=(" + String(get_position()) + ")"; +} + void InputEventPanGesture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_delta", "delta"), &InputEventPanGesture::set_delta); diff --git a/core/os/input_event.h b/core/os/input_event.h index ad754d0d1f..0a33ab18a7 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -494,6 +494,7 @@ public: real_t get_factor() const; virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; + virtual String as_text() const; InputEventMagnifyGesture(); }; @@ -511,6 +512,7 @@ public: Vector2 get_delta() const; virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; + virtual String as_text() const; InputEventPanGesture(); }; diff --git a/core/os/os.cpp b/core/os/os.cpp index 422acf95dc..618a4bbac3 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -34,6 +34,7 @@ #include "input.h" #include "os/file_access.h" #include "project_settings.h" +#include "servers/audio_server.h" #include "version_generated.gen.h" #include <stdarg.h> @@ -627,6 +628,34 @@ void OS::center_window() { set_window_position(Vector2(x, y)); } +int OS::get_video_driver_count() const { + + return 2; +} + +const char *OS::get_video_driver_name(int p_driver) const { + + switch (p_driver) { + case VIDEO_DRIVER_GLES2: + return "GLES2"; + case VIDEO_DRIVER_GLES3: + default: + return "GLES3"; + } +} + +int OS::get_audio_driver_count() const { + + return AudioDriverManager::get_driver_count(); +} + +const char *OS::get_audio_driver_name(int p_driver) const { + + AudioDriver *driver = AudioDriverManager::get_driver(p_driver); + ERR_FAIL_COND_V(!driver, ""); + return AudioDriverManager::get_driver(p_driver)->get_name(); +} + OS::OS() { void *volatile stack_bottom; diff --git a/core/os/os.h b/core/os/os.h index 38e55fa3b7..5a2c998782 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -44,6 +44,12 @@ @author Juan Linietsky <reduzio@gmail.com> */ +enum VideoDriver { + VIDEO_DRIVER_GLES3, + VIDEO_DRIVER_GLES2, + VIDEO_DRIVER_MAX, +}; + class OS { static OS *singleton; @@ -115,12 +121,6 @@ protected: RenderThreadMode _render_thread_mode; // functions used by main to initialize/deintialize the OS - virtual int get_video_driver_count() const = 0; - virtual const char *get_video_driver_name(int p_driver) const = 0; - - virtual int get_audio_driver_count() const = 0; - virtual const char *get_audio_driver_name(int p_driver) const = 0; - void add_logger(Logger *p_logger); virtual void initialize_core() = 0; @@ -175,6 +175,12 @@ 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; + virtual int get_video_driver_count() const; + virtual const char *get_video_driver_name(int p_driver) const; + + virtual int get_audio_driver_count() const; + virtual const char *get_audio_driver_name(int p_driver) const; + virtual int get_screen_count() const { return 1; } virtual int get_current_screen() const { return 0; } virtual void set_current_screen(int p_screen) {} diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp index fa0bb3dafd..b6371235c4 100644 --- a/core/os/thread_dummy.cpp +++ b/core/os/thread_dummy.cpp @@ -55,3 +55,11 @@ Semaphore *SemaphoreDummy::create() { void SemaphoreDummy::make_default() { Semaphore::create_func = &SemaphoreDummy::create; }; + +RWLock *RWLockDummy::create() { + return memnew(RWLockDummy); +}; + +void RWLockDummy::make_default() { + RWLock::create_func = &RWLockDummy::create; +}; diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h index b67b52a726..74957b95fe 100644 --- a/core/os/thread_dummy.h +++ b/core/os/thread_dummy.h @@ -32,6 +32,7 @@ #define THREAD_DUMMY_H #include "mutex.h" +#include "rw_lock.h" #include "semaphore.h" #include "thread.h" @@ -69,4 +70,20 @@ public: static void make_default(); }; +class RWLockDummy : public RWLock { + + static RWLock *create(); + +public: + virtual void read_lock() {} + virtual void read_unlock() {} + virtual Error read_try_lock() { return OK; } + + virtual void write_lock() {} + virtual void write_unlock() {} + virtual Error write_try_lock() { return OK; } + + static void make_default(); +}; + #endif diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp index d81e1912bf..017586b92a 100644 --- a/core/pool_allocator.cpp +++ b/core/pool_allocator.cpp @@ -90,7 +90,7 @@ bool PoolAllocator::find_hole(EntryArrayPos *p_pos, int p_for_size) { int hole_size = entry.pos - prev_entry_end_pos; - /* detemine if what we want fits in that hole */ + /* determine if what we want fits in that hole */ if (hole_size >= p_for_size) { *p_pos = i; return true; @@ -100,7 +100,7 @@ bool PoolAllocator::find_hole(EntryArrayPos *p_pos, int p_for_size) { prev_entry_end_pos = entry_end(entry); } - /* No holes between entrys, check at the end..*/ + /* No holes between entries, check at the end..*/ if ((pool_size - prev_entry_end_pos) >= p_for_size) { *p_pos = entry_count; diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 0991c0df68..20d91e7940 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -268,12 +268,12 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo if (FileAccessNetworkClient::get_singleton()) { - if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) { - - _load_settings("res://override.cfg"); + Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); + if (err == OK) { + // Optional, we don't mind if it fails + _load_settings_text("res://override.cfg"); } - - return OK; + return err; } String exec_path = OS::get_singleton()->get_executable_path(); @@ -285,12 +285,13 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo bool ok = _load_resource_pack(p_main_pack); ERR_FAIL_COND_V(!ok, ERR_CANT_OPEN); - if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) { - //load override from location of the main pack - _load_settings(p_main_pack.get_base_dir().plus_file("override.cfg")); + Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); + if (err == OK) { + // Load override from location of the main pack + // Optional, we don't mind if it fails + _load_settings_text(p_main_pack.get_base_dir().plus_file("override.cfg")); } - - return OK; + return err; } //Attempt with execname.pck @@ -313,12 +314,13 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo // if we opened our package, try and load our project... if (found) { - if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) { - // load override from location of executable - _load_settings(exec_path.get_base_dir().plus_file("override.cfg")); + Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); + if (err == OK) { + // Load override from location of executable + // Optional, we don't mind if it fails + _load_settings_text(exec_path.get_base_dir().plus_file("override.cfg")); } - - return OK; + return err; } } @@ -334,11 +336,13 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo // data.pck and data.zip are deprecated and no longer supported, apologies. // make sure this is loaded from the resource path - if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) { - _load_settings("res://override.cfg"); + Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); + if (err == OK) { + // Optional, we don't mind if it fails + _load_settings_text("res://override.cfg"); } - return OK; + return err; } //Nothing was found, try to find a project.godot somewhere! @@ -350,20 +354,23 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo String candidate = d->get_current_dir(); String current_dir = d->get_current_dir(); + bool found = false; + Error err; while (true) { - //try to load settings in ascending through dirs shape! - if (_load_settings(current_dir + "/project.godot") == OK || _load_settings_binary(current_dir + "/project.binary") == OK) { - - _load_settings(current_dir + "/override.cfg"); + err = _load_settings_text_or_binary(current_dir.plus_file("project.godot"), current_dir.plus_file("project.binary")); + if (err == OK) { + // Optional, we don't mind if it fails + _load_settings_text(current_dir.plus_file("override.cfg")); candidate = current_dir; found = true; break; } if (p_upwards) { + // Try to load settings ascending through dirs shape! d->change_dir(".."); if (d->get_current_dir() == current_dir) break; //not doing anything useful @@ -378,7 +385,7 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo memdelete(d); if (!found) - return ERR_FILE_NOT_FOUND; + return err; if (resource_path.length() && resource_path[resource_path.length() - 1] == '/') resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end @@ -440,13 +447,17 @@ Error ProjectSettings::_load_settings_binary(const String p_path) { return OK; } -Error ProjectSettings::_load_settings(const String p_path) { + +Error ProjectSettings::_load_settings_text(const String p_path) { Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - if (!f) - return ERR_CANT_OPEN; + if (!f) { + // FIXME: Above 'err' error code is ERR_FILE_CANT_OPEN if the file is missing + // This needs to be streamlined if we want decent error reporting + return ERR_FILE_NOT_FOUND; + } VariantParser::StreamFile stream; stream.f = f; @@ -471,7 +482,7 @@ Error ProjectSettings::_load_settings(const String p_path) { memdelete(f); return OK; } else if (err != OK) { - ERR_PRINTS("ProjectSettings::load - " + p_path + ":" + itos(lines) + " error: " + error_text); + ERR_PRINTS("Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted."); memdelete(f); return err; } @@ -497,6 +508,23 @@ Error ProjectSettings::_load_settings(const String p_path) { return OK; } +Error ProjectSettings::_load_settings_text_or_binary(const String p_text_path, const String p_bin_path) { + + // Attempt first to load the text-based project.godot file + Error err_text = _load_settings_text(p_text_path); + if (err_text == OK) { + return OK; + } else if (err_text != ERR_FILE_NOT_FOUND) { + // If the text-based file exists but can't be loaded, we want to know it + ERR_PRINTS("Couldn't load file '" + p_text_path + "', error code " + itos(err_text) + "."); + return err_text; + } + + // Fallback to binary project.binary file if text-based was not found + Error err_bin = _load_settings_binary(p_bin_path); + return err_bin; +} + int ProjectSettings::get_order(const String &p_name) const { ERR_FAIL_COND_V(!props.has(p_name), -1); @@ -525,7 +553,7 @@ void ProjectSettings::clear(const String &p_name) { Error ProjectSettings::save() { - return save_custom(get_resource_path() + "/project.godot"); + return save_custom(get_resource_path().plus_file("project.godot")); } Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom, const String &p_custom_features) { @@ -664,7 +692,10 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin String vstr; VariantWriter::write_to_string(value, vstr); - file->store_string(F->get() + "=" + vstr + "\n"); + if (F->get().find(" ") != -1) + file->store_string(F->get().quote() + "=" + vstr + "\n"); + else + file->store_string(F->get() + "=" + vstr + "\n"); } } @@ -999,6 +1030,20 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("input/ui_page_down", va); input_presets.push_back("input/ui_page_down"); + va = Array(); + key.instance(); + key->set_scancode(KEY_HOME); + va.push_back(key); + GLOBAL_DEF("input/ui_home", va); + input_presets.push_back("input/ui_home"); + + va = Array(); + key.instance(); + key->set_scancode(KEY_END); + va.push_back(key); + GLOBAL_DEF("input/ui_end", va); + input_presets.push_back("input/ui_end"); + //GLOBAL_DEF("display/window/handheld/orientation", "landscape"); custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::STRING, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor"); diff --git a/core/project_settings.h b/core/project_settings.h index eba53441cf..9b51bc3ac3 100644 --- a/core/project_settings.h +++ b/core/project_settings.h @@ -93,8 +93,9 @@ protected: static ProjectSettings *singleton; - Error _load_settings(const String p_path); + Error _load_settings_text(const String p_path); Error _load_settings_binary(const String p_path); + Error _load_settings_text_or_binary(const String p_text_path, const String p_bin_path); Error _save_settings_text(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String()); Error _save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String()); diff --git a/core/reference.h b/core/reference.h index a0bdb62258..0d6b1ced6e 100644 --- a/core/reference.h +++ b/core/reference.h @@ -63,7 +63,7 @@ public: template <class T> class Ref { - T *reference = NULL; + T *reference; void ref(const Ref &p_from) { @@ -213,10 +213,9 @@ public: Ref(T *p_reference) { + reference = NULL; if (p_reference) ref_pointer(p_reference); - else - reference = NULL; } Ref(const Variant &p_variant) { diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 41071ace5d..632285f48d 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -1016,11 +1016,11 @@ void ScriptDebuggerRemote::add_profiling_frame_data(const StringName &p_name, co } void ScriptDebuggerRemote::profiling_start() { - //ignores this, uses it via connnection + //ignores this, uses it via connection } void ScriptDebuggerRemote::profiling_end() { - //ignores this, uses it via connnection + //ignores this, uses it via connection } void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) { diff --git a/core/script_language.h b/core/script_language.h index d1da0a3b72..6d32fc054c 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -203,6 +203,7 @@ public: virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {} virtual bool is_using_templates() { return false; } virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const = 0; + virtual String validate_path(const String &p_path) const { return ""; } virtual Script *create_script() const = 0; virtual bool has_named_classes() const = 0; virtual bool supports_builtin_mode() const = 0; diff --git a/core/set.h b/core/set.h index 4f17c953b1..d79dd81644 100644 --- a/core/set.h +++ b/core/set.h @@ -185,7 +185,7 @@ private: if (node->right != _data._nil) { node = node->right; - while (node->left != _data._nil) { /* returns the minium of the right subtree of node */ + while (node->left != _data._nil) { /* returns the minimum of the right subtree of node */ node = node->left; } return node; @@ -207,7 +207,7 @@ private: if (node->left != _data._nil) { node = node->left; - while (node->right != _data._nil) { /* returns the minium of the left subtree of node */ + while (node->right != _data._nil) { /* returns the minimum of the left subtree of node */ node = node->right; } return node; diff --git a/core/string_buffer.h b/core/string_buffer.h index b148e45544..7e9b151bea 100644 --- a/core/string_buffer.h +++ b/core/string_buffer.h @@ -39,7 +39,7 @@ class StringBuffer { CharType short_buffer[SHORT_BUFFER_SIZE]; String buffer; - int string_length = 0; + int string_length; _FORCE_INLINE_ CharType *current_buffer_ptr() { return static_cast<Vector<CharType> &>(buffer).empty() ? short_buffer : buffer.ptrw(); @@ -79,6 +79,10 @@ public: _FORCE_INLINE_ operator String() { return as_string(); } + + StringBuffer() { + string_length = 0; + } }; template <int SHORT_BUFFER_SIZE> diff --git a/core/string_builder.h b/core/string_builder.h index 9e2599ac32..596b3bf730 100644 --- a/core/string_builder.h +++ b/core/string_builder.h @@ -37,7 +37,7 @@ class StringBuilder { - uint32_t string_length = 0; + uint32_t string_length; Vector<String> strings; Vector<const char *> c_strings; @@ -75,6 +75,10 @@ public: _FORCE_INLINE_ operator String() const { return as_string(); } + + StringBuilder() { + string_length = 0; + } }; #endif // STRING_BUILDER_H diff --git a/core/ustring.cpp b/core/ustring.cpp index d445e4ed47..a7a7810837 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -1135,6 +1135,36 @@ String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { return s; } +String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) { + + uint64_t n = p_num; + + int chars = 0; + do { + n /= base; + chars++; + } while (n); + + String s; + s.resize(chars + 1); + CharType *c = s.ptrw(); + c[chars] = 0; + n = p_num; + do { + int mod = ABS(n % base); + if (mod >= 10) { + char a = (capitalize_hex ? 'A' : 'a'); + c[--chars] = a + (mod - 10); + } else { + c[--chars] = '0' + mod; + } + + n /= base; + } while (n); + + return s; +} + String String::num_real(double p_num) { String s; diff --git a/core/ustring.h b/core/ustring.h index 90496b71b6..bb676ce623 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -146,6 +146,7 @@ public: static String num_scientific(double p_num); static String num_real(double p_num); static String num_int64(int64_t p_num, int base = 10, bool capitalize_hex = false); + static String num_uint64(uint64_t p_num, int base = 10, bool capitalize_hex = false); static String chr(CharType p_char); static String md5(const uint8_t *p_md5); static String hex_encode_buffer(const uint8_t *p_buffer, int p_len); diff --git a/core/variant.cpp b/core/variant.cpp index 2e26169bfe..5d48c8785e 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -1607,6 +1607,8 @@ Variant::operator Vector3() const { if (type == VECTOR3) return *reinterpret_cast<const Vector3 *>(_data._mem); + else if (type == VECTOR2) + return Vector3(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0); else return Vector3(); } diff --git a/core/variant.h b/core/variant.h index 51ee8ea9d1..0a4afada5b 100644 --- a/core/variant.h +++ b/core/variant.h @@ -293,7 +293,7 @@ public: // If this changes the table in variant_op must be updated enum Operator { - //comparation + //comparison OP_EQUAL, OP_NOT_EQUAL, OP_LESS, diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 5607751a27..cda7dccf0c 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -347,7 +347,7 @@ struct _VariantCall { VCALL_LOCALMEM1R(Vector2, bounce); VCALL_LOCALMEM1R(Vector2, reflect); VCALL_LOCALMEM0R(Vector2, angle); - //VCALL_LOCALMEM1R(Vector2,cross); + VCALL_LOCALMEM1R(Vector2, cross); VCALL_LOCALMEM0R(Vector2, abs); VCALL_LOCALMEM1R(Vector2, clamped); @@ -443,6 +443,7 @@ struct _VariantCall { VCALL_LOCALMEM1R(Color, lightened); VCALL_LOCALMEM1R(Color, darkened); VCALL_LOCALMEM1R(Color, to_html); + VCALL_LOCALMEM4R(Color, from_hsv); VCALL_LOCALMEM0R(RID, get_id); @@ -490,6 +491,7 @@ struct _VariantCall { VCALL_LOCALMEM1(Array, erase); VCALL_LOCALMEM0(Array, sort); VCALL_LOCALMEM2(Array, sort_custom); + VCALL_LOCALMEM0(Array, shuffle); VCALL_LOCALMEM2R(Array, bsearch); VCALL_LOCALMEM4R(Array, bsearch_custom); VCALL_LOCALMEM0R(Array, duplicate); @@ -1515,7 +1517,7 @@ void register_variant_methods() { ADDFUNC1R(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray()); ADDFUNC1R(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray()); ADDFUNC1R(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray()); - //ADDFUNC1R(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray()); + ADDFUNC1R(VECTOR2, REAL, Vector2, cross, VECTOR2, "with", varray()); ADDFUNC0R(VECTOR2, VECTOR2, Vector2, abs, varray()); ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray()); @@ -1589,6 +1591,7 @@ void register_variant_methods() { ADDFUNC1R(COLOR, COLOR, Color, lightened, REAL, "amount", varray()); ADDFUNC1R(COLOR, COLOR, Color, darkened, REAL, "amount", varray()); ADDFUNC1R(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true)); + ADDFUNC4R(COLOR, COLOR, Color, from_hsv, REAL, "h", REAL, "s", REAL, "v", REAL, "a", varray(1.0)); ADDFUNC0R(_RID, INT, RID, get_id, varray()); @@ -1634,6 +1637,7 @@ void register_variant_methods() { ADDFUNC0RNC(ARRAY, NIL, Array, pop_front, varray()); ADDFUNC0NC(ARRAY, NIL, Array, sort, varray()); ADDFUNC2NC(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray()); + ADDFUNC0NC(ARRAY, NIL, Array, shuffle, varray()); ADDFUNC2R(ARRAY, INT, Array, bsearch, NIL, "value", BOOL, "before", varray(true)); ADDFUNC4R(ARRAY, INT, Array, bsearch_custom, NIL, "value", OBJECT, "obj", STRING, "func", BOOL, "before", varray(true)); ADDFUNC0NC(ARRAY, NIL, Array, invert, varray()); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index e46fac77ee..842f5f0af6 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -147,7 +147,7 @@ Variant::operator bool() const { return booleanize(); } -// We consider all unitialized or empty types to be false based on the type's +// We consider all uninitialized or empty types to be false based on the type's // zeroiness. bool Variant::booleanize() const { return !is_zero(); @@ -177,7 +177,7 @@ bool Variant::booleanize() const { CASE_TYPE(m_prefix, m_op_name, m_name) { \ if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \ if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \ - if (p_b.type == NIL) _RETURN(!p_b.type m_op NIL); \ + if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \ \ _RETURN_FAIL \ }; @@ -252,7 +252,7 @@ bool Variant::booleanize() const { CASE_TYPE(m_prefix, m_op_name, m_name) { \ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ - if (p_b.type == NIL) _RETURN(!p_b.type m_op NIL); \ + if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \ \ _RETURN_FAIL \ }; @@ -278,7 +278,7 @@ bool Variant::booleanize() const { if (p_b.type == m_name) \ _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ if (p_b.type == NIL) \ - _RETURN(!p_b.type m_op NIL); \ + _RETURN(!(p_b.type m_op NIL)); \ \ _RETURN_FAIL \ }; @@ -323,7 +323,7 @@ bool Variant::booleanize() const { if (p_b.type == m_name) \ _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \ if (p_b.type == NIL) \ - _RETURN(!p_b.type m_op NIL); \ + _RETURN(!(p_b.type m_op NIL)); \ \ _RETURN_FAIL \ } @@ -1501,7 +1501,7 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool v->set_hsv(v->get_h(), p_value._data._real, v->get_v()); valid = true; } else if (p_index == CoreStringNames::singleton->v) { - v->set_hsv(v->get_h(), v->get_v(), p_value._data._real); + v->set_hsv(v->get_h(), v->get_s(), p_value._data._real); valid = true; } } diff --git a/core/version.h b/core/version.h index 7a55d69ad7..d39172865a 100644 --- a/core/version.h +++ b/core/version.h @@ -30,9 +30,32 @@ #include "version_generated.gen.h" +// Godot versions are of the form <major>.<minor> for the initial release, +// and then <major>.<minor>.<patch> for subsequent bugfix releases where <patch> != 0 +// That's arbitrary, but we find it pretty and it's the current policy. + +// Defines the main "branch" version. Patch versions in this branch should be +// forward-compatible. +// Example: "3.1" +#define VERSION_BRANCH "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) #ifdef VERSION_PATCH -#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) "." VERSION_STATUS "." VERSION_BUILD VERSION_MODULE_CONFIG +// Example: "3.1.4" +#define VERSION_NUMBER "" VERSION_BRANCH "." _MKSTR(VERSION_PATCH) #else -#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." VERSION_STATUS "." VERSION_BUILD VERSION_MODULE_CONFIG +// Example: "3.1" +#define VERSION_NUMBER "" VERSION_BRANCH #endif // VERSION_PATCH -#define VERSION_FULL_NAME "" VERSION_NAME " v" VERSION_MKSTRING + +// Describes the full configuration of that Godot version, including the version number, +// the status (beta, stable, etc.) and potential module-specific features (e.g. mono). +// Example: "3.1.4.stable.mono" +#define VERSION_FULL_CONFIG "" VERSION_NUMBER "." VERSION_STATUS VERSION_MODULE_CONFIG + +// Similar to VERSION_FULL_CONFIG, but also includes the (potentially custom) VERSION_BUILD +// description (e.g. official, custom_build, etc.). +// Example: "3.1.4.stable.mono.official" +#define VERSION_FULL_BUILD "" VERSION_FULL_CONFIG "." VERSION_BUILD + +// Same as above, but prepended with Godot's name and a cosmetic "v" for "version". +// Example: "Godot v3.1.4.stable.official.mono" +#define VERSION_FULL_NAME "" VERSION_NAME " v" VERSION_FULL_BUILD diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index 4e9a6a5fc0..07e428faad 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="@GDScript" category="Core" version="3.0-stable"> +<class name="@GDScript" category="Core" version="3.1"> <brief_description> Built-in GDScript functions. </brief_description> @@ -20,7 +20,7 @@ </argument> <argument index="2" name="b8" type="int"> </argument> - <argument index="3" name="a8" type="int"> + <argument index="3" name="a8" type="int" default="255"> </argument> <description> Returns a 32 bit color with red, green, blue and alpha channels. Each channel has 8 bits of information ranging from 0 to 255. @@ -38,7 +38,7 @@ </return> <argument index="0" name="name" type="String"> </argument> - <argument index="1" name="alpha" type="float"> + <argument index="1" name="alpha" type="float" default="1.0"> </argument> <description> Returns a color according to the standardised [code]name[/code] with [code]alpha[/code] ranging from 0 to 1. @@ -1131,9 +1131,9 @@ <method name="yield"> <return type="GDScriptFunctionState"> </return> - <argument index="0" name="object" type="Object"> + <argument index="0" name="object" type="Object" default="null"> </argument> - <argument index="1" name="signal" type="String"> + <argument index="1" name="signal" type="String" default=""""> </argument> <description> Stops the function execution and returns the current state. Call [method GDScriptFunctionState.resume] on the state to resume execution. This invalidates the state. diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 1f6256f8c9..840d884a8c 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="@GlobalScope" category="Core" version="3.0-stable"> +<class name="@GlobalScope" category="Core" version="3.1"> <brief_description> Global scope constants and variables. </brief_description> diff --git a/doc/classes/@NativeScript.xml b/doc/classes/@NativeScript.xml index 8fde9e3dc3..2bf1dc7a7c 100644 --- a/doc/classes/@NativeScript.xml +++ b/doc/classes/@NativeScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="@NativeScript" category="Core" version="3.0-stable"> +<class name="@NativeScript" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/@VisualScript.xml b/doc/classes/@VisualScript.xml index 4867a5a22b..d4a924a259 100644 --- a/doc/classes/@VisualScript.xml +++ b/doc/classes/@VisualScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="@VisualScript" category="Core" version="3.0-stable"> +<class name="@VisualScript" category="Core" version="3.1"> <brief_description> Built-in visual script functions. </brief_description> diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index f253d49dc0..730c395f10 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AABB" category="Built-In Types" version="3.0-stable"> +<class name="AABB" category="Built-In Types" version="3.1"> <brief_description> Axis-Aligned Bounding Box. </brief_description> diff --git a/doc/classes/ARVRAnchor.xml b/doc/classes/ARVRAnchor.xml index cc9370e8fe..a8366e3405 100644 --- a/doc/classes/ARVRAnchor.xml +++ b/doc/classes/ARVRAnchor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRAnchor" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="ARVRAnchor" inherits="Spatial" category="Core" version="3.1"> <brief_description> Anchor point in AR Space </brief_description> diff --git a/doc/classes/ARVRCamera.xml b/doc/classes/ARVRCamera.xml index b603a69337..e74b435e11 100644 --- a/doc/classes/ARVRCamera.xml +++ b/doc/classes/ARVRCamera.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRCamera" inherits="Camera" category="Core" version="3.0-stable"> +<class name="ARVRCamera" inherits="Camera" category="Core" version="3.1"> <brief_description> A camera node with a few overrules for AR/VR applied such as location tracking. </brief_description> diff --git a/doc/classes/ARVRController.xml b/doc/classes/ARVRController.xml index 07692f5ab2..9c306c3ea4 100644 --- a/doc/classes/ARVRController.xml +++ b/doc/classes/ARVRController.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRController" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="ARVRController" inherits="Spatial" category="Core" version="3.1"> <brief_description> A spatial node representing a spatially tracked controller. </brief_description> diff --git a/doc/classes/ARVRInterface.xml b/doc/classes/ARVRInterface.xml index bf9dde7706..413370ed0b 100644 --- a/doc/classes/ARVRInterface.xml +++ b/doc/classes/ARVRInterface.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRInterface" inherits="Reference" category="Core" version="3.0-stable"> +<class name="ARVRInterface" inherits="Reference" category="Core" version="3.1"> <brief_description> Base class for ARVR interface implementation. </brief_description> diff --git a/doc/classes/ARVROrigin.xml b/doc/classes/ARVROrigin.xml index ec9b79bf84..80626338f2 100644 --- a/doc/classes/ARVROrigin.xml +++ b/doc/classes/ARVROrigin.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVROrigin" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="ARVROrigin" inherits="Spatial" category="Core" version="3.1"> <brief_description> Our origin point in AR/VR. </brief_description> diff --git a/doc/classes/ARVRPositionalTracker.xml b/doc/classes/ARVRPositionalTracker.xml index ea2139406b..e703de36f4 100644 --- a/doc/classes/ARVRPositionalTracker.xml +++ b/doc/classes/ARVRPositionalTracker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRPositionalTracker" inherits="Object" category="Core" version="3.0-stable"> +<class name="ARVRPositionalTracker" inherits="Object" category="Core" version="3.1"> <brief_description> A tracked object </brief_description> diff --git a/doc/classes/ARVRServer.xml b/doc/classes/ARVRServer.xml index 29d217d1d3..965fad1961 100644 --- a/doc/classes/ARVRServer.xml +++ b/doc/classes/ARVRServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRServer" inherits="Object" category="Core" version="3.0-stable"> +<class name="ARVRServer" inherits="Object" category="Core" version="3.1"> <brief_description> This is our AR/VR Server. </brief_description> diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml index 0573e4edf0..482566ee9f 100644 --- a/doc/classes/AStar.xml +++ b/doc/classes/AStar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AStar" inherits="Reference" category="Core" version="3.0-stable"> +<class name="AStar" inherits="Reference" category="Core" version="3.1"> <brief_description> AStar class representation that uses vectors as edges. </brief_description> diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml index a6cc40238b..99a3f59487 100644 --- a/doc/classes/AcceptDialog.xml +++ b/doc/classes/AcceptDialog.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AcceptDialog" inherits="WindowDialog" category="Core" version="3.0-stable"> +<class name="AcceptDialog" inherits="WindowDialog" category="Core" version="3.1"> <brief_description> Base dialog for user notification. </brief_description> diff --git a/doc/classes/AnimatedSprite.xml b/doc/classes/AnimatedSprite.xml index 3e67fd6840..a6521c0cd1 100644 --- a/doc/classes/AnimatedSprite.xml +++ b/doc/classes/AnimatedSprite.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimatedSprite" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="AnimatedSprite" inherits="Node2D" category="Core" version="3.1"> <brief_description> Sprite node that can use multiple textures for animation. </brief_description> diff --git a/doc/classes/AnimatedSprite3D.xml b/doc/classes/AnimatedSprite3D.xml index f72211776e..733d565676 100644 --- a/doc/classes/AnimatedSprite3D.xml +++ b/doc/classes/AnimatedSprite3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimatedSprite3D" inherits="SpriteBase3D" category="Core" version="3.0-stable"> +<class name="AnimatedSprite3D" inherits="SpriteBase3D" category="Core" version="3.1"> <brief_description> 2D sprite node in 3D world, that can use multiple 2D textures for animation. </brief_description> diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index f8c94dd12d..ea503f8aa9 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Animation" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Animation" inherits="Resource" category="Core" version="3.1"> <brief_description> Contains data used to animate everything in the engine. </brief_description> diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index b15f0ec732..178c714a20 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimationPlayer" inherits="Node" category="Core" version="3.0-stable"> +<class name="AnimationPlayer" inherits="Node" category="Core" version="3.1"> <brief_description> Container and player of [Animation] resources. </brief_description> diff --git a/doc/classes/AnimationTreePlayer.xml b/doc/classes/AnimationTreePlayer.xml index c09121857e..49b4c6b43e 100644 --- a/doc/classes/AnimationTreePlayer.xml +++ b/doc/classes/AnimationTreePlayer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimationTreePlayer" inherits="Node" category="Core" version="3.0-stable"> +<class name="AnimationTreePlayer" inherits="Node" category="Core" version="3.1"> <brief_description> Animation Player that uses a node graph for blending Animations. </brief_description> diff --git a/doc/classes/Area.xml b/doc/classes/Area.xml index 2853159c0e..5c56b5e21b 100644 --- a/doc/classes/Area.xml +++ b/doc/classes/Area.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Area" inherits="CollisionObject" category="Core" version="3.0-stable"> +<class name="Area" inherits="CollisionObject" category="Core" version="3.1"> <brief_description> General purpose area node for detection and 3D physics influence. </brief_description> @@ -192,7 +192,7 @@ <argument index="0" name="body" type="Object"> </argument> <description> - Emitted when a [PhysicsBody2D] object exits. + Emitted when a [PhysicsBody] object exits. </description> </signal> <signal name="body_shape_entered"> @@ -205,7 +205,7 @@ <argument index="3" name="area_shape" type="int"> </argument> <description> - Emitted when a [PhysicsBody2D] object enters, reporting which shapes overlapped. + Emitted when a [PhysicsBody] object enters, reporting which shapes overlapped. </description> </signal> <signal name="body_shape_exited"> @@ -218,7 +218,7 @@ <argument index="3" name="area_shape" type="int"> </argument> <description> - Emitted when a [PhysicsBody2D] object exits, reporting which shapes were overlapping. + Emitted when a [PhysicsBody] object exits, reporting which shapes were overlapping. </description> </signal> </signals> diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index 8e8382d5de..c50ccefc4c 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Area2D" inherits="CollisionObject2D" category="Core" version="3.0-stable"> +<class name="Area2D" inherits="CollisionObject2D" category="Core" version="3.1"> <brief_description> 2D area for detection and 2D physics influence. </brief_description> diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 4d282761fe..2e2176743f 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Array" category="Built-In Types" version="3.0-stable"> +<class name="Array" category="Built-In Types" version="3.1"> <brief_description> Generic array datatype. </brief_description> @@ -265,6 +265,11 @@ Searches the array in reverse order. Optionally, a start search index can be passed. If negative, the start index is considered relative to the end of the array. </description> </method> + <method name="shuffle"> + <description> + Shuffle the array such that the items will have a random order. + </description> + </method> <method name="size"> <return type="int"> </return> diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml index 7b74b678bd..c25044b120 100644 --- a/doc/classes/ArrayMesh.xml +++ b/doc/classes/ArrayMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ArrayMesh" inherits="Mesh" category="Core" version="3.0-stable"> +<class name="ArrayMesh" inherits="Mesh" category="Core" version="3.1"> <brief_description> </brief_description> <description> @@ -66,6 +66,16 @@ Return the amount of surfaces that the [code]ArrayMesh[/code] holds. </description> </method> + <method name="lightmap_unwrap"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="arg0" type="Transform"> + </argument> + <argument index="1" name="arg1" type="float"> + </argument> + <description> + </description> + </method> <method name="regen_normalmaps"> <return type="void"> </return> diff --git a/doc/classes/AtlasTexture.xml b/doc/classes/AtlasTexture.xml index 87cd072d99..409c40e809 100644 --- a/doc/classes/AtlasTexture.xml +++ b/doc/classes/AtlasTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AtlasTexture" inherits="Texture" category="Core" version="3.0-stable"> +<class name="AtlasTexture" inherits="Texture" category="Core" version="3.1"> <brief_description> Packs multiple small textures in a single, bigger one. Helps to optimize video memory costs and render calls. </brief_description> diff --git a/doc/classes/AudioBusLayout.xml b/doc/classes/AudioBusLayout.xml index d960093fc6..c43da3e233 100644 --- a/doc/classes/AudioBusLayout.xml +++ b/doc/classes/AudioBusLayout.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioBusLayout" inherits="Resource" category="Core" version="3.0-stable"> +<class name="AudioBusLayout" inherits="Resource" category="Core" version="3.1"> <brief_description> Stores information about the audiobusses. </brief_description> diff --git a/doc/classes/AudioEffect.xml b/doc/classes/AudioEffect.xml index 81c72e34b2..acbc96e70e 100644 --- a/doc/classes/AudioEffect.xml +++ b/doc/classes/AudioEffect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffect" inherits="Resource" category="Core" version="3.0-stable"> +<class name="AudioEffect" inherits="Resource" category="Core" version="3.1"> <brief_description> Audio Effect For Audio. </brief_description> diff --git a/doc/classes/AudioEffectAmplify.xml b/doc/classes/AudioEffectAmplify.xml index 7a031f7f47..3582ddc4f7 100644 --- a/doc/classes/AudioEffectAmplify.xml +++ b/doc/classes/AudioEffectAmplify.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectAmplify" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectAmplify" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a Amplify audio effect to an Audio bus. Increases or decreases the volume of the selected audio bus. diff --git a/doc/classes/AudioEffectBandLimitFilter.xml b/doc/classes/AudioEffectBandLimitFilter.xml index 592735e098..9eba806ad5 100644 --- a/doc/classes/AudioEffectBandLimitFilter.xml +++ b/doc/classes/AudioEffectBandLimitFilter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectBandLimitFilter" inherits="AudioEffectFilter" category="Core" version="3.0-stable"> +<class name="AudioEffectBandLimitFilter" inherits="AudioEffectFilter" category="Core" version="3.1"> <brief_description> Adds a band limit filter to the Audio Bus. </brief_description> diff --git a/doc/classes/AudioEffectBandPassFilter.xml b/doc/classes/AudioEffectBandPassFilter.xml index 3705590c83..11aab3e86d 100644 --- a/doc/classes/AudioEffectBandPassFilter.xml +++ b/doc/classes/AudioEffectBandPassFilter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectBandPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0-stable"> +<class name="AudioEffectBandPassFilter" inherits="AudioEffectFilter" category="Core" version="3.1"> <brief_description> Adds a band pass filter to the Audio Bus. </brief_description> diff --git a/doc/classes/AudioEffectChorus.xml b/doc/classes/AudioEffectChorus.xml index 4bcd0e2552..43e14b3964 100644 --- a/doc/classes/AudioEffectChorus.xml +++ b/doc/classes/AudioEffectChorus.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectChorus" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectChorus" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a chorus audio effect. </brief_description> diff --git a/doc/classes/AudioEffectCompressor.xml b/doc/classes/AudioEffectCompressor.xml index 4fd28326a2..fa81bcf030 100644 --- a/doc/classes/AudioEffectCompressor.xml +++ b/doc/classes/AudioEffectCompressor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectCompressor" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectCompressor" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a Compressor audio effect to an Audio bus. Reduces sounds that exceed a certain threshold level, smooths out the dynamics and increases the overall volume. diff --git a/doc/classes/AudioEffectDelay.xml b/doc/classes/AudioEffectDelay.xml index d253ffab96..7c9d11111c 100644 --- a/doc/classes/AudioEffectDelay.xml +++ b/doc/classes/AudioEffectDelay.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectDelay" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectDelay" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a Delay audio effect to an Audio bus. Plays input signal back after a period of time. Two tap delay and feedback options. diff --git a/doc/classes/AudioEffectDistortion.xml b/doc/classes/AudioEffectDistortion.xml index 91a1961b30..74d12df554 100644 --- a/doc/classes/AudioEffectDistortion.xml +++ b/doc/classes/AudioEffectDistortion.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectDistortion" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectDistortion" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a Distortion audio effect to an Audio bus. Modify the sound to make it dirty. diff --git a/doc/classes/AudioEffectEQ.xml b/doc/classes/AudioEffectEQ.xml index 667982d529..35a6f7557d 100644 --- a/doc/classes/AudioEffectEQ.xml +++ b/doc/classes/AudioEffectEQ.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectEQ" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectEQ" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Base class for audio equalizers. Gives you control over frequencies. Use it to create a custom equalizer if [AudioEffectEQ6], [AudioEffectEQ10] or [AudioEffectEQ21] don't fit your needs. diff --git a/doc/classes/AudioEffectEQ10.xml b/doc/classes/AudioEffectEQ10.xml index 9e5303a266..f88a954417 100644 --- a/doc/classes/AudioEffectEQ10.xml +++ b/doc/classes/AudioEffectEQ10.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectEQ10" inherits="AudioEffectEQ" category="Core" version="3.0-stable"> +<class name="AudioEffectEQ10" inherits="AudioEffectEQ" category="Core" version="3.1"> <brief_description> Adds a 10-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 31 Hz to 16000 Hz. Each frequency can be modulated between -60/+24 dB. diff --git a/doc/classes/AudioEffectEQ21.xml b/doc/classes/AudioEffectEQ21.xml index ec0db8bbbe..86d2189f27 100644 --- a/doc/classes/AudioEffectEQ21.xml +++ b/doc/classes/AudioEffectEQ21.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectEQ21" inherits="AudioEffectEQ" category="Core" version="3.0-stable"> +<class name="AudioEffectEQ21" inherits="AudioEffectEQ" category="Core" version="3.1"> <brief_description> Adds a 21-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 22 Hz to 22000 Hz. Each frequency can be modulated between -60/+24 dB. diff --git a/doc/classes/AudioEffectEQ6.xml b/doc/classes/AudioEffectEQ6.xml index f5748f0a36..8f789cdbdd 100644 --- a/doc/classes/AudioEffectEQ6.xml +++ b/doc/classes/AudioEffectEQ6.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectEQ6" inherits="AudioEffectEQ" category="Core" version="3.0-stable"> +<class name="AudioEffectEQ6" inherits="AudioEffectEQ" category="Core" version="3.1"> <brief_description> Adds a 6-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 32 Hz to 10000 Hz. Each frequency can be modulated between -60/+24 dB. diff --git a/doc/classes/AudioEffectFilter.xml b/doc/classes/AudioEffectFilter.xml index 9c0eb38612..5a86c092a0 100644 --- a/doc/classes/AudioEffectFilter.xml +++ b/doc/classes/AudioEffectFilter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectFilter" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectFilter" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a filter to the Audio Bus. </brief_description> diff --git a/doc/classes/AudioEffectHighPassFilter.xml b/doc/classes/AudioEffectHighPassFilter.xml index 451c65a228..3d487fc783 100644 --- a/doc/classes/AudioEffectHighPassFilter.xml +++ b/doc/classes/AudioEffectHighPassFilter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectHighPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0-stable"> +<class name="AudioEffectHighPassFilter" inherits="AudioEffectFilter" category="Core" version="3.1"> <brief_description> Adds a high pass filter to the Audio Bus. </brief_description> diff --git a/doc/classes/AudioEffectHighShelfFilter.xml b/doc/classes/AudioEffectHighShelfFilter.xml index a26d4a4e6b..ca2312ba6a 100644 --- a/doc/classes/AudioEffectHighShelfFilter.xml +++ b/doc/classes/AudioEffectHighShelfFilter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectHighShelfFilter" inherits="AudioEffectFilter" category="Core" version="3.0-stable"> +<class name="AudioEffectHighShelfFilter" inherits="AudioEffectFilter" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/AudioEffectLimiter.xml b/doc/classes/AudioEffectLimiter.xml index b6fe7b74e5..9e791f02d7 100644 --- a/doc/classes/AudioEffectLimiter.xml +++ b/doc/classes/AudioEffectLimiter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectLimiter" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectLimiter" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a soft clip Limiter audio effect to an Audio bus. </brief_description> diff --git a/doc/classes/AudioEffectLowPassFilter.xml b/doc/classes/AudioEffectLowPassFilter.xml index 25c80e2ea0..3facd8b665 100644 --- a/doc/classes/AudioEffectLowPassFilter.xml +++ b/doc/classes/AudioEffectLowPassFilter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectLowPassFilter" inherits="AudioEffectFilter" category="Core" version="3.0-stable"> +<class name="AudioEffectLowPassFilter" inherits="AudioEffectFilter" category="Core" version="3.1"> <brief_description> Adds a low pass filter to the Audio Bus. </brief_description> diff --git a/doc/classes/AudioEffectLowShelfFilter.xml b/doc/classes/AudioEffectLowShelfFilter.xml index f60429ca15..aadbf30eaa 100644 --- a/doc/classes/AudioEffectLowShelfFilter.xml +++ b/doc/classes/AudioEffectLowShelfFilter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectLowShelfFilter" inherits="AudioEffectFilter" category="Core" version="3.0-stable"> +<class name="AudioEffectLowShelfFilter" inherits="AudioEffectFilter" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/AudioEffectNotchFilter.xml b/doc/classes/AudioEffectNotchFilter.xml index ac78d9c3e5..741931f262 100644 --- a/doc/classes/AudioEffectNotchFilter.xml +++ b/doc/classes/AudioEffectNotchFilter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectNotchFilter" inherits="AudioEffectFilter" category="Core" version="3.0-stable"> +<class name="AudioEffectNotchFilter" inherits="AudioEffectFilter" category="Core" version="3.1"> <brief_description> Adds a notch filter to the Audio Bus. </brief_description> diff --git a/doc/classes/AudioEffectPanner.xml b/doc/classes/AudioEffectPanner.xml index 493e83393a..cbd14de905 100644 --- a/doc/classes/AudioEffectPanner.xml +++ b/doc/classes/AudioEffectPanner.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectPanner" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectPanner" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a Panner audio effect to an Audio bus. Pans sound left or right. </brief_description> diff --git a/doc/classes/AudioEffectPhaser.xml b/doc/classes/AudioEffectPhaser.xml index 3cc89e73f8..10566d089b 100644 --- a/doc/classes/AudioEffectPhaser.xml +++ b/doc/classes/AudioEffectPhaser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectPhaser" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectPhaser" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a Phaser audio effect to an Audio bus. Combines the original signal with a copy that is slightly out of phase with the original. diff --git a/doc/classes/AudioEffectPitchShift.xml b/doc/classes/AudioEffectPitchShift.xml index b0e7dbc049..99095bae44 100644 --- a/doc/classes/AudioEffectPitchShift.xml +++ b/doc/classes/AudioEffectPitchShift.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectPitchShift" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectPitchShift" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a Pitch shift audio effect to an Audio bus. Raises or lowers the pitch of original sound. diff --git a/doc/classes/AudioEffectReverb.xml b/doc/classes/AudioEffectReverb.xml index 46d1866ff0..fb2009105d 100644 --- a/doc/classes/AudioEffectReverb.xml +++ b/doc/classes/AudioEffectReverb.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectReverb" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectReverb" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> Adds a Reverb audio effect to an Audio bus. Simulates the sound of acoustic environments such as rooms, concert halls, caverns, or an open spaces. diff --git a/doc/classes/AudioEffectStereoEnhance.xml b/doc/classes/AudioEffectStereoEnhance.xml index 6e6e9af5c6..ae296d81a0 100644 --- a/doc/classes/AudioEffectStereoEnhance.xml +++ b/doc/classes/AudioEffectStereoEnhance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioEffectStereoEnhance" inherits="AudioEffect" category="Core" version="3.0-stable"> +<class name="AudioEffectStereoEnhance" inherits="AudioEffect" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml index a6352bca1e..0be91427b1 100644 --- a/doc/classes/AudioServer.xml +++ b/doc/classes/AudioServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioServer" inherits="Object" category="Core" version="3.0-stable"> +<class name="AudioServer" inherits="Object" category="Core" version="3.1"> <brief_description> Server interface for low level audio access. </brief_description> diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml index f06ca0f901..d332277248 100644 --- a/doc/classes/AudioStream.xml +++ b/doc/classes/AudioStream.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStream" inherits="Resource" category="Core" version="3.0-stable"> +<class name="AudioStream" inherits="Resource" category="Core" version="3.1"> <brief_description> Base class for audio streams. </brief_description> @@ -12,6 +12,12 @@ <demos> </demos> <methods> + <method name="get_length" qualifiers="const"> + <return type="float"> + </return> + <description> + </description> + </method> </methods> <constants> </constants> diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml index 3babff52d1..0960935ad9 100644 --- a/doc/classes/AudioStreamPlayback.xml +++ b/doc/classes/AudioStreamPlayback.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamPlayback" inherits="Reference" category="Core" version="3.0-stable"> +<class name="AudioStreamPlayback" inherits="Reference" category="Core" version="3.1"> <brief_description> Meta class for playing back audio. </brief_description> diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml index e2cb442c36..4a69695ae5 100644 --- a/doc/classes/AudioStreamPlayer.xml +++ b/doc/classes/AudioStreamPlayer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamPlayer" inherits="Node" category="Core" version="3.0-stable"> +<class name="AudioStreamPlayer" inherits="Node" category="Core" version="3.1"> <brief_description> Plays back audio. </brief_description> @@ -56,6 +56,8 @@ <member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioStreamPlayer.MixTarget"> If the audio configuration has more than two speakers, this sets the target channels. See [code]MIX_TARGET_*[/code] constants. </member> + <member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale"> + </member> <member name="playing" type="bool" setter="_set_playing" getter="is_playing"> If [code]true[/code] audio is playing. </member> diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml index 2abb86472b..495d37e6b8 100644 --- a/doc/classes/AudioStreamPlayer2D.xml +++ b/doc/classes/AudioStreamPlayer2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamPlayer2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="AudioStreamPlayer2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Plays audio in 2D. </brief_description> @@ -62,6 +62,8 @@ <member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance"> Maximum distance from which audio is still hearable. </member> + <member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale"> + </member> <member name="playing" type="bool" setter="_set_playing" getter="is_playing"> If [code]true[/code] audio is playing. </member> diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml index a40a6b4f96..1ab5184684 100644 --- a/doc/classes/AudioStreamPlayer3D.xml +++ b/doc/classes/AudioStreamPlayer3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamPlayer3D" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="AudioStreamPlayer3D" inherits="Spatial" category="Core" version="3.1"> <brief_description> Plays 3D sound in 3D space </brief_description> @@ -86,6 +86,8 @@ <member name="out_of_range_mode" type="int" setter="set_out_of_range_mode" getter="get_out_of_range_mode" enum="AudioStreamPlayer3D.OutOfRangeMode"> Decides if audio should pause when source is outside of 'max_distance' range. </member> + <member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale"> + </member> <member name="playing" type="bool" setter="_set_playing" getter="is_playing"> If [code]true[/code], audio is playing. </member> diff --git a/doc/classes/AudioStreamRandomPitch.xml b/doc/classes/AudioStreamRandomPitch.xml index a78c412f26..992c731d47 100644 --- a/doc/classes/AudioStreamRandomPitch.xml +++ b/doc/classes/AudioStreamRandomPitch.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamRandomPitch" inherits="AudioStream" category="Core" version="3.0-stable"> +<class name="AudioStreamRandomPitch" inherits="AudioStream" category="Core" version="3.1"> <brief_description> Plays audio with random pitch tweaking. </brief_description> diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamSample.xml index 8e11a870ca..8b6651abe7 100644 --- a/doc/classes/AudioStreamSample.xml +++ b/doc/classes/AudioStreamSample.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamSample" inherits="AudioStream" category="Core" version="3.0-stable"> +<class name="AudioStreamSample" inherits="AudioStream" category="Core" version="3.1"> <brief_description> Plays audio. </brief_description> diff --git a/doc/classes/BackBufferCopy.xml b/doc/classes/BackBufferCopy.xml index e11b55a6a0..7070fdec4c 100644 --- a/doc/classes/BackBufferCopy.xml +++ b/doc/classes/BackBufferCopy.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BackBufferCopy" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="BackBufferCopy" inherits="Node2D" category="Core" version="3.1"> <brief_description> Copies a region of the screen (or the whole screen) to a buffer so it can be accessed with the texscreen() shader instruction. </brief_description> diff --git a/doc/classes/BakedLightmap.xml b/doc/classes/BakedLightmap.xml index a9033906dc..45c60302a6 100644 --- a/doc/classes/BakedLightmap.xml +++ b/doc/classes/BakedLightmap.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BakedLightmap" inherits="VisualInstance" category="Core" version="3.0-stable"> +<class name="BakedLightmap" inherits="VisualInstance" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/BakedLightmapData.xml b/doc/classes/BakedLightmapData.xml index 0fcd984c5e..8ee10b0b8b 100644 --- a/doc/classes/BakedLightmapData.xml +++ b/doc/classes/BakedLightmapData.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BakedLightmapData" inherits="Resource" category="Core" version="3.0-stable"> +<class name="BakedLightmapData" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 6d7ee544e4..2f44179adb 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BaseButton" inherits="Control" category="Core" version="3.0-stable"> +<class name="BaseButton" inherits="Control" category="Core" version="3.1"> <brief_description> Base class for different kinds of buttons. </brief_description> diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index c90dfeea27..f7270fa5f9 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Basis" category="Built-In Types" version="3.0-stable"> +<class name="Basis" category="Built-In Types" version="3.1"> <brief_description> 3x3 matrix datatype. </brief_description> diff --git a/doc/classes/BitMap.xml b/doc/classes/BitMap.xml index f85c538456..98f554ebaa 100644 --- a/doc/classes/BitMap.xml +++ b/doc/classes/BitMap.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BitMap" inherits="Resource" category="Core" version="3.0-stable"> +<class name="BitMap" inherits="Resource" category="Core" version="3.1"> <brief_description> Boolean matrix. </brief_description> @@ -25,8 +25,10 @@ </return> <argument index="0" name="image" type="Image"> </argument> + <argument index="1" name="threshold" type="float" default="0.1"> + </argument> <description> - Creates a bitmap that matches the given image dimensions, every element of the bitmap is set to false if the alpha value of the image at that position is 0, and true in other case. + Creates a bitmap that matches the given image dimensions, every element of the bitmap is set to false if the alpha value of the image at that position is equal to [code]threshold[/code] or less, and true in other case. </description> </method> <method name="get_bit" qualifiers="const"> diff --git a/doc/classes/BitmapFont.xml b/doc/classes/BitmapFont.xml index 77c1e0949c..c943caf636 100644 --- a/doc/classes/BitmapFont.xml +++ b/doc/classes/BitmapFont.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BitmapFont" inherits="Font" category="Core" version="3.0-stable"> +<class name="BitmapFont" inherits="Font" category="Core" version="3.1"> <brief_description> Renders text using [code]*.fnt[/code] fonts. </brief_description> diff --git a/doc/classes/BoneAttachment.xml b/doc/classes/BoneAttachment.xml index 77c8bd603e..a85453a415 100644 --- a/doc/classes/BoneAttachment.xml +++ b/doc/classes/BoneAttachment.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BoneAttachment" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="BoneAttachment" inherits="Spatial" category="Core" version="3.1"> <brief_description> A node that will attach to a bone. </brief_description> diff --git a/doc/classes/BoxContainer.xml b/doc/classes/BoxContainer.xml index b509e83985..3fbad58a24 100644 --- a/doc/classes/BoxContainer.xml +++ b/doc/classes/BoxContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BoxContainer" inherits="Container" category="Core" version="3.0-stable"> +<class name="BoxContainer" inherits="Container" category="Core" version="3.1"> <brief_description> Base class for box containers. </brief_description> diff --git a/doc/classes/BoxShape.xml b/doc/classes/BoxShape.xml index 00b4b6bdbb..d98a188870 100644 --- a/doc/classes/BoxShape.xml +++ b/doc/classes/BoxShape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BoxShape" inherits="Shape" category="Core" version="3.0-stable"> +<class name="BoxShape" inherits="Shape" category="Core" version="3.1"> <brief_description> Box shape resource. </brief_description> diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml index bc1608baf8..382a538f2b 100644 --- a/doc/classes/Button.xml +++ b/doc/classes/Button.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Button" inherits="BaseButton" category="Core" version="3.0-stable"> +<class name="Button" inherits="BaseButton" category="Core" version="3.1"> <brief_description> Standard themed Button. </brief_description> diff --git a/doc/classes/ButtonGroup.xml b/doc/classes/ButtonGroup.xml index 19a75843e1..e839c3e750 100644 --- a/doc/classes/ButtonGroup.xml +++ b/doc/classes/ButtonGroup.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ButtonGroup" inherits="Resource" category="Core" version="3.0-stable"> +<class name="ButtonGroup" inherits="Resource" category="Core" version="3.1"> <brief_description> Group of Buttons. </brief_description> <description> Group of [Button]. All direct and indirect children buttons become radios. Only one allows being pressed. + [member BaseButton.toggle_mode] should be [code]true[/code]. </description> <tutorials> </tutorials> diff --git a/doc/classes/Camera.xml b/doc/classes/Camera.xml index e481799c5c..0b7cd4ef7a 100644 --- a/doc/classes/Camera.xml +++ b/doc/classes/Camera.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Camera" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="Camera" inherits="Spatial" category="Core" version="3.1"> <brief_description> Camera node, displays from a point of view. </brief_description> @@ -133,7 +133,7 @@ The camera's field of view angle (in degrees). Only applicable in perspective mode. Since [member keep_aspect] locks one axis, [code]fov[/code] sets the other axis' field of view angle. </member> <member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset"> - The horizontal (X) offset of the Camear viewport. + The horizontal (X) offset of the Camera viewport. </member> <member name="keep_aspect" type="int" setter="set_keep_aspect_mode" getter="get_keep_aspect_mode" enum="Camera.KeepAspect"> The axis to lock during [member fov]/[member size] adjustments. @@ -148,7 +148,7 @@ The camera's size measured as 1/2 the width or height. Only applicable in orthogonal mode. Since [member keep_aspect] locks on axis, [code]size[/code] sets the other axis' size length. </member> <member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset"> - The horizontal (Y) offset of the Camear viewport. + The horizontal (Y) offset of the Camera viewport. </member> </members> <constants> diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml index f3825019a2..39cc1b84b3 100644 --- a/doc/classes/Camera2D.xml +++ b/doc/classes/Camera2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Camera2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Camera2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Camera node for 2D scenes. </brief_description> diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index bb3d4938b8..1705808c04 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CanvasItem" inherits="Node" category="Core" version="3.0-stable"> +<class name="CanvasItem" inherits="Node" category="Core" version="3.1"> <brief_description> Base class of anything 2D. </brief_description> @@ -90,6 +90,18 @@ Draws a line from a 2D point to another, with a given color and width. It can be optionally antialiased. </description> </method> + <method name="draw_mesh"> + <return type="void"> + </return> + <argument index="0" name="mesh" type="Mesh"> + </argument> + <argument index="1" name="texture" type="Texture"> + </argument> + <argument index="2" name="normal_map" type="Texture" default="null"> + </argument> + <description> + </description> + </method> <method name="draw_multiline"> <return type="void"> </return> @@ -120,6 +132,18 @@ Draws multiple, parallel lines with a uniform [code]width[/code], segment-by-segment coloring, and optional antialiasing. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code]. </description> </method> + <method name="draw_multimesh"> + <return type="void"> + </return> + <argument index="0" name="mesh" type="Mesh"> + </argument> + <argument index="1" name="texture" type="Texture"> + </argument> + <argument index="2" name="normal_map" type="Texture" default="null"> + </argument> + <description> + </description> + </method> <method name="draw_polygon"> <return type="void"> </return> diff --git a/doc/classes/CanvasItemMaterial.xml b/doc/classes/CanvasItemMaterial.xml index 5ec32bc63d..fe7194dcfe 100644 --- a/doc/classes/CanvasItemMaterial.xml +++ b/doc/classes/CanvasItemMaterial.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CanvasItemMaterial" inherits="Material" category="Core" version="3.0-stable"> +<class name="CanvasItemMaterial" inherits="Material" category="Core" version="3.1"> <brief_description> A material for [CanvasItem]s. </brief_description> diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml index 3b7ba5b1ad..b2b0938822 100644 --- a/doc/classes/CanvasLayer.xml +++ b/doc/classes/CanvasLayer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CanvasLayer" inherits="Node" category="Core" version="3.0-stable"> +<class name="CanvasLayer" inherits="Node" category="Core" version="3.1"> <brief_description> Canvas drawing layer. </brief_description> diff --git a/doc/classes/CanvasModulate.xml b/doc/classes/CanvasModulate.xml index 827502d6c0..7740423cf5 100644 --- a/doc/classes/CanvasModulate.xml +++ b/doc/classes/CanvasModulate.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CanvasModulate" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="CanvasModulate" inherits="Node2D" category="Core" version="3.1"> <brief_description> Tint the entire canvas. </brief_description> diff --git a/doc/classes/CapsuleMesh.xml b/doc/classes/CapsuleMesh.xml index 3a291128c7..3500701290 100644 --- a/doc/classes/CapsuleMesh.xml +++ b/doc/classes/CapsuleMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CapsuleMesh" inherits="PrimitiveMesh" category="Core" version="3.0-stable"> +<class name="CapsuleMesh" inherits="PrimitiveMesh" category="Core" version="3.1"> <brief_description> Class representing a capsule-shaped [PrimitiveMesh]. </brief_description> diff --git a/doc/classes/CapsuleShape.xml b/doc/classes/CapsuleShape.xml index 1ff4f5aa00..0c00288783 100644 --- a/doc/classes/CapsuleShape.xml +++ b/doc/classes/CapsuleShape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CapsuleShape" inherits="Shape" category="Core" version="3.0-stable"> +<class name="CapsuleShape" inherits="Shape" category="Core" version="3.1"> <brief_description> Capsule shape for collisions. </brief_description> diff --git a/doc/classes/CapsuleShape2D.xml b/doc/classes/CapsuleShape2D.xml index 0b306643b9..488c1ddc4f 100644 --- a/doc/classes/CapsuleShape2D.xml +++ b/doc/classes/CapsuleShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CapsuleShape2D" inherits="Shape2D" category="Core" version="3.0-stable"> +<class name="CapsuleShape2D" inherits="Shape2D" category="Core" version="3.1"> <brief_description> Capsule shape for 2D collisions. </brief_description> diff --git a/doc/classes/CenterContainer.xml b/doc/classes/CenterContainer.xml index a4e17bf0b6..41c8cf7100 100644 --- a/doc/classes/CenterContainer.xml +++ b/doc/classes/CenterContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CenterContainer" inherits="Container" category="Core" version="3.0-stable"> +<class name="CenterContainer" inherits="Container" category="Core" version="3.1"> <brief_description> Keeps children controls centered. </brief_description> diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml index 25340ed284..d37f0422bc 100644 --- a/doc/classes/CheckBox.xml +++ b/doc/classes/CheckBox.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CheckBox" inherits="Button" category="Core" version="3.0-stable"> +<class name="CheckBox" inherits="Button" category="Core" version="3.1"> <brief_description> Binary choice user interface widget </brief_description> diff --git a/doc/classes/CheckButton.xml b/doc/classes/CheckButton.xml index ec214fc498..deba9a17b6 100644 --- a/doc/classes/CheckButton.xml +++ b/doc/classes/CheckButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CheckButton" inherits="Button" category="Core" version="3.0-stable"> +<class name="CheckButton" inherits="Button" category="Core" version="3.1"> <brief_description> Checkable button. </brief_description> diff --git a/doc/classes/CircleShape2D.xml b/doc/classes/CircleShape2D.xml index 0c8b2088b3..db84c82e48 100644 --- a/doc/classes/CircleShape2D.xml +++ b/doc/classes/CircleShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CircleShape2D" inherits="Shape2D" category="Core" version="3.0-stable"> +<class name="CircleShape2D" inherits="Shape2D" category="Core" version="3.1"> <brief_description> Circular shape for 2D collisions. </brief_description> diff --git a/doc/classes/ClassDB.xml b/doc/classes/ClassDB.xml index e90a84f07c..6b2c540c19 100644 --- a/doc/classes/ClassDB.xml +++ b/doc/classes/ClassDB.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ClassDB" inherits="Object" category="Core" version="3.0-stable"> +<class name="ClassDB" inherits="Object" category="Core" version="3.1"> <brief_description> Class information repository. </brief_description> diff --git a/doc/classes/CollisionObject.xml b/doc/classes/CollisionObject.xml index 8b397f3227..22b9725121 100644 --- a/doc/classes/CollisionObject.xml +++ b/doc/classes/CollisionObject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CollisionObject" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="CollisionObject" inherits="Spatial" category="Core" version="3.1"> <brief_description> Base node for collision objects. </brief_description> diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml index 5b4ab46fd9..1ef72c0ca2 100644 --- a/doc/classes/CollisionObject2D.xml +++ b/doc/classes/CollisionObject2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CollisionObject2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="CollisionObject2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Base node for 2D collision objects. </brief_description> diff --git a/doc/classes/CollisionPolygon.xml b/doc/classes/CollisionPolygon.xml index 79c41e632e..28e9ba4217 100644 --- a/doc/classes/CollisionPolygon.xml +++ b/doc/classes/CollisionPolygon.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CollisionPolygon" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="CollisionPolygon" inherits="Spatial" category="Core" version="3.1"> <brief_description> Editor-only class for defining a collision polygon in 3D space. </brief_description> diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml index 0b17e6d26e..5b940e7ff1 100644 --- a/doc/classes/CollisionPolygon2D.xml +++ b/doc/classes/CollisionPolygon2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CollisionPolygon2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="CollisionPolygon2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Defines a 2D collision polygon. </brief_description> diff --git a/doc/classes/CollisionShape.xml b/doc/classes/CollisionShape.xml index 36a015ce80..9910de494e 100644 --- a/doc/classes/CollisionShape.xml +++ b/doc/classes/CollisionShape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CollisionShape" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="CollisionShape" inherits="Spatial" category="Core" version="3.1"> <brief_description> Node that represents collision shape data in 3D space. </brief_description> diff --git a/doc/classes/CollisionShape2D.xml b/doc/classes/CollisionShape2D.xml index ed5a094996..6d62a0ba62 100644 --- a/doc/classes/CollisionShape2D.xml +++ b/doc/classes/CollisionShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CollisionShape2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="CollisionShape2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Node that represents collision shape data in 2D space. </brief_description> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index 11c59531a8..2617aaef17 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Color" category="Built-In Types" version="3.0-stable"> +<class name="Color" category="Built-In Types" version="3.1"> <brief_description> Color in RGBA format with some support for ARGB format. </brief_description> @@ -117,6 +117,24 @@ [/codeblock] </description> </method> + <method name="from_hsv"> + <return type="Color"> + </return> + <argument index="0" name="h" type="float"> + </argument> + <argument index="1" name="s" type="float"> + </argument> + <argument index="2" name="v" type="float"> + </argument> + <argument index="3" name="a" type="float" default="1"> + </argument> + <description> + Constructs a color from an HSV profile. [code]h[/code] is a value between 0 and 360. [code]s[/code] and [code]v[/code] are values between 0 and 1. + [codeblock] + var c = Color.from_hsv(210, 0.5, 0.79, 0.8) # equivalent to HSV(210, 50, 79, 0.8) or Color8(100, 151, 201, 0.8) + [/codeblock] + </description> + </method> <method name="gray"> <return type="float"> </return> diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml index c69fc360a8..2214264dca 100644 --- a/doc/classes/ColorPicker.xml +++ b/doc/classes/ColorPicker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ColorPicker" inherits="BoxContainer" category="Core" version="3.0-stable"> +<class name="ColorPicker" inherits="BoxContainer" category="Core" version="3.1"> <brief_description> Color picker control. </brief_description> diff --git a/doc/classes/ColorPickerButton.xml b/doc/classes/ColorPickerButton.xml index 47fc198638..717f7e4efc 100644 --- a/doc/classes/ColorPickerButton.xml +++ b/doc/classes/ColorPickerButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ColorPickerButton" inherits="Button" category="Core" version="3.0-stable"> +<class name="ColorPickerButton" inherits="Button" category="Core" version="3.1"> <brief_description> Button that pops out a [ColorPicker] </brief_description> diff --git a/doc/classes/ColorRect.xml b/doc/classes/ColorRect.xml index 332d0f573f..69a70cfa39 100644 --- a/doc/classes/ColorRect.xml +++ b/doc/classes/ColorRect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ColorRect" inherits="Control" category="Core" version="3.0-stable"> +<class name="ColorRect" inherits="Control" category="Core" version="3.1"> <brief_description> Colored rect for canvas. </brief_description> diff --git a/doc/classes/ConcavePolygonShape.xml b/doc/classes/ConcavePolygonShape.xml index 4700491921..f4958d88d0 100644 --- a/doc/classes/ConcavePolygonShape.xml +++ b/doc/classes/ConcavePolygonShape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ConcavePolygonShape" inherits="Shape" category="Core" version="3.0-stable"> +<class name="ConcavePolygonShape" inherits="Shape" category="Core" version="3.1"> <brief_description> Concave polygon shape. </brief_description> diff --git a/doc/classes/ConcavePolygonShape2D.xml b/doc/classes/ConcavePolygonShape2D.xml index c339ee65a0..a653872353 100644 --- a/doc/classes/ConcavePolygonShape2D.xml +++ b/doc/classes/ConcavePolygonShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ConcavePolygonShape2D" inherits="Shape2D" category="Core" version="3.0-stable"> +<class name="ConcavePolygonShape2D" inherits="Shape2D" category="Core" version="3.1"> <brief_description> Concave polygon 2D shape resource for physics. </brief_description> diff --git a/doc/classes/ConeTwistJoint.xml b/doc/classes/ConeTwistJoint.xml index b7a4894ea7..feb3262be0 100644 --- a/doc/classes/ConeTwistJoint.xml +++ b/doc/classes/ConeTwistJoint.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ConeTwistJoint" inherits="Joint" category="Core" version="3.0-stable"> +<class name="ConeTwistJoint" inherits="Joint" category="Core" version="3.1"> <brief_description> A twist joint between two 3D bodies </brief_description> diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml index 17243b2100..a42d0f196e 100644 --- a/doc/classes/ConfigFile.xml +++ b/doc/classes/ConfigFile.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ConfigFile" inherits="Reference" category="Core" version="3.0-stable"> +<class name="ConfigFile" inherits="Reference" category="Core" version="3.1"> <brief_description> Helper class to handle INI-style files. </brief_description> <description> - This helper class can be used to store [Variant] values on the filesystem using INI-style formatting. The stored values are indentified by a section and a key: + This helper class can be used to store [Variant] values on the filesystem using INI-style formatting. The stored values are identified by a section and a key: [codeblock] [section] some_key=42 diff --git a/doc/classes/ConfirmationDialog.xml b/doc/classes/ConfirmationDialog.xml index 2759c1b883..461f48420a 100644 --- a/doc/classes/ConfirmationDialog.xml +++ b/doc/classes/ConfirmationDialog.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ConfirmationDialog" inherits="AcceptDialog" category="Core" version="3.0-stable"> +<class name="ConfirmationDialog" inherits="AcceptDialog" category="Core" version="3.1"> <brief_description> Dialog for confirmation of actions. </brief_description> diff --git a/doc/classes/Container.xml b/doc/classes/Container.xml index 0447c80887..db365db233 100644 --- a/doc/classes/Container.xml +++ b/doc/classes/Container.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Container" inherits="Control" category="Core" version="3.0-stable"> +<class name="Container" inherits="Control" category="Core" version="3.1"> <brief_description> Base node for containers. </brief_description> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 9db93bb6a9..722bb5d258 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Control" inherits="CanvasItem" category="Core" version="3.0-stable"> +<class name="Control" inherits="CanvasItem" category="Core" version="3.1"> <brief_description> All User Interface nodes inherit from Control. Features anchors and margins to adapt its position and size to its parent. </brief_description> @@ -117,6 +117,16 @@ <argument index="1" name="data" type="Variant"> </argument> <description> + Godot calls this method to test if [code]data[/code] from a control's [method get_drag_data] can be dropped at [code]position[/code]. [code]position[/code] is local to this control. + This method should only be used to test the data. Process the data in [method drop_data]. + [codeblock] + extends Control + + func can_drop_data(position, data): + # check position if it is relevant to you + # otherwise just check data + return typeof(data) == TYPE_DICTIONARY and data.has('expected') + [/codeblock] </description> </method> <method name="drop_data" qualifiers="virtual"> @@ -127,6 +137,16 @@ <argument index="1" name="data" type="Variant"> </argument> <description> + Godot calls this method to pass you the [code]data[/code] from a control's [method get_drag_data] result. Godot first calls [method can_drop_data] to test if [code]data[/code] is allowed to drop at [code]position[/code] where [code]position[/code] is local to this control. + [codeblock] + extends ColorRect + + func can_drop_data(position, data): + return typeof(data) == TYPE_DICTIONARY and data.has('color') + + func drop_data(position, data): + color = data['color'] + [/codeblock] </description> </method> <method name="force_drag"> @@ -137,6 +157,8 @@ <argument index="1" name="preview" type="Control"> </argument> <description> + Forces drag and bypasses [method get_drag_data] and [method set_drag_preview] by passing [code]data[/code] and [code]preview[/code]. Drag will start even if the mouse is neither over nor pressed on this control. + The methods [method can_drop_data] and [method drop_data] must be implemented on controls that want to recieve drop data. </description> </method> <method name="get_begin" qualifiers="const"> @@ -186,6 +208,16 @@ <argument index="0" name="position" type="Vector2"> </argument> <description> + Godot calls this method to get data that can be dragged and dropped onto controls that expect drop data. Return null if there is no data to drag. Controls that want to recieve drop data should implement [method can_drop_data] and [method drop_data]. [code]position[/code] is local to this control. Drag may be forced with [method force_drag]. + A preview that will follow the mouse that should represent the data can be set with [method set_drag_preview]. A good time to set the preview is in this method. + [codeblock] + extends Control + + func get_drag_data(position): + var mydata = make_data() + set_drag_preview(make_preview(mydata)) + return mydata + [/codeblock] </description> </method> <method name="get_end" qualifiers="const"> @@ -485,6 +517,28 @@ <argument index="0" name="target" type="Control"> </argument> <description> + Forwards the handling of this control's drag and drop to [code]target[/code] control. + Forwarding can be implemented in the target control similar to the methods [method get_drag_data], [method can_drop_data], and [method drop_data] but with two differences: + 1. The function name must be suffixed with [b]_fw[/b] + 2. The function must take an extra argument that is the control doing the forwarding + [codeblock] + # ThisControl.gd + extends Control + func _ready(): + set_drag_forwarding(target_control) + + # TargetControl.gd + extends Control + func can_drop_data_fw(position, data, from_control): + return true + + func drop_data_fw(position, data, from_control): + my_handle_data(data) + + func get_drag_data_fw(position, from_control): + set_drag_preview(my_preview) + return my_data() + [/codeblock] </description> </method> <method name="set_drag_preview"> @@ -493,6 +547,7 @@ <argument index="0" name="control" type="Control"> </argument> <description> + Shows the given control at the mouse pointer. A good time to call this method is in [method get_drag_data]. </description> </method> <method name="set_end"> diff --git a/doc/classes/ConvexPolygonShape.xml b/doc/classes/ConvexPolygonShape.xml index 2b809ca80a..757b053ffe 100644 --- a/doc/classes/ConvexPolygonShape.xml +++ b/doc/classes/ConvexPolygonShape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ConvexPolygonShape" inherits="Shape" category="Core" version="3.0-stable"> +<class name="ConvexPolygonShape" inherits="Shape" category="Core" version="3.1"> <brief_description> Convex polygon shape for 3D physics. </brief_description> diff --git a/doc/classes/ConvexPolygonShape2D.xml b/doc/classes/ConvexPolygonShape2D.xml index b5ce052b4b..6b31149c2f 100644 --- a/doc/classes/ConvexPolygonShape2D.xml +++ b/doc/classes/ConvexPolygonShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ConvexPolygonShape2D" inherits="Shape2D" category="Core" version="3.0-stable"> +<class name="ConvexPolygonShape2D" inherits="Shape2D" category="Core" version="3.1"> <brief_description> Convex Polygon Shape for 2D physics. </brief_description> diff --git a/doc/classes/CubeMap.xml b/doc/classes/CubeMap.xml index 26fda49803..ac5359738e 100644 --- a/doc/classes/CubeMap.xml +++ b/doc/classes/CubeMap.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CubeMap" inherits="Resource" category="Core" version="3.0-stable"> +<class name="CubeMap" inherits="Resource" category="Core" version="3.1"> <brief_description> A CubeMap is a 6 sided 3D texture. </brief_description> diff --git a/doc/classes/CubeMesh.xml b/doc/classes/CubeMesh.xml index c7ec4d9dfe..cef412bbde 100644 --- a/doc/classes/CubeMesh.xml +++ b/doc/classes/CubeMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CubeMesh" inherits="PrimitiveMesh" category="Core" version="3.0-stable"> +<class name="CubeMesh" inherits="PrimitiveMesh" category="Core" version="3.1"> <brief_description> Generate an axis-aligned cuboid [PrimitiveMesh]. </brief_description> diff --git a/doc/classes/Curve.xml b/doc/classes/Curve.xml index 388d8ab54f..c7f2f7bb8d 100644 --- a/doc/classes/Curve.xml +++ b/doc/classes/Curve.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Curve" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Curve" inherits="Resource" category="Core" version="3.1"> <brief_description> A mathematic curve. </brief_description> diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml index 2dbfcbc6ec..03db9c2ea1 100644 --- a/doc/classes/Curve2D.xml +++ b/doc/classes/Curve2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Curve2D" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Curve2D" inherits="Resource" category="Core" version="3.1"> <brief_description> Describes a Bezier curve in 2D space. </brief_description> diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml index acb6b0d72f..f2308de12c 100644 --- a/doc/classes/Curve3D.xml +++ b/doc/classes/Curve3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Curve3D" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Curve3D" inherits="Resource" category="Core" version="3.1"> <brief_description> Describes a Bezier curve in 3D space. </brief_description> diff --git a/doc/classes/CurveTexture.xml b/doc/classes/CurveTexture.xml index bc090d623a..10e8a61f99 100644 --- a/doc/classes/CurveTexture.xml +++ b/doc/classes/CurveTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CurveTexture" inherits="Texture" category="Core" version="3.0-stable"> +<class name="CurveTexture" inherits="Texture" category="Core" version="3.1"> <brief_description> A texture that shows a curve. </brief_description> diff --git a/doc/classes/CylinderMesh.xml b/doc/classes/CylinderMesh.xml index e57ffd2841..623830371a 100644 --- a/doc/classes/CylinderMesh.xml +++ b/doc/classes/CylinderMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CylinderMesh" inherits="PrimitiveMesh" category="Core" version="3.0-stable"> +<class name="CylinderMesh" inherits="PrimitiveMesh" category="Core" version="3.1"> <brief_description> Class representing a cylindrical [PrimitiveMesh]. </brief_description> diff --git a/doc/classes/DampedSpringJoint2D.xml b/doc/classes/DampedSpringJoint2D.xml index 950817dc04..12e29cec32 100644 --- a/doc/classes/DampedSpringJoint2D.xml +++ b/doc/classes/DampedSpringJoint2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="DampedSpringJoint2D" inherits="Joint2D" category="Core" version="3.0-stable"> +<class name="DampedSpringJoint2D" inherits="Joint2D" category="Core" version="3.1"> <brief_description> Damped spring constraint for 2D physics. </brief_description> diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml index 37845dbae4..d7118265f1 100644 --- a/doc/classes/Dictionary.xml +++ b/doc/classes/Dictionary.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Dictionary" category="Built-In Types" version="3.0-stable"> +<class name="Dictionary" category="Built-In Types" version="3.1"> <brief_description> Dictionary type. </brief_description> diff --git a/doc/classes/DirectionalLight.xml b/doc/classes/DirectionalLight.xml index bbb8936a12..5e492b74da 100644 --- a/doc/classes/DirectionalLight.xml +++ b/doc/classes/DirectionalLight.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="DirectionalLight" inherits="Light" category="Core" version="3.0-stable"> +<class name="DirectionalLight" inherits="Light" category="Core" version="3.1"> <brief_description> Directional Light, such as the Sun or the Moon. </brief_description> diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml index bfd1e2872d..040ccf4462 100644 --- a/doc/classes/Directory.xml +++ b/doc/classes/Directory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Directory" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Directory" inherits="Reference" category="Core" version="3.1"> <brief_description> Type used to handle the filesystem. </brief_description> diff --git a/doc/classes/DynamicFont.xml b/doc/classes/DynamicFont.xml index 06291c1e61..03752c6e89 100644 --- a/doc/classes/DynamicFont.xml +++ b/doc/classes/DynamicFont.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="DynamicFont" inherits="Font" category="Core" version="3.0-stable"> +<class name="DynamicFont" inherits="Font" category="Core" version="3.1"> <brief_description> DynamicFont renders vector font files at runtime. </brief_description> diff --git a/doc/classes/DynamicFontData.xml b/doc/classes/DynamicFontData.xml index 5f4e598f36..7b34d02316 100644 --- a/doc/classes/DynamicFontData.xml +++ b/doc/classes/DynamicFontData.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="DynamicFontData" inherits="Resource" category="Core" version="3.0-stable"> +<class name="DynamicFontData" inherits="Resource" category="Core" version="3.1"> <brief_description> Used with [DynamicFont] to describe the location of a font file. </brief_description> @@ -16,7 +16,19 @@ <member name="font_path" type="String" setter="set_font_path" getter="get_font_path"> The path to the vector font file. </member> + <member name="hinting" type="int" setter="set_hinting" getter="get_hinting" enum="DynamicFontData.Hinting"> + The font hinting mode used by FreeType. + </member> </members> <constants> + <constant name="HINTING_NONE" value="0" enum="Hinting"> + Disable font hinting (smoother but less crisp). + </constant> + <constant name="HINTING_LIGHT" value="1" enum="Hinting"> + Use the light font hinting mode. + </constant> + <constant name="HINTING_NORMAL" value="2" enum="Hinting"> + Use the default font hinting mode (crisper but less smooth). + </constant> </constants> </class> diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml index ede892e7ef..a6b72d08ff 100644 --- a/doc/classes/EditorExportPlugin.xml +++ b/doc/classes/EditorExportPlugin.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorExportPlugin" inherits="Reference" category="Core" version="3.0-stable"> +<class name="EditorExportPlugin" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/EditorFileDialog.xml b/doc/classes/EditorFileDialog.xml index b3a12dbede..fed9e264db 100644 --- a/doc/classes/EditorFileDialog.xml +++ b/doc/classes/EditorFileDialog.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorFileDialog" inherits="ConfirmationDialog" category="Core" version="3.0-stable"> +<class name="EditorFileDialog" inherits="ConfirmationDialog" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml index 1eda817d33..347acce2dd 100644 --- a/doc/classes/EditorFileSystem.xml +++ b/doc/classes/EditorFileSystem.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorFileSystem" inherits="Node" category="Core" version="3.0-stable"> +<class name="EditorFileSystem" inherits="Node" category="Core" version="3.1"> <brief_description> Resource filesystem, as the editor sees it. </brief_description> diff --git a/doc/classes/EditorFileSystemDirectory.xml b/doc/classes/EditorFileSystemDirectory.xml index 005bebaca8..f5d0471037 100644 --- a/doc/classes/EditorFileSystemDirectory.xml +++ b/doc/classes/EditorFileSystemDirectory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorFileSystemDirectory" inherits="Object" category="Core" version="3.0-stable"> +<class name="EditorFileSystemDirectory" inherits="Object" category="Core" version="3.1"> <brief_description> A diretory for the resource filesystem. </brief_description> diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml index 85f3d80607..406bd7b7df 100644 --- a/doc/classes/EditorImportPlugin.xml +++ b/doc/classes/EditorImportPlugin.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorImportPlugin" inherits="Reference" category="Core" version="3.0-stable"> +<class name="EditorImportPlugin" inherits="Reference" category="Core" version="3.1"> <brief_description> Registers a custom resource importer in the editor. Use the class to parse any file and import it as a new resource type. </brief_description> diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 61c93becde..006a7ca690 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorInterface" inherits="Node" category="Core" version="3.0-stable"> +<class name="EditorInterface" inherits="Node" category="Core" version="3.1"> <brief_description> Editor interface and main components. </brief_description> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index b3aca798a4..0a8d95d25d 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorPlugin" inherits="Node" category="Core" version="3.0-stable"> +<class name="EditorPlugin" inherits="Node" category="Core" version="3.1"> <brief_description> Used by the editor to extend its functionality. </brief_description> @@ -12,6 +12,17 @@ <demos> </demos> <methods> + <method name="add_autoload_singleton"> + <return type="void"> + </return> + <argument index="0" name="name" type="String"> + </argument> + <argument index="1" name="path" type="String"> + </argument> + <description> + Add a script at [code]path[/code] to the Autoload list as [code]name[/code]. + </description> + </method> <method name="add_control_to_bottom_panel"> <return type="ToolButton"> </return> @@ -265,6 +276,15 @@ Queue save the project's editor layout. </description> </method> + <method name="remove_autoload_singleton"> + <return type="void"> + </return> + <argument index="0" name="name" type="String"> + </argument> + <description> + Remove an Autoload [code]name[/code] from the list. + </description> + </method> <method name="remove_control_from_bottom_panel"> <return type="void"> </return> diff --git a/doc/classes/EditorResourceConversionPlugin.xml b/doc/classes/EditorResourceConversionPlugin.xml index 9facba18b0..ad0b7b0586 100644 --- a/doc/classes/EditorResourceConversionPlugin.xml +++ b/doc/classes/EditorResourceConversionPlugin.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorResourceConversionPlugin" inherits="Reference" category="Core" version="3.0-stable"> +<class name="EditorResourceConversionPlugin" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/EditorResourcePreview.xml b/doc/classes/EditorResourcePreview.xml index 9b14771f0f..3b3e8a8369 100644 --- a/doc/classes/EditorResourcePreview.xml +++ b/doc/classes/EditorResourcePreview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorResourcePreview" inherits="Node" category="Core" version="3.0-stable"> +<class name="EditorResourcePreview" inherits="Node" category="Core" version="3.1"> <brief_description> Helper to generate previews of resources or files. </brief_description> diff --git a/doc/classes/EditorResourcePreviewGenerator.xml b/doc/classes/EditorResourcePreviewGenerator.xml index d116e56cf7..fb9af47b1f 100644 --- a/doc/classes/EditorResourcePreviewGenerator.xml +++ b/doc/classes/EditorResourcePreviewGenerator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorResourcePreviewGenerator" inherits="Reference" category="Core" version="3.0-stable"> +<class name="EditorResourcePreviewGenerator" inherits="Reference" category="Core" version="3.1"> <brief_description> Custom generator of previews. </brief_description> diff --git a/doc/classes/EditorSceneImporter.xml b/doc/classes/EditorSceneImporter.xml index 31846ed401..6394dfdfe9 100644 --- a/doc/classes/EditorSceneImporter.xml +++ b/doc/classes/EditorSceneImporter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorSceneImporter" inherits="Reference" category="Core" version="3.0-stable"> +<class name="EditorSceneImporter" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/EditorScenePostImport.xml b/doc/classes/EditorScenePostImport.xml index 4c0709249e..664ea33dd6 100644 --- a/doc/classes/EditorScenePostImport.xml +++ b/doc/classes/EditorScenePostImport.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorScenePostImport" inherits="Reference" category="Core" version="3.0-stable"> +<class name="EditorScenePostImport" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml index a3cd12ab50..1c22095b37 100644 --- a/doc/classes/EditorScript.xml +++ b/doc/classes/EditorScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorScript" inherits="Reference" category="Core" version="3.0-stable"> +<class name="EditorScript" inherits="Reference" category="Core" version="3.1"> <brief_description> Base script that can be used to add extension functions to the editor. </brief_description> diff --git a/doc/classes/EditorSelection.xml b/doc/classes/EditorSelection.xml index 0424ab5e43..4edd8583a0 100644 --- a/doc/classes/EditorSelection.xml +++ b/doc/classes/EditorSelection.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorSelection" inherits="Object" category="Core" version="3.0-stable"> +<class name="EditorSelection" inherits="Object" category="Core" version="3.1"> <brief_description> Manages the SceneTree selection in the editor. </brief_description> diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index a37ea0fec7..cdd9560eda 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorSettings" inherits="Resource" category="Core" version="3.0-stable"> +<class name="EditorSettings" inherits="Resource" category="Core" version="3.1"> <brief_description> Object that holds the project-independent editor settings. </brief_description> diff --git a/doc/classes/EditorSpatialGizmo.xml b/doc/classes/EditorSpatialGizmo.xml index ba026166bb..58d2671968 100644 --- a/doc/classes/EditorSpatialGizmo.xml +++ b/doc/classes/EditorSpatialGizmo.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EditorSpatialGizmo" inherits="SpatialGizmo" category="Core" version="3.0-stable"> +<class name="EditorSpatialGizmo" inherits="SpatialGizmo" category="Core" version="3.1"> <brief_description> Custom gizmo for editing Spatial objects. </brief_description> diff --git a/doc/classes/EncodedObjectAsID.xml b/doc/classes/EncodedObjectAsID.xml index 604ce42516..8e6a117ea2 100644 --- a/doc/classes/EncodedObjectAsID.xml +++ b/doc/classes/EncodedObjectAsID.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="EncodedObjectAsID" inherits="Reference" category="Core" version="3.0-stable"> +<class name="EncodedObjectAsID" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index ad5e75bad5..ea3c404346 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Engine" inherits="Object" category="Core" version="3.0-stable"> +<class name="Engine" inherits="Object" category="Core" version="3.1"> <brief_description> Access to basic engine properties. </brief_description> diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index ea35ef89f3..18adaa645c 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Environment" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Environment" inherits="Resource" category="Core" version="3.1"> <brief_description> Resource for environment nodes (like [WorldEnvironment]) that define multiple rendering options. </brief_description> <description> - Resource for environment nodes (like [WorldEnvironment]) that define multiple environment operations (such as background [Sky] or [Color], ambient light, fog, depth-of-field...). These parameters affect the final render of the scene. The order of these operations is: - - DOF Blur + Resource for environment nodes (like [WorldEnvironment]) that define multiple environment operations (such as background [Sky] or [Color], ambient light, fog, depth-of-field...). These parameters affect the final render of the scene. The order of these operations is: + + - DOF Blur - Motion Blur - Bloom - Tonemap (auto exposure) @@ -13,7 +14,7 @@ </description> <tutorials> http://docs.godotengine.org/en/3.0/tutorials/3d/environment_and_post_processing.html - http://docs.godotengine.org/en/3.0/tutorials/3d/high_dynamic_range.html + http://docs.godotengine.org/en/3.0/tutorials/3d/high_dynamic_range.html </tutorials> <demos> </demos> diff --git a/doc/classes/File.xml b/doc/classes/File.xml index 3ac2a7e643..534323348e 100644 --- a/doc/classes/File.xml +++ b/doc/classes/File.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="File" inherits="Reference" category="Core" version="3.0-stable"> +<class name="File" inherits="Reference" category="Core" version="3.1"> <brief_description> Type to handle file reading and writing operations. </brief_description> @@ -163,6 +163,20 @@ Returns a [String] saved in Pascal format from the file. </description> </method> + <method name="get_path"> + <return type="String"> + </return> + <description> + Returns the path as a [String] for the current open file. + </description> + </method> + <method name="get_path_absolute"> + <return type="String"> + </return> + <description> + Returns the absolute path as a [String] for the current open file. + </description> + </method> <method name="get_position" qualifiers="const"> <return type="int"> </return> @@ -380,7 +394,7 @@ <members> <member name="endian_swap" type="bool" setter="set_endian_swap" getter="get_endian_swap"> If [code]true[/code] the file's endianness is swapped. Use this if you're dealing with files written in big endian machines. - Note that this is about the file format, not CPU type. This is always reseted to [code]false[/code] whenever you open the file. + Note that this is about the file format, not CPU type. This is always reset to [code]false[/code] whenever you open the file. </member> </members> <constants> diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml index cee64b7ade..b165d8fb8c 100644 --- a/doc/classes/FileDialog.xml +++ b/doc/classes/FileDialog.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="FileDialog" inherits="ConfirmationDialog" category="Core" version="3.0-stable"> +<class name="FileDialog" inherits="ConfirmationDialog" category="Core" version="3.1"> <brief_description> Dialog for selecting files or directories in the filesystem. </brief_description> diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml index 7190067b09..376d234ec3 100644 --- a/doc/classes/Font.xml +++ b/doc/classes/Font.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Font" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Font" inherits="Resource" category="Core" version="3.1"> <brief_description> Internationalized font and text drawing support. </brief_description> diff --git a/doc/classes/FuncRef.xml b/doc/classes/FuncRef.xml index 8ad6da9adc..02b9dcfd88 100644 --- a/doc/classes/FuncRef.xml +++ b/doc/classes/FuncRef.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="FuncRef" inherits="Reference" category="Core" version="3.0-stable"> +<class name="FuncRef" inherits="Reference" category="Core" version="3.1"> <brief_description> Reference to a function in an object. </brief_description> diff --git a/doc/classes/GIProbe.xml b/doc/classes/GIProbe.xml index e9f1dfecaf..fde91d09ac 100644 --- a/doc/classes/GIProbe.xml +++ b/doc/classes/GIProbe.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GIProbe" inherits="VisualInstance" category="Core" version="3.0-stable"> +<class name="GIProbe" inherits="VisualInstance" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/GIProbeData.xml b/doc/classes/GIProbeData.xml index 32a891e277..b2186d7647 100644 --- a/doc/classes/GIProbeData.xml +++ b/doc/classes/GIProbeData.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GIProbeData" inherits="Resource" category="Core" version="3.0-stable"> +<class name="GIProbeData" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/Generic6DOFJoint.xml b/doc/classes/Generic6DOFJoint.xml index 4be44b3819..f49f4231ef 100644 --- a/doc/classes/Generic6DOFJoint.xml +++ b/doc/classes/Generic6DOFJoint.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Generic6DOFJoint" inherits="Joint" category="Core" version="3.0-stable"> +<class name="Generic6DOFJoint" inherits="Joint" category="Core" version="3.1"> <brief_description> The generic 6 degrees of freedom joint can implement a variety of joint-types by locking certain axes' rotation or translation. </brief_description> diff --git a/doc/classes/Geometry.xml b/doc/classes/Geometry.xml index b3f63daf9c..7b25f87b19 100644 --- a/doc/classes/Geometry.xml +++ b/doc/classes/Geometry.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Geometry" inherits="Object" category="Core" version="3.0-stable"> +<class name="Geometry" inherits="Object" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/GeometryInstance.xml b/doc/classes/GeometryInstance.xml index 8dd3c23ee2..aea1882dae 100644 --- a/doc/classes/GeometryInstance.xml +++ b/doc/classes/GeometryInstance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GeometryInstance" inherits="VisualInstance" category="Core" version="3.0-stable"> +<class name="GeometryInstance" inherits="VisualInstance" category="Core" version="3.1"> <brief_description> Base node for geometry based visual instances. </brief_description> diff --git a/doc/classes/Gradient.xml b/doc/classes/Gradient.xml index 8b4bf4d448..df4a507b65 100644 --- a/doc/classes/Gradient.xml +++ b/doc/classes/Gradient.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Gradient" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Gradient" inherits="Resource" category="Core" version="3.1"> <brief_description> Color interpolator node. </brief_description> diff --git a/doc/classes/GradientTexture.xml b/doc/classes/GradientTexture.xml index 127a6d8204..9d2465e23d 100644 --- a/doc/classes/GradientTexture.xml +++ b/doc/classes/GradientTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GradientTexture" inherits="Texture" category="Core" version="3.0-stable"> +<class name="GradientTexture" inherits="Texture" category="Core" version="3.1"> <brief_description> Gradient filled texture. </brief_description> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index 2090155e85..5fb12612ab 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GraphEdit" inherits="Control" category="Core" version="3.0-stable"> +<class name="GraphEdit" inherits="Control" category="Core" version="3.1"> <brief_description> GraphEdit is an area capable of showing various GraphNodes. It manages connection events between them. </brief_description> diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index ce8cb053ce..4c39720d69 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GraphNode" inherits="Container" category="Core" version="3.0-stable"> +<class name="GraphNode" inherits="Container" category="Core" version="3.1"> <brief_description> A GraphNode is a container with several input and output slots allowing connections between GraphNodes. Slots can have different, incompatible types. </brief_description> diff --git a/doc/classes/GridContainer.xml b/doc/classes/GridContainer.xml index 8463acc1d4..7f70a8b7b4 100644 --- a/doc/classes/GridContainer.xml +++ b/doc/classes/GridContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GridContainer" inherits="Container" category="Core" version="3.0-stable"> +<class name="GridContainer" inherits="Container" category="Core" version="3.1"> <brief_description> Grid container used to arrange elements in a grid like layout </brief_description> diff --git a/doc/classes/GrooveJoint2D.xml b/doc/classes/GrooveJoint2D.xml index c1aa10026c..a15c658f78 100644 --- a/doc/classes/GrooveJoint2D.xml +++ b/doc/classes/GrooveJoint2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GrooveJoint2D" inherits="Joint2D" category="Core" version="3.0-stable"> +<class name="GrooveJoint2D" inherits="Joint2D" category="Core" version="3.1"> <brief_description> Groove constraint for 2D physics. </brief_description> diff --git a/doc/classes/HBoxContainer.xml b/doc/classes/HBoxContainer.xml index 3597b4d2d0..9c86f17ef1 100644 --- a/doc/classes/HBoxContainer.xml +++ b/doc/classes/HBoxContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="HBoxContainer" inherits="BoxContainer" category="Core" version="3.0-stable"> +<class name="HBoxContainer" inherits="BoxContainer" category="Core" version="3.1"> <brief_description> Horizontal box container. </brief_description> diff --git a/doc/classes/HScrollBar.xml b/doc/classes/HScrollBar.xml index ed0a5ae3ad..61759c4f94 100644 --- a/doc/classes/HScrollBar.xml +++ b/doc/classes/HScrollBar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="HScrollBar" inherits="ScrollBar" category="Core" version="3.0-stable"> +<class name="HScrollBar" inherits="ScrollBar" category="Core" version="3.1"> <brief_description> Horizontal scroll bar. </brief_description> diff --git a/doc/classes/HSeparator.xml b/doc/classes/HSeparator.xml index ac02f76146..1a9cf25857 100644 --- a/doc/classes/HSeparator.xml +++ b/doc/classes/HSeparator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="HSeparator" inherits="Separator" category="Core" version="3.0-stable"> +<class name="HSeparator" inherits="Separator" category="Core" version="3.1"> <brief_description> Horizontal separator. </brief_description> diff --git a/doc/classes/HSlider.xml b/doc/classes/HSlider.xml index 791bc5159b..6d5acded3c 100644 --- a/doc/classes/HSlider.xml +++ b/doc/classes/HSlider.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="HSlider" inherits="Slider" category="Core" version="3.0-stable"> +<class name="HSlider" inherits="Slider" category="Core" version="3.1"> <brief_description> Horizontal slider. </brief_description> diff --git a/doc/classes/HSplitContainer.xml b/doc/classes/HSplitContainer.xml index 68a794eb9f..45b99c85a6 100644 --- a/doc/classes/HSplitContainer.xml +++ b/doc/classes/HSplitContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="HSplitContainer" inherits="SplitContainer" category="Core" version="3.0-stable"> +<class name="HSplitContainer" inherits="SplitContainer" category="Core" version="3.1"> <brief_description> Horizontal split container. </brief_description> diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index 3fa780e892..5bd7c4cd3e 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="HTTPClient" inherits="Reference" category="Core" version="3.0-stable"> +<class name="HTTPClient" inherits="Reference" category="Core" version="3.1"> <brief_description> Hyper-text transfer protocol client. </brief_description> @@ -384,7 +384,7 @@ HTTP status code [code]429 Too Many Requests[/code]. The user has sent too many requests in a given amount of time (see "rate limiting"). Back off and increase time between requests or try again later. </constant> <constant name="RESPONSE_REQUEST_HEADER_FIELDS_TOO_LARGE" value="431" enum="ResponseCode"> - HTTP status code [code]431 Rquest Header Fields Too Large[/code]. The server is unwilling to process the request because its header fields are too large. The request MAY be resubmitted after reducing the size of the request header fields. + HTTP status code [code]431 Request Header Fields Too Large[/code]. The server is unwilling to process the request because its header fields are too large. The request MAY be resubmitted after reducing the size of the request header fields. </constant> <constant name="RESPONSE_UNAVAILABLE_FOR_LEGAL_REASONS" value="451" enum="ResponseCode"> HTTP status code [code]451 Response Unavailable For Legal Reasons[/code]. The server is denying access to the resource as a consequence of a legal demand. diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index 8b8cc6b744..010ef6d9d5 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="HTTPRequest" inherits="Node" category="Core" version="3.0-stable"> +<class name="HTTPRequest" inherits="Node" category="Core" version="3.1"> <brief_description> A node with the ability to send HTTP requests. </brief_description> diff --git a/doc/classes/HingeJoint.xml b/doc/classes/HingeJoint.xml index 367867dd00..3c5719056b 100644 --- a/doc/classes/HingeJoint.xml +++ b/doc/classes/HingeJoint.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="HingeJoint" inherits="Joint" category="Core" version="3.0-stable"> +<class name="HingeJoint" inherits="Joint" category="Core" version="3.1"> <brief_description> A hinge between two 3D bodies. </brief_description> diff --git a/doc/classes/IP.xml b/doc/classes/IP.xml index d01d88590e..bcb15e44fc 100644 --- a/doc/classes/IP.xml +++ b/doc/classes/IP.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="IP" inherits="Object" category="Core" version="3.0-stable"> +<class name="IP" inherits="Object" category="Core" version="3.1"> <brief_description> Internet protocol (IP) support functions like DNS resolution. </brief_description> diff --git a/doc/classes/IP_Unix.xml b/doc/classes/IP_Unix.xml index ba33793d72..0dd4455562 100644 --- a/doc/classes/IP_Unix.xml +++ b/doc/classes/IP_Unix.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="IP_Unix" inherits="IP" category="Core" version="3.0-stable"> +<class name="IP_Unix" inherits="IP" category="Core" version="3.1"> <brief_description> Unix IP support. See [IP]. </brief_description> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index a38bfeb35e..c1bd8d34eb 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Image" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Image" inherits="Resource" category="Core" version="3.1"> <brief_description> Image datatype. </brief_description> @@ -436,74 +436,109 @@ <constant name="FORMAT_LA8" value="1" enum="Format"> </constant> <constant name="FORMAT_R8" value="2" enum="Format"> + OpenGL texture format RED with a single component and a bitdepth of 8. </constant> <constant name="FORMAT_RG8" value="3" enum="Format"> + OpenGL texture format RG with two components and a bitdepth of 8 for each. </constant> <constant name="FORMAT_RGB8" value="4" enum="Format"> + OpenGL texture format RGB with three components, each with a bitdepth of 8. </constant> <constant name="FORMAT_RGBA8" value="5" enum="Format"> + OpenGL texture format RGBA with four components, each with a bitdepth of 8. </constant> <constant name="FORMAT_RGBA4444" value="6" enum="Format"> + OpenGL texture format RGBA with four components, each with a bitdepth of 4. </constant> <constant name="FORMAT_RGBA5551" value="7" enum="Format"> + OpenGL texture format GL_RGB5_A1 where 5 bits of depth for each component of RGB and one bit for alpha. </constant> <constant name="FORMAT_RF" value="8" enum="Format"> + OpenGL texture format GL_R32F where there's one component, a 32-bit floating-point value. </constant> <constant name="FORMAT_RGF" value="9" enum="Format"> + OpenGL texture format GL_RG32F where there are two components, each a 32-bit floating-point values. </constant> <constant name="FORMAT_RGBF" value="10" enum="Format"> + OpenGL texture format GL_RGB32F where there are three components, each a 32-bit floating-point values. </constant> <constant name="FORMAT_RGBAF" value="11" enum="Format"> + OpenGL texture format GL_RGBA32F where there are four components, each a 32-bit floating-point values. </constant> <constant name="FORMAT_RH" value="12" enum="Format"> + OpenGL texture format GL_R32F where there's one component, a 16-bit "half-precision" floating-point value. </constant> <constant name="FORMAT_RGH" value="13" enum="Format"> + OpenGL texture format GL_RG32F where there's two components, each a 16-bit "half-precision" floating-point value. </constant> <constant name="FORMAT_RGBH" value="14" enum="Format"> + OpenGL texture format GL_RGB32F where there's three components, each a 16-bit "half-precision" floating-point value. </constant> <constant name="FORMAT_RGBAH" value="15" enum="Format"> + OpenGL texture format GL_RGBA32F where there's four components, each a 16-bit "half-precision" floating-point value. </constant> <constant name="FORMAT_RGBE9995" value="16" enum="Format"> + A special OpenGL texture format where the three color components have 9 bits of precision and all three share a single exponent. </constant> <constant name="FORMAT_DXT1" value="17" enum="Format"> + The S3TC texture format that uses Block Compression 1, and is the smallest variation of S3TC, only providing 1 bit of alpha and color data being premultiplied with alpha. More information can be found at https://www.khronos.org/opengl/wiki/S3_Texture_Compression. </constant> <constant name="FORMAT_DXT3" value="18" enum="Format"> + The S3TC texture format that uses Block Compression 2, and color data is interpreted as not having been premultiplied by alpha. Well suited for images with sharp alpha transitions between translucent and opaque areas. </constant> <constant name="FORMAT_DXT5" value="19" enum="Format"> + The S3TC texture format also known as Block Compression 3 or BC3 that contains 64 bits of alpha channel data followed by 64 bits of DXT1-encoded color data. Color data is not premultiplied by alpha, same as DXT3. DXT5 generally produces superior results for transparency gradients than DXT3. </constant> <constant name="FORMAT_RGTC_R" value="20" enum="Format"> + Texture format that uses Red Green Texture Compression, normalizing the red channel data using the same compression algorithm that DXT5 uses for the alpha channel. More information can be found here https://www.khronos.org/opengl/wiki/Red_Green_Texture_Compression. </constant> <constant name="FORMAT_RGTC_RG" value="21" enum="Format"> + Texture format that uses Red Green Texture Compression, normalizing the red and green channel data using the same compression algorithm that DXT5 uses for the alpha channel. </constant> <constant name="FORMAT_BPTC_RGBA" value="22" enum="Format"> + Texture format that uses BPTC compression with unsigned normalized RGBA components. More information can be found at https://www.khronos.org/opengl/wiki/BPTC_Texture_Compression. </constant> <constant name="FORMAT_BPTC_RGBF" value="23" enum="Format"> + Texture format that uses BPTC compression with signed floating-point RGB components. </constant> <constant name="FORMAT_BPTC_RGBFU" value="24" enum="Format"> + Texture format that uses BPTC compression with unsigned floating-point RGB components. </constant> <constant name="FORMAT_PVRTC2" value="25" enum="Format"> + Texture format used on PowerVR-supported mobile platforms, uses 2 bit color depth with no alpha. More information on PVRTC can be found here https://en.wikipedia.org/wiki/PVRTC. </constant> <constant name="FORMAT_PVRTC2A" value="26" enum="Format"> + Same as PVRTC2, but with an alpha component. </constant> <constant name="FORMAT_PVRTC4" value="27" enum="Format"> + Similar to PVRTC2, but with 4 bit color depth and no alpha. </constant> <constant name="FORMAT_PVRTC4A" value="28" enum="Format"> + Same as PVRTC4, but with an alpha component. </constant> <constant name="FORMAT_ETC" value="29" enum="Format"> + Ericsson Texture Compression format, also referred to as 'ETC1', and is part of the OpenGL ES graphics standard. An overview of the format is given at https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC1. </constant> <constant name="FORMAT_ETC2_R11" value="30" enum="Format"> + Ericsson Texture Compression format 2 variant R11_EAC, which provides one channel of unsigned data. </constant> <constant name="FORMAT_ETC2_R11S" value="31" enum="Format"> + Ericsson Texture Compression format 2 variant SIGNED_R11_EAC, which provides one channel of signed data. </constant> <constant name="FORMAT_ETC2_RG11" value="32" enum="Format"> + Ericsson Texture Compression format 2 variant RG11_EAC, which provides two channels of unsigned data. </constant> <constant name="FORMAT_ETC2_RG11S" value="33" enum="Format"> + Ericsson Texture Compression format 2 variant SIGNED_RG11_EAC, which provides two channels of signed data. </constant> <constant name="FORMAT_ETC2_RGB8" value="34" enum="Format"> + Ericsson Texture Compression format 2 variant RGB8, which is a followup of ETC1 and compresses RGB888 data. </constant> <constant name="FORMAT_ETC2_RGBA8" value="35" enum="Format"> + Ericsson Texture Compression format 2 variant RGBA8, which compresses RGBA8888 data with full alpha support. </constant> <constant name="FORMAT_ETC2_RGB8A1" value="36" enum="Format"> + Ericsson Texture Compression format 2 variant RGB8_PUNCHTHROUGH_ALPHA1, which compresses RGBA data to make alpha either fully transparent or fully opaque. </constant> <constant name="FORMAT_MAX" value="37" enum="Format"> </constant> diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml index 96261c8e12..9a5937299c 100644 --- a/doc/classes/ImageTexture.xml +++ b/doc/classes/ImageTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ImageTexture" inherits="Texture" category="Core" version="3.0-stable"> +<class name="ImageTexture" inherits="Texture" category="Core" version="3.1"> <brief_description> A [Texture] based on an [Image]. </brief_description> diff --git a/doc/classes/ImmediateGeometry.xml b/doc/classes/ImmediateGeometry.xml index 0376854bb6..29d05bf877 100644 --- a/doc/classes/ImmediateGeometry.xml +++ b/doc/classes/ImmediateGeometry.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ImmediateGeometry" inherits="GeometryInstance" category="Core" version="3.0-stable"> +<class name="ImmediateGeometry" inherits="GeometryInstance" category="Core" version="3.1"> <brief_description> Draws simple geometry from code. </brief_description> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 946b7b9bac..f3bff5a146 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Input" inherits="Object" category="Core" version="3.0-stable"> +<class name="Input" inherits="Object" category="Core" version="3.1"> <brief_description> A Singleton that deals with inputs. </brief_description> @@ -7,6 +7,7 @@ A Singleton that deals with inputs. This includes key presses, mouse buttons and movement, joypads, and input actions. Actions and their events can be set in the Project Settings / Input Map tab. Or be set with [InputMap]. </description> <tutorials> + http://docs.godotengine.org/en/3.0/tutorials/inputs/index.html </tutorials> <demos> </demos> @@ -44,7 +45,7 @@ <return type="Vector3"> </return> <description> - If the device has an accelerometer, this will return the movement. + If the device has an accelerometer, this will return the acceleration. Otherwise, it returns an empty [Vector3]. </description> </method> <method name="get_connected_joypads"> @@ -58,13 +59,14 @@ <return type="Vector3"> </return> <description> + If the device has an accelerometer, this will return the gravity. Otherwise, it returns an empty [Vector3]. </description> </method> <method name="get_gyroscope" qualifiers="const"> <return type="Vector3"> </return> <description> - If the device has a gyroscope, this will return the rate of rotation in rad/s around a device's x, y, and z axis. + If the device has a gyroscope, this will return the rate of rotation in rad/s around a device's x, y, and z axis. Otherwise, it returns an empty [Vector3]. </description> </method> <method name="get_joy_axis" qualifiers="const"> @@ -180,7 +182,8 @@ <argument index="0" name="action" type="String"> </argument> <description> - Returns [code]true[/code] when you start pressing the action event. + Returns [code]true[/code] when the user starts pressing the action event, meaning it's true only on the frame that the user pressed down the button. + This is useful for code that needs to run only once when an action is pressed, instead of every frame while it's pressed. </description> </method> <method name="is_action_just_released" qualifiers="const"> @@ -189,7 +192,7 @@ <argument index="0" name="action" type="String"> </argument> <description> - Returns [code]true[/code] when you stop pressing the action event. + Returns [code]true[/code] when the user stops pressing the action event, meaning it's true only on the frame that the user released the button. </description> </method> <method name="is_action_pressed" qualifiers="const"> @@ -259,6 +262,7 @@ <argument index="0" name="event" type="InputEvent"> </argument> <description> + Feeds an [InputEvent] to the game. Can be used to artificially trigger input events from code. </description> </method> <method name="remove_joy_mapping"> @@ -334,7 +338,7 @@ <argument index="1" name="connected" type="bool"> </argument> <description> - Emitted when a joypad device has been connected or disconnected + Emitted when a joypad device has been connected or disconnected. </description> </signal> </signals> @@ -349,40 +353,58 @@ Captures the mouse. The mouse will be hidden and unable to leave the game window. But it will still register movement and mouse button presses. </constant> <constant name="MOUSE_MODE_CONFINED" value="3" enum="MouseMode"> + Makes the mouse cursor visible but confines it to the game window. </constant> <constant name="CURSOR_ARROW" value="0" enum="CursorShape"> + Arrow cursor. Standard, default pointing cursor. </constant> <constant name="CURSOR_IBEAM" value="1" enum="CursorShape"> + I-beam cursor. Usually used to show where the text cursor will appear when the mouse is clicked. </constant> <constant name="CURSOR_POINTING_HAND" value="2" enum="CursorShape"> + Pointing hand cursor. Usually used to indicate the pointer is over a link or other interactable item. </constant> <constant name="CURSOR_CROSS" value="3" enum="CursorShape"> + Cross cursor. Typically appears over regions in which a drawing operation can be performance or for selections. </constant> <constant name="CURSOR_WAIT" value="4" enum="CursorShape"> + Wait cursor. Indicates that the application is busy performing an operation. </constant> <constant name="CURSOR_BUSY" value="5" enum="CursorShape"> + Busy cursor. See [code]CURSOR_WAIT[/code]. </constant> <constant name="CURSOR_DRAG" value="6" enum="CursorShape"> + Drag cursor. Usually displayed when dragging something. </constant> <constant name="CURSOR_CAN_DROP" value="7" enum="CursorShape"> + Can drop cursor. Usually displayed when dragging something to indicate that it can be dropped at the current position. </constant> <constant name="CURSOR_FORBIDDEN" value="8" enum="CursorShape"> + Forbidden cursor. Indicates that the current action is forbidden (for example, when dragging something) or that the control at a position is disabled. </constant> <constant name="CURSOR_VSIZE" value="9" enum="CursorShape"> + Vertical resize mouse cursor. A double headed vertical arrow. It tells the user they can resize the window or the panel vertically. </constant> <constant name="CURSOR_HSIZE" value="10" enum="CursorShape"> + Horizontal resize mouse cursor. A double headed horizontal arrow. It tells the user they can resize the window or the panel horizontally. </constant> <constant name="CURSOR_BDIAGSIZE" value="11" enum="CursorShape"> + Window resize mouse cursor. The cursor is a double headed arrow that goes from the bottom left to the top right. It tells the user they can resize the window or the panel both horizontally and vertically. </constant> <constant name="CURSOR_FDIAGSIZE" value="12" enum="CursorShape"> + Window resize mouse cursor. The cursor is a double headed arrow that goes from the top left to the bottom right, the opposite of [code]CURSOR_BDIAGSIZE[/code]. It tells the user they can resize the window or the panel both horizontally and vertically. </constant> <constant name="CURSOR_MOVE" value="13" enum="CursorShape"> + Move cursor. Indicates that something can be moved. </constant> <constant name="CURSOR_VSPLIT" value="14" enum="CursorShape"> + Vertical split mouse cursor. On Windows, it's the same as [code]CURSOR_VSIZE[/code]. </constant> <constant name="CURSOR_HSPLIT" value="15" enum="CursorShape"> + Horizontal split mouse cursor. On Windows, it's the same as [code]CURSOR_HSIZE[/code]. </constant> <constant name="CURSOR_HELP" value="16" enum="CursorShape"> + Help cursor. Usually a question mark. </constant> </constants> </class> diff --git a/doc/classes/InputDefault.xml b/doc/classes/InputDefault.xml index b804c29cd0..27bfff2e67 100644 --- a/doc/classes/InputDefault.xml +++ b/doc/classes/InputDefault.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputDefault" inherits="Input" category="Core" version="3.0-stable"> +<class name="InputDefault" inherits="Input" category="Core" version="3.1"> <brief_description> Default implementation of the [Input] class. </brief_description> diff --git a/doc/classes/InputEvent.xml b/doc/classes/InputEvent.xml index 07372d382d..b30b144614 100644 --- a/doc/classes/InputEvent.xml +++ b/doc/classes/InputEvent.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEvent" inherits="Resource" category="Core" version="3.0-stable"> +<class name="InputEvent" inherits="Resource" category="Core" version="3.1"> <brief_description> Generic input event </brief_description> diff --git a/doc/classes/InputEventAction.xml b/doc/classes/InputEventAction.xml index 5ef1711e75..e50c43c045 100644 --- a/doc/classes/InputEventAction.xml +++ b/doc/classes/InputEventAction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventAction" inherits="InputEvent" category="Core" version="3.0-stable"> +<class name="InputEventAction" inherits="InputEvent" category="Core" version="3.1"> <brief_description> Input event type for actions. </brief_description> diff --git a/doc/classes/InputEventGesture.xml b/doc/classes/InputEventGesture.xml index 4d82363b21..eb1e613b7c 100644 --- a/doc/classes/InputEventGesture.xml +++ b/doc/classes/InputEventGesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventGesture" inherits="InputEventWithModifiers" category="Core" version="3.0-stable"> +<class name="InputEventGesture" inherits="InputEventWithModifiers" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/InputEventJoypadButton.xml b/doc/classes/InputEventJoypadButton.xml index 47ba2f08ca..fdfdc10460 100644 --- a/doc/classes/InputEventJoypadButton.xml +++ b/doc/classes/InputEventJoypadButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventJoypadButton" inherits="InputEvent" category="Core" version="3.0-stable"> +<class name="InputEventJoypadButton" inherits="InputEvent" category="Core" version="3.1"> <brief_description> Input event for gamepad buttons. </brief_description> diff --git a/doc/classes/InputEventJoypadMotion.xml b/doc/classes/InputEventJoypadMotion.xml index 478f0dddfc..001dce9a03 100644 --- a/doc/classes/InputEventJoypadMotion.xml +++ b/doc/classes/InputEventJoypadMotion.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventJoypadMotion" inherits="InputEvent" category="Core" version="3.0-stable"> +<class name="InputEventJoypadMotion" inherits="InputEvent" category="Core" version="3.1"> <brief_description> Input event type for gamepad joysticks and other motions. For buttons see [code]InputEventJoypadButton[/code]. </brief_description> diff --git a/doc/classes/InputEventKey.xml b/doc/classes/InputEventKey.xml index a930491beb..dada5034f5 100644 --- a/doc/classes/InputEventKey.xml +++ b/doc/classes/InputEventKey.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventKey" inherits="InputEventWithModifiers" category="Core" version="3.0-stable"> +<class name="InputEventKey" inherits="InputEventWithModifiers" category="Core" version="3.1"> <brief_description> Input event type for keyboard events. </brief_description> diff --git a/doc/classes/InputEventMagnifyGesture.xml b/doc/classes/InputEventMagnifyGesture.xml index 880da473a6..e9a0149c56 100644 --- a/doc/classes/InputEventMagnifyGesture.xml +++ b/doc/classes/InputEventMagnifyGesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventMagnifyGesture" inherits="InputEventGesture" category="Core" version="3.0-stable"> +<class name="InputEventMagnifyGesture" inherits="InputEventGesture" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/InputEventMouse.xml b/doc/classes/InputEventMouse.xml index ca29c23634..96a0116c3c 100644 --- a/doc/classes/InputEventMouse.xml +++ b/doc/classes/InputEventMouse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventMouse" inherits="InputEventWithModifiers" category="Core" version="3.0-stable"> +<class name="InputEventMouse" inherits="InputEventWithModifiers" category="Core" version="3.1"> <brief_description> Base input event type for mouse events. </brief_description> diff --git a/doc/classes/InputEventMouseButton.xml b/doc/classes/InputEventMouseButton.xml index a8dc087eca..73190c7283 100644 --- a/doc/classes/InputEventMouseButton.xml +++ b/doc/classes/InputEventMouseButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventMouseButton" inherits="InputEventMouse" category="Core" version="3.0-stable"> +<class name="InputEventMouseButton" inherits="InputEventMouse" category="Core" version="3.1"> <brief_description> Input event type for mouse button events. </brief_description> diff --git a/doc/classes/InputEventMouseMotion.xml b/doc/classes/InputEventMouseMotion.xml index 2bd175348b..83aa28c693 100644 --- a/doc/classes/InputEventMouseMotion.xml +++ b/doc/classes/InputEventMouseMotion.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventMouseMotion" inherits="InputEventMouse" category="Core" version="3.0-stable"> +<class name="InputEventMouseMotion" inherits="InputEventMouse" category="Core" version="3.1"> <brief_description> Input event type for mouse motion events. </brief_description> diff --git a/doc/classes/InputEventPanGesture.xml b/doc/classes/InputEventPanGesture.xml index 1a16c0f385..063986ae65 100644 --- a/doc/classes/InputEventPanGesture.xml +++ b/doc/classes/InputEventPanGesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventPanGesture" inherits="InputEventGesture" category="Core" version="3.0-stable"> +<class name="InputEventPanGesture" inherits="InputEventGesture" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/InputEventScreenDrag.xml b/doc/classes/InputEventScreenDrag.xml index a9780e280a..a2ac8d587f 100644 --- a/doc/classes/InputEventScreenDrag.xml +++ b/doc/classes/InputEventScreenDrag.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventScreenDrag" inherits="InputEvent" category="Core" version="3.0-stable"> +<class name="InputEventScreenDrag" inherits="InputEvent" category="Core" version="3.1"> <brief_description> Input event type for screen drag events. (only available on mobile devices) diff --git a/doc/classes/InputEventScreenTouch.xml b/doc/classes/InputEventScreenTouch.xml index 783c36099b..64b9550f9d 100644 --- a/doc/classes/InputEventScreenTouch.xml +++ b/doc/classes/InputEventScreenTouch.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventScreenTouch" inherits="InputEvent" category="Core" version="3.0-stable"> +<class name="InputEventScreenTouch" inherits="InputEvent" category="Core" version="3.1"> <brief_description> Input event type for screen touch events. (only available on mobile devices) diff --git a/doc/classes/InputEventWithModifiers.xml b/doc/classes/InputEventWithModifiers.xml index a1b1b6523f..2d046cbfd2 100644 --- a/doc/classes/InputEventWithModifiers.xml +++ b/doc/classes/InputEventWithModifiers.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputEventWithModifiers" inherits="InputEvent" category="Core" version="3.0-stable"> +<class name="InputEventWithModifiers" inherits="InputEvent" category="Core" version="3.1"> <brief_description> Base class for keys events with modifiers. </brief_description> diff --git a/doc/classes/InputMap.xml b/doc/classes/InputMap.xml index 4cedd94094..eeb225d445 100644 --- a/doc/classes/InputMap.xml +++ b/doc/classes/InputMap.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InputMap" inherits="Object" category="Core" version="3.0-stable"> +<class name="InputMap" inherits="Object" category="Core" version="3.1"> <brief_description> Singleton that manages [InputEventAction]. </brief_description> diff --git a/doc/classes/InstancePlaceholder.xml b/doc/classes/InstancePlaceholder.xml index f698551d41..5945e1068f 100644 --- a/doc/classes/InstancePlaceholder.xml +++ b/doc/classes/InstancePlaceholder.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InstancePlaceholder" inherits="Node" category="Core" version="3.0-stable"> +<class name="InstancePlaceholder" inherits="Node" category="Core" version="3.1"> <brief_description> Placeholder for the root [Node] of a [PackedScene]. </brief_description> <description> - Turning on the option [b]Load As Placeholder[/b] for an instanced scene in the editor causes it to be replaced by an InstacePlaceholder when running the game. This makes it possible to delay actually loading the scene until calling [method replace_by_instance]. This is useful to avoid loading large scenes all at once by loading parts of it selectively. + Turning on the option [b]Load As Placeholder[/b] for an instanced scene in the editor causes it to be replaced by an InstancePlaceholder when running the game. This makes it possible to delay actually loading the scene until calling [method replace_by_instance]. This is useful to avoid loading large scenes all at once by loading parts of it selectively. The InstancePlaceholder does not have a transform. This causes any child nodes to be positioned relatively to the Viewport from point (0,0), rather than their parent as displayed in the editor. Replacing the placeholder with a scene with a transform will transform children relatively to their parent again. </description> <tutorials> diff --git a/doc/classes/InterpolatedCamera.xml b/doc/classes/InterpolatedCamera.xml index de84a7df6e..9ee06b9d4f 100644 --- a/doc/classes/InterpolatedCamera.xml +++ b/doc/classes/InterpolatedCamera.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="InterpolatedCamera" inherits="Camera" category="Core" version="3.0-stable"> +<class name="InterpolatedCamera" inherits="Camera" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index b94a06f170..e4db5aeb84 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ItemList" inherits="Control" category="Core" version="3.0-stable"> +<class name="ItemList" inherits="Control" category="Core" version="3.1"> <brief_description> Control that provides a list of selectable items (and/or icons) in a single column, or optionally in multiple columns. </brief_description> diff --git a/doc/classes/JSON.xml b/doc/classes/JSON.xml index 078c293fc0..fbf9aea7f9 100644 --- a/doc/classes/JSON.xml +++ b/doc/classes/JSON.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="JSON" inherits="Object" category="Core" version="3.0-stable"> +<class name="JSON" inherits="Object" category="Core" version="3.1"> <brief_description> Helper class for parsing JSON data. </brief_description> diff --git a/doc/classes/JSONParseResult.xml b/doc/classes/JSONParseResult.xml index 18313beaf8..a9162e2d95 100644 --- a/doc/classes/JSONParseResult.xml +++ b/doc/classes/JSONParseResult.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="JSONParseResult" inherits="Reference" category="Core" version="3.0-stable"> +<class name="JSONParseResult" inherits="Reference" category="Core" version="3.1"> <brief_description> Data class wrapper for decoded JSON. </brief_description> diff --git a/doc/classes/JavaScript.xml b/doc/classes/JavaScript.xml index 8183b48ece..1d40b990a9 100644 --- a/doc/classes/JavaScript.xml +++ b/doc/classes/JavaScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="JavaScript" inherits="Object" category="Core" version="3.0-stable"> +<class name="JavaScript" inherits="Object" category="Core" version="3.1"> <brief_description> Singleton that connects the engine with the browser's JavaScript context in HTML5 export. </brief_description> diff --git a/doc/classes/Joint.xml b/doc/classes/Joint.xml index 8ead75d556..8cafdbdbf3 100644 --- a/doc/classes/Joint.xml +++ b/doc/classes/Joint.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Joint" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="Joint" inherits="Spatial" category="Core" version="3.1"> <brief_description> Base class for all 3D joints </brief_description> diff --git a/doc/classes/Joint2D.xml b/doc/classes/Joint2D.xml index 22f267f26f..8247997927 100644 --- a/doc/classes/Joint2D.xml +++ b/doc/classes/Joint2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Joint2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Joint2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Base node for all joint constraints in 2D physics. </brief_description> diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml index 1735501a47..5553602db2 100644 --- a/doc/classes/KinematicBody.xml +++ b/doc/classes/KinematicBody.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="KinematicBody" inherits="PhysicsBody" category="Core" version="3.0-stable"> +<class name="KinematicBody" inherits="PhysicsBody" category="Core" version="3.1"> <brief_description> Kinematic body 3D node. </brief_description> @@ -63,6 +63,8 @@ </return> <argument index="0" name="rel_vec" type="Vector3"> </argument> + <argument index="1" name="infinite_inertia" type="bool" default="true"> + </argument> <description> Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision], which contains information about the collision. </description> @@ -74,11 +76,13 @@ </argument> <argument index="1" name="floor_normal" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> - <argument index="2" name="slope_stop_min_velocity" type="float" default="0.05"> + <argument index="2" name="infinite_inertia" type="bool" default="true"> + </argument> + <argument index="3" name="slope_stop_min_velocity" type="float" default="0.05"> </argument> - <argument index="3" name="max_slides" type="int" default="4"> + <argument index="4" name="max_slides" type="int" default="4"> </argument> - <argument index="4" name="floor_max_angle" type="float" default="0.785398"> + <argument index="5" name="floor_max_angle" type="float" default="0.785398"> </argument> <description> Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [code]KinematicBody[/code] or [RigidBody], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes. @@ -97,6 +101,8 @@ </argument> <argument index="1" name="rel_vec" type="Vector3"> </argument> + <argument index="2" name="infinite_inertia" type="bool"> + </argument> <description> Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur. </description> diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml index f7303c19c4..0448707c2e 100644 --- a/doc/classes/KinematicBody2D.xml +++ b/doc/classes/KinematicBody2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="KinematicBody2D" inherits="PhysicsBody2D" category="Core" version="3.0-stable"> +<class name="KinematicBody2D" inherits="PhysicsBody2D" category="Core" version="3.1"> <brief_description> Kinematic body 2D node. </brief_description> @@ -62,6 +62,8 @@ </return> <argument index="0" name="rel_vec" type="Vector2"> </argument> + <argument index="1" name="infinite_inertia" type="bool" default="true"> + </argument> <description> Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision. </description> @@ -73,11 +75,13 @@ </argument> <argument index="1" name="floor_normal" type="Vector2" default="Vector2( 0, 0 )"> </argument> - <argument index="2" name="slope_stop_min_velocity" type="float" default="5"> + <argument index="2" name="infinite_inertia" type="bool" default="true"> + </argument> + <argument index="3" name="slope_stop_min_velocity" type="float" default="5"> </argument> - <argument index="3" name="max_bounces" type="int" default="4"> + <argument index="4" name="max_bounces" type="int" default="4"> </argument> - <argument index="4" name="floor_max_angle" type="float" default="0.785398"> + <argument index="5" name="floor_max_angle" type="float" default="0.785398"> </argument> <description> Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [code]KinematicBody2D[/code] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes. @@ -96,6 +100,8 @@ </argument> <argument index="1" name="rel_vec" type="Vector2"> </argument> + <argument index="2" name="infinite_inertia" type="bool"> + </argument> <description> Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur. </description> diff --git a/doc/classes/KinematicCollision.xml b/doc/classes/KinematicCollision.xml index 613b135578..87eb9e77b5 100644 --- a/doc/classes/KinematicCollision.xml +++ b/doc/classes/KinematicCollision.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="KinematicCollision" inherits="Reference" category="Core" version="3.0-stable"> +<class name="KinematicCollision" inherits="Reference" category="Core" version="3.1"> <brief_description> Collision data for KinematicBody collisions. </brief_description> diff --git a/doc/classes/KinematicCollision2D.xml b/doc/classes/KinematicCollision2D.xml index bb949877ad..e403ada0b9 100644 --- a/doc/classes/KinematicCollision2D.xml +++ b/doc/classes/KinematicCollision2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="KinematicCollision2D" inherits="Reference" category="Core" version="3.0-stable"> +<class name="KinematicCollision2D" inherits="Reference" category="Core" version="3.1"> <brief_description> Collision data for KinematicBody2D collisions. </brief_description> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index bbf83308de..24c28fc810 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Label" inherits="Control" category="Core" version="3.0-stable"> +<class name="Label" inherits="Control" category="Core" version="3.1"> <brief_description> Displays plain text in a line or wrapped inside a rectangle. For formatted text, use [RichTextLabel]. </brief_description> diff --git a/doc/classes/LargeTexture.xml b/doc/classes/LargeTexture.xml index 219943f021..763b38f49e 100644 --- a/doc/classes/LargeTexture.xml +++ b/doc/classes/LargeTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="LargeTexture" inherits="Texture" category="Core" version="3.0-stable"> +<class name="LargeTexture" inherits="Texture" category="Core" version="3.1"> <brief_description> A Texture capable of storing many smaller Textures with offsets. </brief_description> diff --git a/doc/classes/Light.xml b/doc/classes/Light.xml index 30722919d5..e05ed2d0b1 100644 --- a/doc/classes/Light.xml +++ b/doc/classes/Light.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Light" inherits="VisualInstance" category="Core" version="3.0-stable"> +<class name="Light" inherits="VisualInstance" category="Core" version="3.1"> <brief_description> Provides a base class for different kinds of light nodes. </brief_description> diff --git a/doc/classes/Light2D.xml b/doc/classes/Light2D.xml index 019bf48082..f3903ffeae 100644 --- a/doc/classes/Light2D.xml +++ b/doc/classes/Light2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Light2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Light2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Casts light in a 2D environment. </brief_description> diff --git a/doc/classes/LightOccluder2D.xml b/doc/classes/LightOccluder2D.xml index 4ea82918e1..38b9054411 100644 --- a/doc/classes/LightOccluder2D.xml +++ b/doc/classes/LightOccluder2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="LightOccluder2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="LightOccluder2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Occludes light cast by a Light2D, casting shadows. </brief_description> diff --git a/doc/classes/Line2D.xml b/doc/classes/Line2D.xml index a5eadae715..19be34978d 100644 --- a/doc/classes/Line2D.xml +++ b/doc/classes/Line2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Line2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Line2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> A 2D line. </brief_description> @@ -53,7 +53,7 @@ <argument index="1" name="position" type="Vector2"> </argument> <description> - Overwites the position in point [code]i[/code] with the supplied [code]position[/code]. + Overwrites the position in point [code]i[/code] with the supplied [code]position[/code]. </description> </method> </methods> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index d82fafd4ec..b6adf84abd 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="LineEdit" inherits="Control" category="Core" version="3.0-stable"> +<class name="LineEdit" inherits="Control" category="Core" version="3.1"> <brief_description> Control that provides single line string editing. </brief_description> diff --git a/doc/classes/LineShape2D.xml b/doc/classes/LineShape2D.xml index a6a1e7eb36..4a5486583a 100644 --- a/doc/classes/LineShape2D.xml +++ b/doc/classes/LineShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="LineShape2D" inherits="Shape2D" category="Core" version="3.0-stable"> +<class name="LineShape2D" inherits="Shape2D" category="Core" version="3.1"> <brief_description> Line shape for 2D collisions. </brief_description> diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml index 37bfb005ab..f419802958 100644 --- a/doc/classes/LinkButton.xml +++ b/doc/classes/LinkButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="LinkButton" inherits="BaseButton" category="Core" version="3.0-stable"> +<class name="LinkButton" inherits="BaseButton" category="Core" version="3.1"> <brief_description> Simple button used to represent a link to some resource </brief_description> diff --git a/doc/classes/Listener.xml b/doc/classes/Listener.xml index 5765e071a4..720a7eafc5 100644 --- a/doc/classes/Listener.xml +++ b/doc/classes/Listener.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Listener" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="Listener" inherits="Spatial" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml index 5a49641531..8c2aa01f81 100644 --- a/doc/classes/MainLoop.xml +++ b/doc/classes/MainLoop.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MainLoop" inherits="Object" category="Core" version="3.0-stable"> +<class name="MainLoop" inherits="Object" category="Core" version="3.1"> <brief_description> Main loop is the abstract main loop base class. </brief_description> diff --git a/doc/classes/MarginContainer.xml b/doc/classes/MarginContainer.xml index 25ac7c5668..15613e4bec 100644 --- a/doc/classes/MarginContainer.xml +++ b/doc/classes/MarginContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MarginContainer" inherits="Container" category="Core" version="3.0-stable"> +<class name="MarginContainer" inherits="Container" category="Core" version="3.1"> <brief_description> Simple margin container. </brief_description> diff --git a/doc/classes/Marshalls.xml b/doc/classes/Marshalls.xml index 554c32c893..687f81eec7 100644 --- a/doc/classes/Marshalls.xml +++ b/doc/classes/Marshalls.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Marshalls" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Marshalls" inherits="Reference" category="Core" version="3.1"> <brief_description> Data transformation (marshalling) and encoding helpers. </brief_description> diff --git a/doc/classes/Material.xml b/doc/classes/Material.xml index 5c31efc5e0..7420a5deb0 100644 --- a/doc/classes/Material.xml +++ b/doc/classes/Material.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Material" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Material" inherits="Resource" category="Core" version="3.1"> <brief_description> Abstract base [Resource] for coloring and shading geometry. </brief_description> diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml index 5b15bba22a..c9a8d3ce7a 100644 --- a/doc/classes/MenuButton.xml +++ b/doc/classes/MenuButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MenuButton" inherits="Button" category="Core" version="3.0-stable"> +<class name="MenuButton" inherits="Button" category="Core" version="3.1"> <brief_description> Special button that brings up a [PopupMenu] when clicked. </brief_description> diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml index 7fbc7768f7..83cadf959c 100644 --- a/doc/classes/Mesh.xml +++ b/doc/classes/Mesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Mesh" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Mesh" inherits="Resource" category="Core" version="3.1"> <brief_description> A [Resource] that contains vertex-array based geometry. </brief_description> diff --git a/doc/classes/MeshDataTool.xml b/doc/classes/MeshDataTool.xml index 720ab6f5d2..43d94004a8 100644 --- a/doc/classes/MeshDataTool.xml +++ b/doc/classes/MeshDataTool.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MeshDataTool" inherits="Reference" category="Core" version="3.0-stable"> +<class name="MeshDataTool" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/MeshInstance.xml b/doc/classes/MeshInstance.xml index 3b9ed70e77..ef42726ca9 100644 --- a/doc/classes/MeshInstance.xml +++ b/doc/classes/MeshInstance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MeshInstance" inherits="GeometryInstance" category="Core" version="3.0-stable"> +<class name="MeshInstance" inherits="GeometryInstance" category="Core" version="3.1"> <brief_description> Node that instances meshes into a scenario. </brief_description> diff --git a/doc/classes/MeshInstance2D.xml b/doc/classes/MeshInstance2D.xml new file mode 100644 index 0000000000..7f0136bf77 --- /dev/null +++ b/doc/classes/MeshInstance2D.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="MeshInstance2D" inherits="Node2D" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh"> + </member> + <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map"> + </member> + <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/MeshLibrary.xml b/doc/classes/MeshLibrary.xml index 774deab0ef..3726524638 100644 --- a/doc/classes/MeshLibrary.xml +++ b/doc/classes/MeshLibrary.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MeshLibrary" inherits="Resource" category="Core" version="3.0-stable"> +<class name="MeshLibrary" inherits="Resource" category="Core" version="3.1"> <brief_description> Library of meshes. </brief_description> diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml index 270da019eb..b78d82199c 100644 --- a/doc/classes/MultiMesh.xml +++ b/doc/classes/MultiMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MultiMesh" inherits="Resource" category="Core" version="3.0-stable"> +<class name="MultiMesh" inherits="Resource" category="Core" version="3.1"> <brief_description> Provides high performance mesh instancing. </brief_description> diff --git a/doc/classes/MultiMeshInstance.xml b/doc/classes/MultiMeshInstance.xml index aef372f810..5e021dfe9b 100644 --- a/doc/classes/MultiMeshInstance.xml +++ b/doc/classes/MultiMeshInstance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MultiMeshInstance" inherits="GeometryInstance" category="Core" version="3.0-stable"> +<class name="MultiMeshInstance" inherits="GeometryInstance" category="Core" version="3.1"> <brief_description> Node that instances a [MultiMesh]. </brief_description> diff --git a/doc/classes/Mutex.xml b/doc/classes/Mutex.xml index 2ed02cad48..8f2751af98 100644 --- a/doc/classes/Mutex.xml +++ b/doc/classes/Mutex.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Mutex" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Mutex" inherits="Reference" category="Core" version="3.1"> <brief_description> A synchronization Mutex. </brief_description> diff --git a/doc/classes/Navigation.xml b/doc/classes/Navigation.xml index 86302694a0..b3b9ada26c 100644 --- a/doc/classes/Navigation.xml +++ b/doc/classes/Navigation.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Navigation" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="Navigation" inherits="Spatial" category="Core" version="3.1"> <brief_description> A collection of [code]NavigationMesh[/code] resources and methods used for pathfinding. </brief_description> diff --git a/doc/classes/Navigation2D.xml b/doc/classes/Navigation2D.xml index 80d53c00a5..d2f4513372 100644 --- a/doc/classes/Navigation2D.xml +++ b/doc/classes/Navigation2D.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Navigation2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Navigation2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> + Class to assist with character navigation and pathfinding. </brief_description> <description> </description> diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml index 5cde8942d1..f0654e5b12 100644 --- a/doc/classes/NavigationMesh.xml +++ b/doc/classes/NavigationMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NavigationMesh" inherits="Resource" category="Core" version="3.0-stable"> +<class name="NavigationMesh" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/NavigationMeshInstance.xml b/doc/classes/NavigationMeshInstance.xml index f329bad0eb..643bfc726f 100644 --- a/doc/classes/NavigationMeshInstance.xml +++ b/doc/classes/NavigationMeshInstance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NavigationMeshInstance" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="NavigationMeshInstance" inherits="Spatial" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/NavigationPolygon.xml b/doc/classes/NavigationPolygon.xml index 6e8154c4e5..b29e19e5d8 100644 --- a/doc/classes/NavigationPolygon.xml +++ b/doc/classes/NavigationPolygon.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NavigationPolygon" inherits="Resource" category="Core" version="3.0-stable"> +<class name="NavigationPolygon" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/NavigationPolygonInstance.xml b/doc/classes/NavigationPolygonInstance.xml index 023f13de89..ff95f652f1 100644 --- a/doc/classes/NavigationPolygonInstance.xml +++ b/doc/classes/NavigationPolygonInstance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NavigationPolygonInstance" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="NavigationPolygonInstance" inherits="Node2D" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/NetworkedMultiplayerPeer.xml b/doc/classes/NetworkedMultiplayerPeer.xml index 8f746594bc..71614c5f76 100644 --- a/doc/classes/NetworkedMultiplayerPeer.xml +++ b/doc/classes/NetworkedMultiplayerPeer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NetworkedMultiplayerPeer" inherits="PacketPeer" category="Core" version="3.0-stable"> +<class name="NetworkedMultiplayerPeer" inherits="PacketPeer" category="Core" version="3.1"> <brief_description> A high-level network interface to simplify multiplayer interactions. </brief_description> diff --git a/doc/classes/Nil.xml b/doc/classes/Nil.xml index 2e845d511a..e09dba6511 100644 --- a/doc/classes/Nil.xml +++ b/doc/classes/Nil.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Nil" category="Built-In Types" version="3.0-stable"> +<class name="Nil" category="Built-In Types" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/NinePatchRect.xml b/doc/classes/NinePatchRect.xml index e67f0ea4a4..f40b32951f 100644 --- a/doc/classes/NinePatchRect.xml +++ b/doc/classes/NinePatchRect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NinePatchRect" inherits="Control" category="Core" version="3.0-stable"> +<class name="NinePatchRect" inherits="Control" category="Core" version="3.1"> <brief_description> Scalable texture-based frame that tiles the texture's centers and sides, but keeps the corners' original size. Perfect for panels and dialog boxes. </brief_description> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 46c8bf01a5..97d09a66c4 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Node" inherits="Object" category="Core" version="3.0-stable"> +<class name="Node" inherits="Object" category="Core" version="3.1"> <brief_description> Base class for all [i]scene[/i] objects. </brief_description> <description> Nodes are Godot's building blocks. They can be assigned as the child of another node, resulting in a tree arrangement. A given node can contain any number of nodes as children with the requirement that all siblings (direct children of a node) should have unique names. - A tree of nodes is called a [i]scene[/i]. Scenes can be saved to the disk and then instanced into other scenes. This allows for very high flexibility in the architecture and data model of Godot projects. Nodes can also optionally be added to groups. This makes it possible to access a number of nodes from code (an "enemies" group, for example) to perform grouped actions. + A tree of nodes is called a [i]scene[/i]. Scenes can be saved to the disk and then instanced into other scenes. This allows for very high flexibility in the architecture and data model of Godot projects. [b]Scene tree:[/b] The [SceneTree] contains the active tree of nodes. When a node is added to the scene tree, it receives the NOTIFICATION_ENTER_TREE notification and its [method _enter_tree] callback is triggered. Child nodes are always added [i]after[/i] their parent node, i.e. the [method _enter_tree] callback of a parent node will be triggered before its child's. Once all nodes have been added in the scene tree, they receive the NOTIFICATION_READY notification and their respective [method _ready] callbacks are triggered. For groups of nodes, the [method _ready] callback is called in reverse order, starting with the children and moving up to the parent nodes. This means that when adding a node to the scene tree, the following order will be used for the callbacks: [method _enter_tree] of the parent, [method _enter_tree] of the children, [method _ready] of the children and finally [method _ready] of the parent (recursively for the entire scene tree). @@ -13,7 +13,8 @@ Nodes can also process input events. When present, the [method _input] function will be called for each input that the program receives. In many cases, this can be overkill (unless used for simple projects), and the [method _unhandled_input] function might be preferred; it is called when the input event was not handled by anyone else (typically, GUI [Control] nodes), ensuring that the node only receives the events that were meant for it. To keep track of the scene hierarchy (especially when instancing scenes into other scenes), an "owner" can be set for the node with [method set_owner]. This keeps track of who instanced what. This is mostly useful when writing editors and tools, though. Finally, when a node is freed with [method free] or [method queue_free], it will also free all its children. - [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]) it is possible to use the built-in RPC (remote procedure call) system to communicate over the network. By calling [method rpc] with a method name, it will be called locally and in all connected peers (peers = clients and the server that accepts connections), with behaviour varying depending on the network mode ([method set_network_mode]) of the receiving peer. To identify which node receives the RPC call Godot will use its [NodePath] (make sure node names are the same on all peers). + [b]Groups:[/b] Nodes can be added to as many groups as you want to be easy to manage, you could create groups like "enemies" or "collectables" for example, depending on your game. See [method add_to_group], [method is_in_group] and [method remove_from_group]. You can then retrieve all nodes in these groups, iterate them and even call methods on groups via the methods on [SceneTree]. + [b]Networking with nodes:[/b] After connecting to a server (or making one, see [NetworkedMultiplayerENet]) it is possible to use the built-in RPC (remote procedure call) system to communicate over the network. By calling [method rpc] with a method name, it will be called locally and in all connected peers (peers = clients and the server that accepts connections). To identify which node receives the RPC call Godot will use its [NodePath] (make sure node names are the same on all peers). Also take a look at the high-level networking tutorial and corresponding demos. </description> <tutorials> http://docs.godotengine.org/en/3.0/getting_started/step_by_step/scenes_and_nodes.html @@ -45,6 +46,8 @@ <description> Called when there is an input event. The input event propagates through the node tree until a node consumes it. It is only called if input processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_input]. + To consume the input event and stop it propagating further to other nodes, [method SceneTree.set_input_as_handled] can be called. + For gameplay input, [method _unhandled_input] and [method _unhandled_key_input] are usually a better fit as they allow the GUI to intercept the events first. </description> </method> <method name="_physics_process" qualifiers="virtual"> @@ -74,7 +77,8 @@ </return> <description> Called when the node is "ready", i.e. when both the node and its children have entered the scene tree. If the node has children, their [method _ready] callbacks get triggered first, and the parent node will receive the ready notification afterwards. - Corresponds to the NOTIFICATION_READY notification in [method Object._notification]. + Corresponds to the NOTIFICATION_READY notification in [method Object._notification]. See also the [code]onready[/code] keyword for variables. + Usually used for initialization. For even earlier initialization, [method Object._init] may be used. Also see [method _enter_tree]. </description> </method> <method name="_unhandled_input" qualifiers="virtual"> @@ -83,8 +87,10 @@ <argument index="0" name="event" type="InputEvent"> </argument> <description> - Propagated to all nodes when the previous InputEvent is not consumed by any nodes. + Propagated to all nodes when the previous [InputEvent] is not consumed by any nodes. It is only called if unhandled input processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_unhandled_input]. + To consume the input event and stop it propagating further to other nodes, [method SceneTree.set_input_as_handled] can be called. + For gameplay input, this and [method _unhandled_key_input] are usually a better fit than [method _input] as they allow the GUI to intercept the events first. </description> </method> <method name="_unhandled_key_input" qualifiers="virtual"> @@ -93,6 +99,10 @@ <argument index="0" name="event" type="InputEventKey"> </argument> <description> + Propagated to all nodes when the previous [InputEventKey] is not consumed by any nodes. + It is only called if unhandled key input processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_unhandled_key_input]. + To consume the input event and stop it propagating further to other nodes, [method SceneTree.set_input_as_handled] can be called. + For gameplay input, this and [method _unhandled_input] are usually a better fit than [method _input] as they allow the GUI to intercept the events first. </description> </method> <method name="add_child"> @@ -129,7 +139,7 @@ <argument index="1" name="persistent" type="bool" default="false"> </argument> <description> - Adds the node to a group. Groups are helpers to name and organize a subset of nodes, for example "enemies" or "collectables". A node can be in any number of groups. Nodes can be assigned a group at any time, but will not be added until they are inside the scene tree (see [method is_inside_tree]). + Adds the node to a group. Groups are helpers to name and organize a subset of nodes, for example "enemies" or "collectables". A node can be in any number of groups. Nodes can be assigned a group at any time, but will not be added until they are inside the scene tree (see [method is_inside_tree]). See notes in the description, and the group methods in [SceneTree]. </description> </method> <method name="can_process" qualifiers="const"> @@ -203,7 +213,7 @@ <return type="int"> </return> <description> - Returns the peer ID of the network master for this node. + Returns the peer ID of the network master for this node. See [method set_network_master]. </description> </method> <method name="get_node" qualifiers="const"> @@ -262,7 +272,7 @@ <argument index="0" name="node" type="Node"> </argument> <description> - Returns the relative path from the current node to the specified node in "node" argument. Both nodes must be in the same scene, or the function will fail. + Returns the relative [NodePath] from this node to the specified [code]node[/code]. Both nodes must be in the same scene or the function will fail. </description> </method> <method name="get_physics_process_delta_time" qualifiers="const"> @@ -290,6 +300,7 @@ <return type="bool"> </return> <description> + Returns [code]true[/code] if this is an instance load placeholder. See [InstancePlaceholder]. </description> </method> <method name="get_tree" qualifiers="const"> @@ -354,7 +365,7 @@ <argument index="0" name="group" type="String"> </argument> <description> - Returns [code]true[/code] if this node is in the specified group. + Returns [code]true[/code] if this node is in the specified group. See notes in the description, and the group methods in [SceneTree]. </description> </method> <method name="is_inside_tree" qualifiers="const"> @@ -368,6 +379,7 @@ <return type="bool"> </return> <description> + Returns [code]true[/code] if the local system is the master of this node. </description> </method> <method name="is_physics_processing" qualifiers="const"> @@ -381,6 +393,7 @@ <return type="bool"> </return> <description> + Returns [code]true[/code] if internal physics processing is enabled (see [method set_physics_process_internal]). </description> </method> <method name="is_processing" qualifiers="const"> @@ -401,6 +414,7 @@ <return type="bool"> </return> <description> + Returns [code]true[/code] if internal processing is enabled (see [method set_process_internal]). </description> </method> <method name="is_processing_unhandled_input" qualifiers="const"> @@ -432,13 +446,14 @@ <return type="void"> </return> <description> + Prints all stray nodes (nodes outside the [SceneTree]). Used for debugging. Works only in debug builds. </description> </method> <method name="print_tree"> <return type="void"> </return> <description> - Prints the scene to stdout. Used mainly for debugging purposes. + Prints the scene hierarchy of this node and all it's children to stdout. Used mainly for debugging purposes. </description> </method> <method name="propagate_call"> @@ -499,7 +514,7 @@ <argument index="0" name="group" type="String"> </argument> <description> - Removes a node from a group. + Removes a node from a group. See notes in the description, and the group methods in [SceneTree]. </description> </method> <method name="replace_by"> @@ -526,7 +541,7 @@ <argument index="0" name="method" type="String"> </argument> <description> - Sends a remote procedure call request to all peers on the network (and locally), optionally sending additional data as arguments. Call request will be received by nodes with the same [NodePath]. + Sends a remote procedure call request for the given [code]method[/code] to peers on the network (and locally), optionally sending all additional arguments as arguments to the method called by the RPC. The call request will only be received by nodes with the same [NodePath], including the exact same node name. Behaviour depends on the RPC configuration for the given method, see [method rpc_config]. Methods are not exposed to RPCs by default. Also see [method rset] and [method rset_config] for properties. Returns an empty [Variant]. Note that you can only safely use RPCs on clients after you received the [code]connected_to_server[/code] signal from the [SceneTree]. You also need to keep track of the connection state, either by the [SceneTree] signals like [code]server_disconnected[/code] or by checking [code]SceneTree.network_peer.get_connection_status() == CONNECTION_CONNECTED[/code]. </description> </method> <method name="rpc_config"> @@ -537,7 +552,7 @@ <argument index="1" name="mode" type="int" enum="Node.RPCMode"> </argument> <description> - Changes the method's RPC mode (one of RPC_MODE_* constants). + Changes the RPC mode for the given [code]method[/code] to the given [code]mode[/code]. See [enum RPCMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]sync[/code], [code]master[/code], [code]slave[/code]). By default, methods are not exposed to networking (and RPCs). Also see [method rset] and [method rset_config] for properties. </description> </method> <method name="rpc_id" qualifiers="vararg"> @@ -548,7 +563,7 @@ <argument index="1" name="method" type="String"> </argument> <description> - Sends a [method rpc] to a specific peer identified by [i]peer_id[/i]. + Sends a [method rpc] to a specific peer identified by [code]peer_id[/code]. Returns an empty [Variant]. </description> </method> <method name="rpc_unreliable" qualifiers="vararg"> @@ -557,7 +572,7 @@ <argument index="0" name="method" type="String"> </argument> <description> - Sends a [method rpc] using an unreliable protocol. + Sends a [method rpc] using an unreliable protocol. Returns an empty [Variant]. </description> </method> <method name="rpc_unreliable_id" qualifiers="vararg"> @@ -568,7 +583,7 @@ <argument index="1" name="method" type="String"> </argument> <description> - Sends a [method rpc] to a specific peer identified by [i]peer_id[/i] using an unreliable protocol. + Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] using an unreliable protocol. Returns an empty [Variant]. </description> </method> <method name="rset"> @@ -579,7 +594,7 @@ <argument index="1" name="value" type="Variant"> </argument> <description> - Remotely changes property's value on other peers (and locally). + Remotely changes a property's value on other peers (and locally). Behaviour depends on the RPC configuration for the given property, see [method rset_config]. Also see [method rpc] for RPCs for methods, most information applies to this method as well. </description> </method> <method name="rset_config"> @@ -590,7 +605,7 @@ <argument index="1" name="mode" type="int" enum="Node.RPCMode"> </argument> <description> - Changes the property's RPC mode (one of RPC_MODE_* constants). + Changes the RPC mode for the given [code]property[/code] to the given [code]mode[/code]. See [enum RPCMode]. An alternative is annotating methods and properties with the corresponding keywords ([code]remote[/code], [code]sync[/code], [code]master[/code], [code]slave[/code]). By default, properties are not exposed to networking (and RPCs). Also see [method rpc] and [method rpc_config] for methods. </description> </method> <method name="rset_id"> @@ -603,7 +618,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> - Remotely changes property's value on a specific peer identified by [i]peer_id[/i]. + Remotely changes the property's value on a specific peer identified by [code]peer_id[/code]. </description> </method> <method name="rset_unreliable"> @@ -614,7 +629,7 @@ <argument index="1" name="value" type="Variant"> </argument> <description> - Remotely changes property's value on other peers (and locally) using an unreliable protocol. + Remotely changes the property's value on other peers (and locally) using an unreliable protocol. </description> </method> <method name="rset_unreliable_id"> @@ -627,7 +642,7 @@ <argument index="2" name="value" type="Variant"> </argument> <description> - Remotely changes property's value on a specific peer identified by [i]peer_id[/i] using an unreliable protocol. + Remotely changes property's value on a specific peer identified by [code]peer_id[/code] using an unreliable protocol. </description> </method> <method name="set_display_folded"> @@ -647,7 +662,7 @@ <argument index="1" name="recursive" type="bool" default="true"> </argument> <description> - Sets the node network master to the peer with the given peer ID. The network master is the peer that has authority over it on the network. Inherited from the parent node by default, which ultimately defaults to peer ID 1 (the server). + Sets the node's network master to the peer with the given peer ID. The network master is the peer that has authority over the node on the network. Useful in conjunction with the [code]master[/code] and [code]slave[/code] keywords. Inherited from the parent node by default, which ultimately defaults to peer ID 1 (the server). If [code]recursive[/code], the given peer is recursively set as the master for all children of this node. </description> </method> <method name="set_physics_process"> @@ -665,6 +680,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> + Enables or disables internal physics for this node. Internal physics processing happens in isolation from the normal [method]_physics_process[/code] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or physics processing is disabled for scripting ([method set_physics_process]). Only useful for advanced uses to manipulate built-in nodes behaviour. </description> </method> <method name="set_process"> @@ -691,6 +707,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> + Enables or disabled internal processing for this node. Internal processing happens in isolation from the normal [method]_process[/code] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or processing is disabled for scripting ([method set_process]). Only useful for advanced uses to manipulate built-in nodes behaviour. </description> </method> <method name="set_process_unhandled_input"> @@ -717,6 +734,7 @@ <argument index="0" name="load_placeholder" type="bool"> </argument> <description> + Sets whether this is an instance load placeholder. See [InstancePlaceholder]. </description> </method> </methods> @@ -725,13 +743,13 @@ When a scene is instanced from a file, its topmost node contains the filename from which it was loaded. </member> <member name="name" type="String" setter="set_name" getter="get_name"> - The name of the node. This name is unique among the siblings (other child nodes from the same parent). - When set to an existing name, the node will be automatically renamed + The name of the node. This name is unique among the siblings (other child nodes from the same parent). When set to an existing name, the node will be automatically renamed </member> <member name="owner" type="Node" setter="set_owner" getter="get_owner"> The node owner. A node can have any other node as owner (as long as it is a valid parent, grandparent, etc. ascending in the tree). When saving a node (using SceneSaver) all the nodes it owns will be saved with it. This allows for the creation of complex [SceneTree]s, with instancing and subinstancing. </member> <member name="pause_mode" type="int" setter="set_pause_mode" getter="get_pause_mode" enum="Node.PauseMode"> + Pause mode. How the node will behave if the [SceneTree] is paused. </member> </members> <signals> @@ -752,7 +770,7 @@ </signal> <signal name="tree_exiting"> <description> - Emitted when the node is still active but about to exit the tree. This is the right place for de-initialization. + Emitted when the node is still active but about to exit the tree. This is the right place for de-initialization (or a "destructor", if you will). </description> </signal> </signals> @@ -800,33 +818,37 @@ Notification received when the node's [NodePath] changed. </constant> <constant name="NOTIFICATION_TRANSLATION_CHANGED" value="24"> + Notification received when translations may have changed. Can be triggered by the user changing the locale. Can be used to respond to language changes, for example to change the UI strings on the fly. Useful when working with the built-in translation support, like [method Object.tr]. </constant> <constant name="NOTIFICATION_INTERNAL_PROCESS" value="25"> + Notification received every frame when the internal process flag is set (see [method set_process_internal]). </constant> <constant name="NOTIFICATION_INTERNAL_PHYSICS_PROCESS" value="26"> + Notification received every frame when the internal physics process flag is set (see [method set_physics_process_internal]). </constant> <constant name="RPC_MODE_DISABLED" value="0" enum="RPCMode"> + Used with [method rpc_config] or [method rset_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods. </constant> <constant name="RPC_MODE_REMOTE" value="1" enum="RPCMode"> - Call a method remotely. + Used with [method rpc_config] or [method rset_config] to set a method to be called or a property to be changed only on the remote end, not locally. Analogous to the [code]remote[/code] keyword. </constant> <constant name="RPC_MODE_SYNC" value="2" enum="RPCMode"> - Call a method both remotely and locally. + Used with [method rpc_config] or [method rset_config] to set a method to be called or a property to be changed both on the remote end and locally. Analogous to the [code]sync[/code] keyword. </constant> <constant name="RPC_MODE_MASTER" value="3" enum="RPCMode"> - Call a method if the Node is Master. + Used with [method rpc_config] or [method rset_config] to set a method to be called or a property to be changed only on the network master for this node. Analogous to the [code]master[/code] keyword. See [method set_network_master]. </constant> <constant name="RPC_MODE_SLAVE" value="4" enum="RPCMode"> - Call a method if the Node is Slave. + Used with [method rpc_config] or [method rset_config] to set a method to be called or a property to be changed only on slaves for this node. Analogous to the [code]slave[/code] keyword. See [method set_network_master]. </constant> <constant name="PAUSE_MODE_INHERIT" value="0" enum="PauseMode"> - Inherits pause mode from parent. For root node, it is equivalent to PAUSE_MODE_STOP. + Inherits pause mode from the node's parent. For the root node, it is equivalent to PAUSE_MODE_STOP. Default. </constant> <constant name="PAUSE_MODE_STOP" value="1" enum="PauseMode"> - Stop processing when SceneTree is paused. + Stop processing when the [SceneTree] is paused. </constant> <constant name="PAUSE_MODE_PROCESS" value="2" enum="PauseMode"> - Continue to process regardless of SceneTree pause state. + Continue to process regardless of the [SceneTree] pause state. </constant> <constant name="DUPLICATE_SIGNALS" value="1" enum="DuplicateFlags"> Duplicate the node's signals. diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml index f51c5abe18..a61678041f 100644 --- a/doc/classes/Node2D.xml +++ b/doc/classes/Node2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Node2D" inherits="CanvasItem" category="Core" version="3.0-stable"> +<class name="Node2D" inherits="CanvasItem" category="Core" version="3.1"> <brief_description> A 2D game object, parent of all 2D related nodes. Has a position, rotation, scale and Z-index. </brief_description> diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml index 6027f110da..f589fa12b7 100644 --- a/doc/classes/NodePath.xml +++ b/doc/classes/NodePath.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NodePath" category="Built-In Types" version="3.0-stable"> +<class name="NodePath" category="Built-In Types" version="3.1"> <brief_description> Pre-parsed scene tree path. </brief_description> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index a61b156b01..a98385f1d2 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="OS" inherits="Object" category="Core" version="3.0-stable"> +<class name="OS" inherits="Object" category="Core" version="3.1"> <brief_description> Operating System functions. </brief_description> @@ -36,6 +36,12 @@ Returns [code]true[/code] if the current host platform is using multiple threads. </description> </method> + <method name="center_window"> + <return type="void"> + </return> + <description> + </description> + </method> <method name="delay_msec" qualifiers="const"> <return type="void"> </return> @@ -232,6 +238,12 @@ Returns the number of cores available in the host machine. </description> </method> + <method name="get_real_window_size" qualifiers="const"> + <return type="Vector2"> + </return> + <description> + </description> + </method> <method name="get_scancode_string" qualifiers="const"> <return type="String"> </return> @@ -373,6 +385,10 @@ </return> <description> Returns the absolute directory path where user data is written ([code]user://[/code]). + On Linux, this is [code]~/.local/share/godot/app_userdata/[project_name][/code], or [code]~/.local/share/[custom_name][/code] if [code]use_custom_user_dir[/code] is set. + On macOS, this is [code]~/Library/Application Support/Godot/app_userdata/[project_name][/code], or [code]~/Library/Application Support/[custom_name][/code] if [code]use_custom_user_dir[/code] is set. + On Windows, this is [code]%APPDATA%/Godot/app_userdata/[project_name][/code], or [code]%APPDATA%/[custom_name][/code] if [code]use_custom_user_dir[/code] is set. + If the project name is empty, [code]user://[/code] falls back to [code]res://[/code]. </description> </method> <method name="get_virtual_keyboard_height"> @@ -458,6 +474,12 @@ If [code]true[/code], the [code]user://[/code] file system is persistent, so that its state is the same after a player quits and starts the game again. Relevant to the HTML5 platform, where this persistence may be unavailable. </description> </method> + <method name="is_window_always_on_top" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> <method name="kill"> <return type="int" enum="Error"> </return> @@ -586,6 +608,14 @@ Enables backup saves if [code]enabled[/code] is [code]true[/code]. </description> </method> + <method name="set_window_always_on_top"> + <return type="void"> + </return> + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> <method name="set_window_title"> <return type="void"> </return> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 8a7006ea97..b5986ec0f5 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Object" category="Core" version="3.0-stable"> +<class name="Object" category="Core" version="3.1"> <brief_description> Base class for all non built-in types. </brief_description> diff --git a/doc/classes/OccluderPolygon2D.xml b/doc/classes/OccluderPolygon2D.xml index f16aca487e..e8d6b54f27 100644 --- a/doc/classes/OccluderPolygon2D.xml +++ b/doc/classes/OccluderPolygon2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="OccluderPolygon2D" inherits="Resource" category="Core" version="3.0-stable"> +<class name="OccluderPolygon2D" inherits="Resource" category="Core" version="3.1"> <brief_description> Defines a 2D polygon for LightOccluder2D. </brief_description> diff --git a/doc/classes/OmniLight.xml b/doc/classes/OmniLight.xml index d4d00e2a9b..0ed133f52e 100644 --- a/doc/classes/OmniLight.xml +++ b/doc/classes/OmniLight.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="OmniLight" inherits="Light" category="Core" version="3.0-stable"> +<class name="OmniLight" inherits="Light" category="Core" version="3.1"> <brief_description> OmniDirectional Light, such as a light bulb or a candle. </brief_description> diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml index 56f4aa2082..de6f60c384 100644 --- a/doc/classes/OptionButton.xml +++ b/doc/classes/OptionButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="OptionButton" inherits="Button" category="Core" version="3.0-stable"> +<class name="OptionButton" inherits="Button" category="Core" version="3.1"> <brief_description> Button control that provides selectable options when pressed. </brief_description> diff --git a/doc/classes/PCKPacker.xml b/doc/classes/PCKPacker.xml index a04f9ef6fb..01985a9bb3 100644 --- a/doc/classes/PCKPacker.xml +++ b/doc/classes/PCKPacker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PCKPacker" inherits="Reference" category="Core" version="3.0-stable"> +<class name="PCKPacker" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/PHashTranslation.xml b/doc/classes/PHashTranslation.xml index 94fddad706..18c72a0576 100644 --- a/doc/classes/PHashTranslation.xml +++ b/doc/classes/PHashTranslation.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PHashTranslation" inherits="Translation" category="Core" version="3.0-stable"> +<class name="PHashTranslation" inherits="Translation" category="Core" version="3.1"> <brief_description> Optimized translation. </brief_description> diff --git a/doc/classes/PackedDataContainer.xml b/doc/classes/PackedDataContainer.xml index 42d00e067b..e6dbe57925 100644 --- a/doc/classes/PackedDataContainer.xml +++ b/doc/classes/PackedDataContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PackedDataContainer" inherits="Resource" category="Core" version="3.0-stable"> +<class name="PackedDataContainer" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/PackedDataContainerRef.xml b/doc/classes/PackedDataContainerRef.xml index 1adbbeb5a1..371fe5a5ac 100644 --- a/doc/classes/PackedDataContainerRef.xml +++ b/doc/classes/PackedDataContainerRef.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PackedDataContainerRef" inherits="Reference" category="Core" version="3.0-stable"> +<class name="PackedDataContainerRef" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index a5877a66d2..cf89e6a2df 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PackedScene" inherits="Resource" category="Core" version="3.0-stable"> +<class name="PackedScene" inherits="Resource" category="Core" version="3.1"> <brief_description> An abstraction of a serialized scene. </brief_description> diff --git a/doc/classes/PacketPeer.xml b/doc/classes/PacketPeer.xml index 354ef1f3f3..a4cf0c8029 100644 --- a/doc/classes/PacketPeer.xml +++ b/doc/classes/PacketPeer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PacketPeer" inherits="Reference" category="Core" version="3.0-stable"> +<class name="PacketPeer" inherits="Reference" category="Core" version="3.1"> <brief_description> Abstraction and base class for packet-based protocols. </brief_description> diff --git a/doc/classes/PacketPeerStream.xml b/doc/classes/PacketPeerStream.xml index b475c9d99e..9e3195bb44 100644 --- a/doc/classes/PacketPeerStream.xml +++ b/doc/classes/PacketPeerStream.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PacketPeerStream" inherits="PacketPeer" category="Core" version="3.0-stable"> +<class name="PacketPeerStream" inherits="PacketPeer" category="Core" version="3.1"> <brief_description> Wrapper to use a PacketPeer over a StreamPeer. </brief_description> diff --git a/doc/classes/PacketPeerUDP.xml b/doc/classes/PacketPeerUDP.xml index d7b38297ba..1b821e06cf 100644 --- a/doc/classes/PacketPeerUDP.xml +++ b/doc/classes/PacketPeerUDP.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PacketPeerUDP" inherits="PacketPeer" category="Core" version="3.0-stable"> +<class name="PacketPeerUDP" inherits="PacketPeer" category="Core" version="3.1"> <brief_description> UDP packet peer. </brief_description> diff --git a/doc/classes/Panel.xml b/doc/classes/Panel.xml index 38c605f8a4..758925e969 100644 --- a/doc/classes/Panel.xml +++ b/doc/classes/Panel.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Panel" inherits="Control" category="Core" version="3.0-stable"> +<class name="Panel" inherits="Control" category="Core" version="3.1"> <brief_description> Provides an opaque background for [Control] children. </brief_description> diff --git a/doc/classes/PanelContainer.xml b/doc/classes/PanelContainer.xml index 4c0875dea5..f5c351fa21 100644 --- a/doc/classes/PanelContainer.xml +++ b/doc/classes/PanelContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PanelContainer" inherits="Container" category="Core" version="3.0-stable"> +<class name="PanelContainer" inherits="Container" category="Core" version="3.1"> <brief_description> Panel container type. </brief_description> diff --git a/doc/classes/PanoramaSky.xml b/doc/classes/PanoramaSky.xml index b99f29e112..eb288d13be 100644 --- a/doc/classes/PanoramaSky.xml +++ b/doc/classes/PanoramaSky.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PanoramaSky" inherits="Sky" category="Core" version="3.0-stable"> +<class name="PanoramaSky" inherits="Sky" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/ParallaxBackground.xml b/doc/classes/ParallaxBackground.xml index 0b9e3c9609..2409b7a1c1 100644 --- a/doc/classes/ParallaxBackground.xml +++ b/doc/classes/ParallaxBackground.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ParallaxBackground" inherits="CanvasLayer" category="Core" version="3.0-stable"> +<class name="ParallaxBackground" inherits="CanvasLayer" category="Core" version="3.1"> <brief_description> A node used to create a parallax scrolling background. </brief_description> diff --git a/doc/classes/ParallaxLayer.xml b/doc/classes/ParallaxLayer.xml index 1feb3054f3..662a15e043 100644 --- a/doc/classes/ParallaxLayer.xml +++ b/doc/classes/ParallaxLayer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ParallaxLayer" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="ParallaxLayer" inherits="Node2D" category="Core" version="3.1"> <brief_description> A parallax scrolling layer to be used with [ParallaxBackground]. </brief_description> diff --git a/doc/classes/Particles.xml b/doc/classes/Particles.xml index bdf62f2b14..04177aca25 100644 --- a/doc/classes/Particles.xml +++ b/doc/classes/Particles.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Particles" inherits="GeometryInstance" category="Core" version="3.0-stable"> +<class name="Particles" inherits="GeometryInstance" category="Core" version="3.1"> <brief_description> 3D particle emitter. </brief_description> diff --git a/doc/classes/Particles2D.xml b/doc/classes/Particles2D.xml index 20b9632c30..47265054b0 100644 --- a/doc/classes/Particles2D.xml +++ b/doc/classes/Particles2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Particles2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Particles2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> 2D particle emitter. </brief_description> diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index 28ca512ec4..354b98485e 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ParticlesMaterial" inherits="Material" category="Core" version="3.0-stable"> +<class name="ParticlesMaterial" inherits="Material" category="Core" version="3.1"> <brief_description> Particle properties for [Particles] and [Particles2D] nodes. </brief_description> @@ -132,7 +132,7 @@ Orbital velocity randomness ratio. Default value: [code]0[/code]. </member> <member name="radial_accel" type="float" setter="set_param" getter="get_param"> - Linear acceleration applied to each particle. + Radial acceleration applied to each particle. </member> <member name="radial_accel_curve" type="Texture" setter="set_param_texture" getter="get_param_texture"> Each particle's radial acceleration will vary along this [CurveTexture]. diff --git a/doc/classes/Path.xml b/doc/classes/Path.xml index 0d931e12fd..621a513da3 100644 --- a/doc/classes/Path.xml +++ b/doc/classes/Path.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Path" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="Path" inherits="Spatial" category="Core" version="3.1"> <brief_description> Container for a [Curve3D]. </brief_description> diff --git a/doc/classes/Path2D.xml b/doc/classes/Path2D.xml index e889027283..5e40fb6956 100644 --- a/doc/classes/Path2D.xml +++ b/doc/classes/Path2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Path2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Path2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Contains a [Curve2D] path for [PathFollow2D] nodes to follow. </brief_description> diff --git a/doc/classes/PathFollow.xml b/doc/classes/PathFollow.xml index 144afa21e7..650fed7ec6 100644 --- a/doc/classes/PathFollow.xml +++ b/doc/classes/PathFollow.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PathFollow" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="PathFollow" inherits="Spatial" category="Core" version="3.1"> <brief_description> Point sampler for a [Path]. </brief_description> diff --git a/doc/classes/PathFollow2D.xml b/doc/classes/PathFollow2D.xml index 2d844c22bb..f9940dab2f 100644 --- a/doc/classes/PathFollow2D.xml +++ b/doc/classes/PathFollow2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PathFollow2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="PathFollow2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Point sampler for a [Path2D]. </brief_description> diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml index 18e45f7c3f..de3a251a79 100644 --- a/doc/classes/Performance.xml +++ b/doc/classes/Performance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Performance" inherits="Object" category="Core" version="3.0-stable"> +<class name="Performance" inherits="Object" category="Core" version="3.1"> <brief_description> Exposes performance related data. </brief_description> diff --git a/doc/classes/Physics2DDirectBodyState.xml b/doc/classes/Physics2DDirectBodyState.xml index 190325396d..73a2d792ab 100644 --- a/doc/classes/Physics2DDirectBodyState.xml +++ b/doc/classes/Physics2DDirectBodyState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Physics2DDirectBodyState" inherits="Object" category="Core" version="3.0-stable"> +<class name="Physics2DDirectBodyState" inherits="Object" category="Core" version="3.1"> <brief_description> Direct access object to a physics body in the [Physics2DServer]. </brief_description> diff --git a/doc/classes/Physics2DDirectBodyStateSW.xml b/doc/classes/Physics2DDirectBodyStateSW.xml index f6bcaef7be..cb1e9239b3 100644 --- a/doc/classes/Physics2DDirectBodyStateSW.xml +++ b/doc/classes/Physics2DDirectBodyStateSW.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Physics2DDirectBodyStateSW" inherits="Physics2DDirectBodyState" category="Core" version="3.0-stable"> +<class name="Physics2DDirectBodyStateSW" inherits="Physics2DDirectBodyState" category="Core" version="3.1"> <brief_description> Software implementation of [Physics2DDirectBodyState]. </brief_description> diff --git a/doc/classes/Physics2DDirectSpaceState.xml b/doc/classes/Physics2DDirectSpaceState.xml index 5e0908f497..b55702dac4 100644 --- a/doc/classes/Physics2DDirectSpaceState.xml +++ b/doc/classes/Physics2DDirectSpaceState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Physics2DDirectSpaceState" inherits="Object" category="Core" version="3.0-stable"> +<class name="Physics2DDirectSpaceState" inherits="Object" category="Core" version="3.1"> <brief_description> Direct access object to a space in the [Physics2DServer]. </brief_description> diff --git a/doc/classes/Physics2DServer.xml b/doc/classes/Physics2DServer.xml index c0316aa1bc..98535dd330 100644 --- a/doc/classes/Physics2DServer.xml +++ b/doc/classes/Physics2DServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Physics2DServer" inherits="Object" category="Core" version="3.0-stable"> +<class name="Physics2DServer" inherits="Object" category="Core" version="3.1"> <brief_description> Physics 2D Server. </brief_description> @@ -713,9 +713,11 @@ </argument> <argument index="2" name="motion" type="Vector2"> </argument> - <argument index="3" name="margin" type="float" default="0.08"> + <argument index="3" name="infinite_inertia" type="bool"> </argument> - <argument index="4" name="result" type="Physics2DTestMotionResult" default="null"> + <argument index="4" name="margin" type="float" default="0.08"> + </argument> + <argument index="5" name="result" type="Physics2DTestMotionResult" default="null"> </argument> <description> Returns whether a body can move from a given point in a given direction. Apart from the boolean return value, a [Physics2DTestMotionResult] can be passed to return additional information in. diff --git a/doc/classes/Physics2DServerSW.xml b/doc/classes/Physics2DServerSW.xml index 6942c5e3af..49157bd94b 100644 --- a/doc/classes/Physics2DServerSW.xml +++ b/doc/classes/Physics2DServerSW.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Physics2DServerSW" inherits="Physics2DServer" category="Core" version="3.0-stable"> +<class name="Physics2DServerSW" inherits="Physics2DServer" category="Core" version="3.1"> <brief_description> Software implementation of [Physics2DServer]. </brief_description> diff --git a/doc/classes/Physics2DShapeQueryParameters.xml b/doc/classes/Physics2DShapeQueryParameters.xml index 7cd35f4167..391ad6276f 100644 --- a/doc/classes/Physics2DShapeQueryParameters.xml +++ b/doc/classes/Physics2DShapeQueryParameters.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Physics2DShapeQueryParameters" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Physics2DShapeQueryParameters" inherits="Reference" category="Core" version="3.1"> <brief_description> Parameters to be sent to a 2D shape physics query. </brief_description> diff --git a/doc/classes/Physics2DShapeQueryResult.xml b/doc/classes/Physics2DShapeQueryResult.xml index b080da43a2..52e7294e24 100644 --- a/doc/classes/Physics2DShapeQueryResult.xml +++ b/doc/classes/Physics2DShapeQueryResult.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Physics2DShapeQueryResult" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Physics2DShapeQueryResult" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/Physics2DTestMotionResult.xml b/doc/classes/Physics2DTestMotionResult.xml index 8b4260c484..3b864433f0 100644 --- a/doc/classes/Physics2DTestMotionResult.xml +++ b/doc/classes/Physics2DTestMotionResult.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Physics2DTestMotionResult" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Physics2DTestMotionResult" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/PhysicsBody.xml b/doc/classes/PhysicsBody.xml index 27db2c8f07..e252aaa048 100644 --- a/doc/classes/PhysicsBody.xml +++ b/doc/classes/PhysicsBody.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicsBody" inherits="CollisionObject" category="Core" version="3.0-stable"> +<class name="PhysicsBody" inherits="CollisionObject" category="Core" version="3.1"> <brief_description> Base class for all objects affected by physics in 3D space. </brief_description> diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml index 34e86fa63a..42b1eac5e4 100644 --- a/doc/classes/PhysicsBody2D.xml +++ b/doc/classes/PhysicsBody2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core" version="3.0-stable"> +<class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core" version="3.1"> <brief_description> Base class for all objects affected by physics in 2D space. </brief_description> diff --git a/doc/classes/PhysicsDirectBodyState.xml b/doc/classes/PhysicsDirectBodyState.xml index 1f9c492571..74190d0780 100644 --- a/doc/classes/PhysicsDirectBodyState.xml +++ b/doc/classes/PhysicsDirectBodyState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicsDirectBodyState" inherits="Object" category="Core" version="3.0-stable"> +<class name="PhysicsDirectBodyState" inherits="Object" category="Core" version="3.1"> <brief_description> </brief_description> <description> @@ -9,6 +9,14 @@ <demos> </demos> <methods> + <method name="add_central_force"> + <return type="void"> + </return> + <argument index="0" name="force" type="Vector3"> + </argument> + <description> + </description> + </method> <method name="add_force"> <return type="void"> </return> @@ -19,6 +27,14 @@ <description> </description> </method> + <method name="add_torque"> + <return type="void"> + </return> + <argument index="0" name="torque" type="Vector3"> + </argument> + <description> + </description> + </method> <method name="apply_impulse"> <return type="void"> </return> @@ -29,7 +45,7 @@ <description> </description> </method> - <method name="apply_torqe_impulse"> + <method name="apply_torque_impulse"> <return type="void"> </return> <argument index="0" name="j" type="Vector3"> diff --git a/doc/classes/PhysicsDirectSpaceState.xml b/doc/classes/PhysicsDirectSpaceState.xml index 6c8d084f26..fabf153dac 100644 --- a/doc/classes/PhysicsDirectSpaceState.xml +++ b/doc/classes/PhysicsDirectSpaceState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicsDirectSpaceState" inherits="Object" category="Core" version="3.0-stable"> +<class name="PhysicsDirectSpaceState" inherits="Object" category="Core" version="3.1"> <brief_description> Direct access object to a space in the [PhysicsServer]. </brief_description> diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml index 9920d5364b..6c3a435360 100644 --- a/doc/classes/PhysicsServer.xml +++ b/doc/classes/PhysicsServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicsServer" inherits="Object" category="Core" version="3.0-stable"> +<class name="PhysicsServer" inherits="Object" category="Core" version="3.1"> <brief_description> Server interface for low level physics access. </brief_description> diff --git a/doc/classes/PhysicsShapeQueryParameters.xml b/doc/classes/PhysicsShapeQueryParameters.xml index 3f68136285..2f36e81e27 100644 --- a/doc/classes/PhysicsShapeQueryParameters.xml +++ b/doc/classes/PhysicsShapeQueryParameters.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicsShapeQueryParameters" inherits="Reference" category="Core" version="3.0-stable"> +<class name="PhysicsShapeQueryParameters" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/PhysicsShapeQueryResult.xml b/doc/classes/PhysicsShapeQueryResult.xml index 109074c35c..080d7389b7 100644 --- a/doc/classes/PhysicsShapeQueryResult.xml +++ b/doc/classes/PhysicsShapeQueryResult.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicsShapeQueryResult" inherits="Reference" category="Core" version="3.0-stable"> +<class name="PhysicsShapeQueryResult" inherits="Reference" category="Core" version="3.1"> <brief_description> Result of a shape query in Physics2DServer. </brief_description> diff --git a/doc/classes/PinJoint.xml b/doc/classes/PinJoint.xml index a8cc0ad9b3..470c22cd4c 100644 --- a/doc/classes/PinJoint.xml +++ b/doc/classes/PinJoint.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PinJoint" inherits="Joint" category="Core" version="3.0-stable"> +<class name="PinJoint" inherits="Joint" category="Core" version="3.1"> <brief_description> Pin Joint for 3D Shapes. </brief_description> diff --git a/doc/classes/PinJoint2D.xml b/doc/classes/PinJoint2D.xml index 08fb849523..42708151ec 100644 --- a/doc/classes/PinJoint2D.xml +++ b/doc/classes/PinJoint2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PinJoint2D" inherits="Joint2D" category="Core" version="3.0-stable"> +<class name="PinJoint2D" inherits="Joint2D" category="Core" version="3.1"> <brief_description> Pin Joint for 2D Shapes. </brief_description> <description> - Pin Joint for 2D Rigid Bodies. It pins 2 bodies (rigid or static) together, or a single body to a fixed position in space. + Pin Joint for 2D Rigid Bodies. It pins two bodies (rigid or static) together. </description> <tutorials> </tutorials> diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml index b1984ec03f..157bf42239 100644 --- a/doc/classes/Plane.xml +++ b/doc/classes/Plane.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Plane" category="Built-In Types" version="3.0-stable"> +<class name="Plane" category="Built-In Types" version="3.1"> <brief_description> Plane in hessian form. </brief_description> diff --git a/doc/classes/PlaneMesh.xml b/doc/classes/PlaneMesh.xml index cd97d5c6eb..fc293ab4df 100644 --- a/doc/classes/PlaneMesh.xml +++ b/doc/classes/PlaneMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PlaneMesh" inherits="PrimitiveMesh" category="Core" version="3.0-stable"> +<class name="PlaneMesh" inherits="PrimitiveMesh" category="Core" version="3.1"> <brief_description> Class representing a planar [PrimitiveMesh]. </brief_description> diff --git a/doc/classes/PlaneShape.xml b/doc/classes/PlaneShape.xml index 5912a2a91b..bc3faf7c01 100644 --- a/doc/classes/PlaneShape.xml +++ b/doc/classes/PlaneShape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PlaneShape" inherits="Shape" category="Core" version="3.0-stable"> +<class name="PlaneShape" inherits="Shape" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/Polygon2D.xml b/doc/classes/Polygon2D.xml index 8c68c06e65..429114a128 100644 --- a/doc/classes/Polygon2D.xml +++ b/doc/classes/Polygon2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Polygon2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Polygon2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> A 2D polygon. </brief_description> @@ -31,6 +31,8 @@ <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. </member> + <member name="splits" type="PoolIntArray" setter="set_splits" getter="get_splits"> + </member> <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> The polygon's fill texture. Use [code]uv[/code] to set texture coordinates. </member> diff --git a/doc/classes/PolygonPathFinder.xml b/doc/classes/PolygonPathFinder.xml index cea33fa5c8..e4a4d9b976 100644 --- a/doc/classes/PolygonPathFinder.xml +++ b/doc/classes/PolygonPathFinder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PolygonPathFinder" inherits="Resource" category="Core" version="3.0-stable"> +<class name="PolygonPathFinder" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/PoolByteArray.xml b/doc/classes/PoolByteArray.xml index 5e80072d46..0118e7477a 100644 --- a/doc/classes/PoolByteArray.xml +++ b/doc/classes/PoolByteArray.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PoolByteArray" category="Built-In Types" version="3.0-stable"> +<class name="PoolByteArray" category="Built-In Types" version="3.1"> <brief_description> Raw byte array. </brief_description> diff --git a/doc/classes/PoolColorArray.xml b/doc/classes/PoolColorArray.xml index 47fb38f440..0a4221728e 100644 --- a/doc/classes/PoolColorArray.xml +++ b/doc/classes/PoolColorArray.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PoolColorArray" category="Built-In Types" version="3.0-stable"> +<class name="PoolColorArray" category="Built-In Types" version="3.1"> <brief_description> Array of Colors </brief_description> diff --git a/doc/classes/PoolIntArray.xml b/doc/classes/PoolIntArray.xml index c24d565db8..7709a69c84 100644 --- a/doc/classes/PoolIntArray.xml +++ b/doc/classes/PoolIntArray.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PoolIntArray" category="Built-In Types" version="3.0-stable"> +<class name="PoolIntArray" category="Built-In Types" version="3.1"> <brief_description> Integer Array. </brief_description> diff --git a/doc/classes/PoolRealArray.xml b/doc/classes/PoolRealArray.xml index 49f4ed85d2..19f31f7dfb 100644 --- a/doc/classes/PoolRealArray.xml +++ b/doc/classes/PoolRealArray.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PoolRealArray" category="Built-In Types" version="3.0-stable"> +<class name="PoolRealArray" category="Built-In Types" version="3.1"> <brief_description> Real Array. </brief_description> diff --git a/doc/classes/PoolStringArray.xml b/doc/classes/PoolStringArray.xml index bc273e2fb6..3d971d1ac9 100644 --- a/doc/classes/PoolStringArray.xml +++ b/doc/classes/PoolStringArray.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PoolStringArray" category="Built-In Types" version="3.0-stable"> +<class name="PoolStringArray" category="Built-In Types" version="3.1"> <brief_description> String Array. </brief_description> diff --git a/doc/classes/PoolVector2Array.xml b/doc/classes/PoolVector2Array.xml index d08cfbba33..14c226d019 100644 --- a/doc/classes/PoolVector2Array.xml +++ b/doc/classes/PoolVector2Array.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PoolVector2Array" category="Built-In Types" version="3.0-stable"> +<class name="PoolVector2Array" category="Built-In Types" version="3.1"> <brief_description> An Array of Vector2. </brief_description> diff --git a/doc/classes/PoolVector3Array.xml b/doc/classes/PoolVector3Array.xml index 99d5929ded..27ddfa10a5 100644 --- a/doc/classes/PoolVector3Array.xml +++ b/doc/classes/PoolVector3Array.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PoolVector3Array" category="Built-In Types" version="3.0-stable"> +<class name="PoolVector3Array" category="Built-In Types" version="3.1"> <brief_description> An Array of Vector3. </brief_description> diff --git a/doc/classes/Popup.xml b/doc/classes/Popup.xml index 0e6d6c844d..abf6ec3238 100644 --- a/doc/classes/Popup.xml +++ b/doc/classes/Popup.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Popup" inherits="Control" category="Core" version="3.0-stable"> +<class name="Popup" inherits="Control" category="Core" version="3.1"> <brief_description> Base container control for popups and dialogs. </brief_description> diff --git a/doc/classes/PopupDialog.xml b/doc/classes/PopupDialog.xml index b47674b588..4f15fb4b05 100644 --- a/doc/classes/PopupDialog.xml +++ b/doc/classes/PopupDialog.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PopupDialog" inherits="Popup" category="Core" version="3.0-stable"> +<class name="PopupDialog" inherits="Popup" category="Core" version="3.1"> <brief_description> Base class for Popup Dialogs. </brief_description> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 2ffdc07e1f..70e6fab5b6 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PopupMenu" inherits="Popup" category="Core" version="3.0-stable"> +<class name="PopupMenu" inherits="Popup" category="Core" version="3.1"> <brief_description> PopupMenu displays a list of options. </brief_description> diff --git a/doc/classes/PopupPanel.xml b/doc/classes/PopupPanel.xml index 0de5319f59..694c29efda 100644 --- a/doc/classes/PopupPanel.xml +++ b/doc/classes/PopupPanel.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PopupPanel" inherits="Popup" category="Core" version="3.0-stable"> +<class name="PopupPanel" inherits="Popup" category="Core" version="3.1"> <brief_description> Class for displaying popups with a panel background. </brief_description> diff --git a/doc/classes/Position2D.xml b/doc/classes/Position2D.xml index d06d9220a7..6c26bf412c 100644 --- a/doc/classes/Position2D.xml +++ b/doc/classes/Position2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Position2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Position2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Generic 2D Position hint for editing. </brief_description> diff --git a/doc/classes/Position3D.xml b/doc/classes/Position3D.xml index 5f3aa004dc..de29ac2154 100644 --- a/doc/classes/Position3D.xml +++ b/doc/classes/Position3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Position3D" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="Position3D" inherits="Spatial" category="Core" version="3.1"> <brief_description> Generic 3D Position hint for editing </brief_description> diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml index 7f0ee9ce37..c5bc3d6e47 100644 --- a/doc/classes/PrimitiveMesh.xml +++ b/doc/classes/PrimitiveMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PrimitiveMesh" inherits="Mesh" category="Core" version="3.0-stable"> +<class name="PrimitiveMesh" inherits="Mesh" category="Core" version="3.1"> <brief_description> Base class for all primitive meshes. Handles applying a [Material] to a primitive mesh. </brief_description> diff --git a/doc/classes/PrismMesh.xml b/doc/classes/PrismMesh.xml index 389acc9320..268395c37a 100644 --- a/doc/classes/PrismMesh.xml +++ b/doc/classes/PrismMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PrismMesh" inherits="PrimitiveMesh" category="Core" version="3.0-stable"> +<class name="PrismMesh" inherits="PrimitiveMesh" category="Core" version="3.1"> <brief_description> Class representing a prism-shaped [PrimitiveMesh]. </brief_description> diff --git a/doc/classes/ProceduralSky.xml b/doc/classes/ProceduralSky.xml index 9d7e590fa3..11af73f953 100644 --- a/doc/classes/ProceduralSky.xml +++ b/doc/classes/ProceduralSky.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ProceduralSky" inherits="Sky" category="Core" version="3.0-stable"> +<class name="ProceduralSky" inherits="Sky" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml index 321f27008d..919ecd7c86 100644 --- a/doc/classes/ProgressBar.xml +++ b/doc/classes/ProgressBar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ProgressBar" inherits="Range" category="Core" version="3.0-stable"> +<class name="ProgressBar" inherits="Range" category="Core" version="3.1"> <brief_description> General purpose progress bar. </brief_description> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 7d0856127c..44bba8bd20 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ProjectSettings" inherits="Object" category="Core" version="3.0-stable"> +<class name="ProjectSettings" inherits="Object" category="Core" version="3.1"> <brief_description> Contains global variables accessible from everywhere. </brief_description> diff --git a/doc/classes/ProximityGroup.xml b/doc/classes/ProximityGroup.xml index b4a424dfdd..1f1c45fbf9 100644 --- a/doc/classes/ProximityGroup.xml +++ b/doc/classes/ProximityGroup.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ProximityGroup" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="ProximityGroup" inherits="Spatial" category="Core" version="3.1"> <brief_description> General purpose proximity-detection node. </brief_description> diff --git a/doc/classes/ProxyTexture.xml b/doc/classes/ProxyTexture.xml index 68f03ca4fa..69702ee22e 100644 --- a/doc/classes/ProxyTexture.xml +++ b/doc/classes/ProxyTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ProxyTexture" inherits="Texture" category="Core" version="3.0-stable"> +<class name="ProxyTexture" inherits="Texture" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/QuadMesh.xml b/doc/classes/QuadMesh.xml index f1b38d379a..a45b2ddf4b 100644 --- a/doc/classes/QuadMesh.xml +++ b/doc/classes/QuadMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="QuadMesh" inherits="PrimitiveMesh" category="Core" version="3.0-stable"> +<class name="QuadMesh" inherits="PrimitiveMesh" category="Core" version="3.1"> <brief_description> Class representing a square mesh. </brief_description> diff --git a/doc/classes/Quat.xml b/doc/classes/Quat.xml index ead73d0267..3a258011b2 100644 --- a/doc/classes/Quat.xml +++ b/doc/classes/Quat.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Quat" category="Built-In Types" version="3.0-stable"> +<class name="Quat" category="Built-In Types" version="3.1"> <brief_description> Quaternion. </brief_description> diff --git a/doc/classes/RID.xml b/doc/classes/RID.xml index 1510d75679..ee34560afd 100644 --- a/doc/classes/RID.xml +++ b/doc/classes/RID.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RID" category="Built-In Types" version="3.0-stable"> +<class name="RID" category="Built-In Types" version="3.1"> <brief_description> Handle for a [Resource]'s unique ID. </brief_description> diff --git a/doc/classes/Range.xml b/doc/classes/Range.xml index 8a0c831805..545f5cc83b 100644 --- a/doc/classes/Range.xml +++ b/doc/classes/Range.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Range" inherits="Control" category="Core" version="3.0-stable"> +<class name="Range" inherits="Control" category="Core" version="3.1"> <brief_description> Abstract base class for range-based controls. </brief_description> diff --git a/doc/classes/RayCast.xml b/doc/classes/RayCast.xml index 09e0f8b643..dce73d9c29 100644 --- a/doc/classes/RayCast.xml +++ b/doc/classes/RayCast.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RayCast" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="RayCast" inherits="Spatial" category="Core" version="3.1"> <brief_description> Query the closest object intersecting a ray. </brief_description> diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml index b76c880bb7..79e733bcdc 100644 --- a/doc/classes/RayCast2D.xml +++ b/doc/classes/RayCast2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RayCast2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="RayCast2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Query the closest object intersecting a ray. </brief_description> diff --git a/doc/classes/RayShape.xml b/doc/classes/RayShape.xml index 6d83ed2903..e03541011d 100644 --- a/doc/classes/RayShape.xml +++ b/doc/classes/RayShape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RayShape" inherits="Shape" category="Core" version="3.0-stable"> +<class name="RayShape" inherits="Shape" category="Core" version="3.1"> <brief_description> Ray shape for 3D collisions. </brief_description> @@ -16,6 +16,9 @@ <member name="length" type="float" setter="set_length" getter="get_length"> The ray's length. </member> + <member name="slips_on_slope" type="bool" setter="set_slips_on_slope" getter="get_slips_on_slope"> + If [code]true[/code] allow the shape to return the correct normal. Default value: [code]false[/code]. + </member> </members> <constants> </constants> diff --git a/doc/classes/RayShape2D.xml b/doc/classes/RayShape2D.xml index ce004b582b..37cfe4f2d3 100644 --- a/doc/classes/RayShape2D.xml +++ b/doc/classes/RayShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RayShape2D" inherits="Shape2D" category="Core" version="3.0-stable"> +<class name="RayShape2D" inherits="Shape2D" category="Core" version="3.1"> <brief_description> Ray shape for 2D collisions. </brief_description> @@ -16,6 +16,9 @@ <member name="length" type="float" setter="set_length" getter="get_length"> The ray's length. </member> + <member name="slips_on_slope" type="bool" setter="set_slips_on_slope" getter="get_slips_on_slope"> + If [code]true[/code] allow the shape to return the correct normal. Default value: [code]false[/code]. + </member> </members> <constants> </constants> diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml index 6d953d2615..1961aee8b5 100644 --- a/doc/classes/Rect2.xml +++ b/doc/classes/Rect2.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Rect2" category="Built-In Types" version="3.0-stable"> +<class name="Rect2" category="Built-In Types" version="3.1"> <brief_description> 2D Axis-aligned bounding box. </brief_description> diff --git a/doc/classes/RectangleShape2D.xml b/doc/classes/RectangleShape2D.xml index 4ecd0aadf4..4a312503f4 100644 --- a/doc/classes/RectangleShape2D.xml +++ b/doc/classes/RectangleShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RectangleShape2D" inherits="Shape2D" category="Core" version="3.0-stable"> +<class name="RectangleShape2D" inherits="Shape2D" category="Core" version="3.1"> <brief_description> Rectangle shape for 2D collisions. </brief_description> diff --git a/doc/classes/Reference.xml b/doc/classes/Reference.xml index ba769db5e7..3238501633 100644 --- a/doc/classes/Reference.xml +++ b/doc/classes/Reference.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Reference" inherits="Object" category="Core" version="3.0-stable"> +<class name="Reference" inherits="Object" category="Core" version="3.1"> <brief_description> Base class for anything that keeps a reference count. </brief_description> diff --git a/doc/classes/ReferenceRect.xml b/doc/classes/ReferenceRect.xml index 2a13eb3312..4453e8726f 100644 --- a/doc/classes/ReferenceRect.xml +++ b/doc/classes/ReferenceRect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ReferenceRect" inherits="Control" category="Core" version="3.0-stable"> +<class name="ReferenceRect" inherits="Control" category="Core" version="3.1"> <brief_description> Reference frame for GUI. </brief_description> diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml index 5db9f32486..36a0c9cfda 100644 --- a/doc/classes/ReflectionProbe.xml +++ b/doc/classes/ReflectionProbe.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ReflectionProbe" inherits="VisualInstance" category="Core" version="3.0-stable"> +<class name="ReflectionProbe" inherits="VisualInstance" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/RemoteTransform.xml b/doc/classes/RemoteTransform.xml index e9b8d2b746..a7deb273b6 100644 --- a/doc/classes/RemoteTransform.xml +++ b/doc/classes/RemoteTransform.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RemoteTransform" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="RemoteTransform" inherits="Spatial" category="Core" version="3.1"> <brief_description> RemoteTransform leads the [Transform] of another [Spatial] derived Node in the scene. </brief_description> diff --git a/doc/classes/RemoteTransform2D.xml b/doc/classes/RemoteTransform2D.xml index c6022fd1ff..bc562dcdad 100644 --- a/doc/classes/RemoteTransform2D.xml +++ b/doc/classes/RemoteTransform2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RemoteTransform2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="RemoteTransform2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> RemoteTransform2D leads the [Transform2D] of another [CanvasItem] derived Node in the scene. </brief_description> diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml index 8113d81fbb..fc42635ce2 100644 --- a/doc/classes/Resource.xml +++ b/doc/classes/Resource.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Resource" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Resource" inherits="Reference" category="Core" version="3.1"> <brief_description> Base class for all resources. </brief_description> diff --git a/doc/classes/ResourceImporter.xml b/doc/classes/ResourceImporter.xml index c68bdd613c..09fe828bd3 100644 --- a/doc/classes/ResourceImporter.xml +++ b/doc/classes/ResourceImporter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceImporter" inherits="Reference" category="Core" version="3.0-stable"> +<class name="ResourceImporter" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/ResourceInteractiveLoader.xml b/doc/classes/ResourceInteractiveLoader.xml index 8a8023c8ec..076121b42d 100644 --- a/doc/classes/ResourceInteractiveLoader.xml +++ b/doc/classes/ResourceInteractiveLoader.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceInteractiveLoader" inherits="Reference" category="Core" version="3.0-stable"> +<class name="ResourceInteractiveLoader" inherits="Reference" category="Core" version="3.1"> <brief_description> Interactive Resource Loader. </brief_description> diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml index d4f61b7929..ac00c13b2f 100644 --- a/doc/classes/ResourceLoader.xml +++ b/doc/classes/ResourceLoader.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceLoader" inherits="Object" category="Core" version="3.0-stable"> +<class name="ResourceLoader" inherits="Object" category="Core" version="3.1"> <brief_description> Resource Loader. </brief_description> diff --git a/doc/classes/ResourcePreloader.xml b/doc/classes/ResourcePreloader.xml index 868ca62963..002bcd891a 100644 --- a/doc/classes/ResourcePreloader.xml +++ b/doc/classes/ResourcePreloader.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourcePreloader" inherits="Node" category="Core" version="3.0-stable"> +<class name="ResourcePreloader" inherits="Node" category="Core" version="3.1"> <brief_description> Resource Preloader Node. </brief_description> diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml index f4abe9f770..ae0d8e909d 100644 --- a/doc/classes/ResourceSaver.xml +++ b/doc/classes/ResourceSaver.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceSaver" inherits="Object" category="Core" version="3.0-stable"> +<class name="ResourceSaver" inherits="Object" category="Core" version="3.1"> <brief_description> Resource Saving Interface. </brief_description> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 24ae94d6db..49bb1aed45 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RichTextLabel" inherits="Control" category="Core" version="3.0-stable"> +<class name="RichTextLabel" inherits="Control" category="Core" version="3.1"> <brief_description> Label that displays rich text. </brief_description> diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml index ad5da50dd6..3190aed5ed 100644 --- a/doc/classes/RigidBody.xml +++ b/doc/classes/RigidBody.xml @@ -1,14 +1,13 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RigidBody" inherits="PhysicsBody" category="Core" version="3.0-stable"> +<class name="RigidBody" inherits="PhysicsBody" category="Core" version="3.1"> <brief_description> Physics Body whose position is determined through physics simulation in 3D space. </brief_description> <description> This is the node that implements full 3D physics. This means that you do not control a RigidBody directly. Instead you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. - This node can use custom force integration, for writing complex physics motion behavior per node. - This node can shift state between regular Rigid body, Kinematic, Character or Static. - Character mode forbids this node from being rotated. - As a warning, don't change RigidBody's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior. + A RigidBody has 4 behavior [member mode]s: Rigid, Static, Character, and Kinematic. + [b]Note:[/b] Don't change a RigidBody's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. + If you need to override the default physics behavior, you can write a custom force integration. See [member custom_integrator]. </description> <tutorials> http://docs.godotengine.org/en/3.0/tutorials/physics/physics_introduction.html @@ -36,6 +35,15 @@ 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. </description> </method> + <method name="apply_torque_impulse"> + <return type="void"> + </return> + <argument index="0" name="impulse" type="Vector3"> + </argument> + <description> + Apply a torque impulse (which will be affected by the body mass and shape). This will rotate the body around the passed in vector. + </description> + </method> <method name="get_colliding_bodies" qualifiers="const"> <return type="Array"> </return> diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index 67ae92c664..75fbb48454 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -1,15 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RigidBody2D" inherits="PhysicsBody2D" category="Core" version="3.0-stable"> +<class name="RigidBody2D" inherits="PhysicsBody2D" category="Core" version="3.1"> <brief_description> A body that is controlled by the 2D physics engine. </brief_description> <description> This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. - A RigidBody2D has 4 behavior modes (see [member mode]): - - [b]Rigid[/b]: The body behaves as a physical object. It collides with other bodies and responds to forces applied to it. This is the default mode. - - [b]Static[/b]: The body behaves like a [StaticBody2D] and does not move. - - [b]Character[/b]: Similar to [code]Rigid[/code] mode, but the body can not rotate. - - [b]Kinematic[/b]: The body behaves like a [KinematicBody2D], and must be moved by code. + A RigidBody2D has 4 behavior [member mode]s: Rigid, Static, Character, and Kinematic. [b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. If you need to override the default physics behavior, you can write a custom force integration. See [member custom_integrator]. </description> @@ -70,9 +66,11 @@ </return> <argument index="0" name="motion" type="Vector2"> </argument> - <argument index="1" name="margin" type="float" default="0.08"> + <argument index="1" name="infinite_inertia" type="bool" default="true"> </argument> - <argument index="2" name="result" type="Physics2DTestMotionResult" default="null"> + <argument index="2" name="margin" type="float" default="0.08"> + </argument> + <argument index="3" name="result" type="Physics2DTestMotionResult" default="null"> </argument> <description> Returns [code]true[/code] if a collision would result from moving in the given vector. [code]margin[/code] increases the size of the shapes involved in the collision detection, and [code]result[/code] is an object of type [Physics2DTestMotionResult], which contains additional information about the collision (should there be one). diff --git a/doc/classes/SceneState.xml b/doc/classes/SceneState.xml index 6fec02c392..36cddf08df 100644 --- a/doc/classes/SceneState.xml +++ b/doc/classes/SceneState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SceneState" inherits="Reference" category="Core" version="3.0-stable"> +<class name="SceneState" inherits="Reference" category="Core" version="3.1"> <brief_description> A script interface to a scene file's data. </brief_description> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 0fe220ae48..be90288308 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SceneTree" inherits="MainLoop" category="Core" version="3.0-stable"> +<class name="SceneTree" inherits="MainLoop" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/SceneTreeTimer.xml b/doc/classes/SceneTreeTimer.xml index f6b262d225..e1234ce88a 100644 --- a/doc/classes/SceneTreeTimer.xml +++ b/doc/classes/SceneTreeTimer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SceneTreeTimer" inherits="Reference" category="Core" version="3.0-stable"> +<class name="SceneTreeTimer" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/Script.xml b/doc/classes/Script.xml index 787d2c24bf..4257991e0d 100644 --- a/doc/classes/Script.xml +++ b/doc/classes/Script.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Script" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Script" inherits="Resource" category="Core" version="3.1"> <brief_description> A class stored as a resource. </brief_description> diff --git a/doc/classes/ScriptEditor.xml b/doc/classes/ScriptEditor.xml index 89a8200d66..4bfd07fdad 100644 --- a/doc/classes/ScriptEditor.xml +++ b/doc/classes/ScriptEditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ScriptEditor" inherits="PanelContainer" category="Core" version="3.0-stable"> +<class name="ScriptEditor" inherits="PanelContainer" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/ScrollBar.xml b/doc/classes/ScrollBar.xml index 53b20e55d5..d3e6c62e49 100644 --- a/doc/classes/ScrollBar.xml +++ b/doc/classes/ScrollBar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ScrollBar" inherits="Range" category="Core" version="3.0-stable"> +<class name="ScrollBar" inherits="Range" category="Core" version="3.1"> <brief_description> Base class for scroll bars. </brief_description> diff --git a/doc/classes/ScrollContainer.xml b/doc/classes/ScrollContainer.xml index a1e6441d1c..79b70fec99 100644 --- a/doc/classes/ScrollContainer.xml +++ b/doc/classes/ScrollContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ScrollContainer" inherits="Container" category="Core" version="3.0-stable"> +<class name="ScrollContainer" inherits="Container" category="Core" version="3.1"> <brief_description> A helper node for displaying scrollable elements (e.g. lists). </brief_description> diff --git a/doc/classes/SegmentShape2D.xml b/doc/classes/SegmentShape2D.xml index 56d9fe6d31..63afb37a7b 100644 --- a/doc/classes/SegmentShape2D.xml +++ b/doc/classes/SegmentShape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SegmentShape2D" inherits="Shape2D" category="Core" version="3.0-stable"> +<class name="SegmentShape2D" inherits="Shape2D" category="Core" version="3.1"> <brief_description> Segment shape for 2D collisions. </brief_description> diff --git a/doc/classes/Semaphore.xml b/doc/classes/Semaphore.xml index 3d6f894f52..f3a37b78e1 100644 --- a/doc/classes/Semaphore.xml +++ b/doc/classes/Semaphore.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Semaphore" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Semaphore" inherits="Reference" category="Core" version="3.1"> <brief_description> A synchronization Semaphore. </brief_description> diff --git a/doc/classes/Separator.xml b/doc/classes/Separator.xml index 20cf870d75..e5efa4a100 100644 --- a/doc/classes/Separator.xml +++ b/doc/classes/Separator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Separator" inherits="Control" category="Core" version="3.0-stable"> +<class name="Separator" inherits="Control" category="Core" version="3.1"> <brief_description> Base class for separators. </brief_description> diff --git a/doc/classes/Shader.xml b/doc/classes/Shader.xml index 28f06f0caa..732881c777 100644 --- a/doc/classes/Shader.xml +++ b/doc/classes/Shader.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Shader" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Shader" inherits="Resource" category="Core" version="3.1"> <brief_description> To be changed, ignore. </brief_description> diff --git a/doc/classes/ShaderMaterial.xml b/doc/classes/ShaderMaterial.xml index 893746ec31..4767686a8f 100644 --- a/doc/classes/ShaderMaterial.xml +++ b/doc/classes/ShaderMaterial.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ShaderMaterial" inherits="Material" category="Core" version="3.0-stable"> +<class name="ShaderMaterial" inherits="Material" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/Shape.xml b/doc/classes/Shape.xml index 986d567c12..582e4f80c3 100644 --- a/doc/classes/Shape.xml +++ b/doc/classes/Shape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Shape" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Shape" inherits="Resource" category="Core" version="3.1"> <brief_description> Base class for all 3D shape resources. </brief_description> diff --git a/doc/classes/Shape2D.xml b/doc/classes/Shape2D.xml index d2366faa7f..ad20bf607a 100644 --- a/doc/classes/Shape2D.xml +++ b/doc/classes/Shape2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Shape2D" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Shape2D" inherits="Resource" category="Core" version="3.1"> <brief_description> Base class for all 2D Shapes. </brief_description> diff --git a/doc/classes/ShortCut.xml b/doc/classes/ShortCut.xml index f0908cfa44..6da9d7c59d 100644 --- a/doc/classes/ShortCut.xml +++ b/doc/classes/ShortCut.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ShortCut" inherits="Resource" category="Core" version="3.0-stable"> +<class name="ShortCut" inherits="Resource" category="Core" version="3.1"> <brief_description> A shortcut for binding input. </brief_description> diff --git a/doc/classes/Skeleton.xml b/doc/classes/Skeleton.xml index 33022cca14..0208d56cfa 100644 --- a/doc/classes/Skeleton.xml +++ b/doc/classes/Skeleton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Skeleton" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="Skeleton" inherits="Spatial" category="Core" version="3.1"> <brief_description> Skeleton for characters and animated objects. </brief_description> diff --git a/doc/classes/Sky.xml b/doc/classes/Sky.xml index 3cd3957f40..245da99084 100644 --- a/doc/classes/Sky.xml +++ b/doc/classes/Sky.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Sky" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Sky" inherits="Resource" category="Core" version="3.1"> <brief_description> The base class for [PanoramaSky] and [ProceduralSky]. </brief_description> diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml index 84c51572c3..554842b50e 100644 --- a/doc/classes/Slider.xml +++ b/doc/classes/Slider.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Slider" inherits="Range" category="Core" version="3.0-stable"> +<class name="Slider" inherits="Range" category="Core" version="3.1"> <brief_description> Base class for GUI Sliders. </brief_description> diff --git a/doc/classes/SliderJoint.xml b/doc/classes/SliderJoint.xml index 4507668292..edb8e6d562 100644 --- a/doc/classes/SliderJoint.xml +++ b/doc/classes/SliderJoint.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SliderJoint" inherits="Joint" category="Core" version="3.0-stable"> +<class name="SliderJoint" inherits="Joint" category="Core" version="3.1"> <brief_description> Piston kind of slider between two bodies in 3D. </brief_description> diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml index 26f6f4003b..822a699984 100644 --- a/doc/classes/Spatial.xml +++ b/doc/classes/Spatial.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Spatial" inherits="Node" category="Core" version="3.0-stable"> +<class name="Spatial" inherits="Node" category="Core" version="3.1"> <brief_description> Most basic 3D game object, parent of all 3D related nodes. </brief_description> diff --git a/doc/classes/SpatialGizmo.xml b/doc/classes/SpatialGizmo.xml index cf6f0efd46..68d1d03296 100644 --- a/doc/classes/SpatialGizmo.xml +++ b/doc/classes/SpatialGizmo.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SpatialGizmo" inherits="Reference" category="Core" version="3.0-stable"> +<class name="SpatialGizmo" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/SpatialMaterial.xml b/doc/classes/SpatialMaterial.xml index eef18c9892..ace1aa846e 100644 --- a/doc/classes/SpatialMaterial.xml +++ b/doc/classes/SpatialMaterial.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SpatialMaterial" inherits="Material" category="Core" version="3.0-stable"> +<class name="SpatialMaterial" inherits="Material" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/SpatialVelocityTracker.xml b/doc/classes/SpatialVelocityTracker.xml index 276b82899b..45cc4232dc 100644 --- a/doc/classes/SpatialVelocityTracker.xml +++ b/doc/classes/SpatialVelocityTracker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SpatialVelocityTracker" inherits="Reference" category="Core" version="3.0-stable"> +<class name="SpatialVelocityTracker" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/SphereMesh.xml b/doc/classes/SphereMesh.xml index 9f2d613267..e0e2d10408 100644 --- a/doc/classes/SphereMesh.xml +++ b/doc/classes/SphereMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SphereMesh" inherits="PrimitiveMesh" category="Core" version="3.0-stable"> +<class name="SphereMesh" inherits="PrimitiveMesh" category="Core" version="3.1"> <brief_description> Class representing a spherical [PrimitiveMesh]. </brief_description> diff --git a/doc/classes/SphereShape.xml b/doc/classes/SphereShape.xml index a8df924bde..bc0cd79ddd 100644 --- a/doc/classes/SphereShape.xml +++ b/doc/classes/SphereShape.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SphereShape" inherits="Shape" category="Core" version="3.0-stable"> +<class name="SphereShape" inherits="Shape" category="Core" version="3.1"> <brief_description> Sphere shape for 3D collisions. </brief_description> diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml index 1762a66302..0fcd5bbaf5 100644 --- a/doc/classes/SpinBox.xml +++ b/doc/classes/SpinBox.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SpinBox" inherits="Range" category="Core" version="3.0-stable"> +<class name="SpinBox" inherits="Range" category="Core" version="3.1"> <brief_description> Numerical input text field. </brief_description> diff --git a/doc/classes/SplitContainer.xml b/doc/classes/SplitContainer.xml index 3a7f22693a..692598f382 100644 --- a/doc/classes/SplitContainer.xml +++ b/doc/classes/SplitContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SplitContainer" inherits="Container" category="Core" version="3.0-stable"> +<class name="SplitContainer" inherits="Container" category="Core" version="3.1"> <brief_description> Container for splitting and adjusting. </brief_description> diff --git a/doc/classes/SpotLight.xml b/doc/classes/SpotLight.xml index 00991e75bc..57a802d325 100644 --- a/doc/classes/SpotLight.xml +++ b/doc/classes/SpotLight.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SpotLight" inherits="Light" category="Core" version="3.0-stable"> +<class name="SpotLight" inherits="Light" category="Core" version="3.1"> <brief_description> Spotlight [Light], such as a reflector spotlight or a lantern. </brief_description> diff --git a/doc/classes/Sprite.xml b/doc/classes/Sprite.xml index c1afb35e09..dd7fe010ba 100644 --- a/doc/classes/Sprite.xml +++ b/doc/classes/Sprite.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Sprite" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="Sprite" inherits="Node2D" category="Core" version="3.1"> <brief_description> General purpose Sprite node. </brief_description> @@ -11,6 +11,13 @@ <demos> </demos> <methods> + <method name="get_rect" qualifiers="const"> + <return type="Rect2"> + </return> + <description> + Returns a Rect2 representing the Sprite's boundary relative to its local coordinates. + </description> + </method> </methods> <members> <member name="centered" type="bool" setter="set_centered" getter="is_centered"> @@ -26,7 +33,7 @@ Current frame to display from sprite sheet. [member vframes] or [member hframes] must be greater than 1. </member> <member name="hframes" type="int" setter="set_hframes" getter="get_hframes"> - The number of collumns in the sprite sheet. + The number of columns in the sprite sheet. </member> <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map"> The normal map gives depth to the Sprite. diff --git a/doc/classes/Sprite3D.xml b/doc/classes/Sprite3D.xml index ca0bd212aa..2a65246dde 100644 --- a/doc/classes/Sprite3D.xml +++ b/doc/classes/Sprite3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Sprite3D" inherits="SpriteBase3D" category="Core" version="3.0-stable"> +<class name="Sprite3D" inherits="SpriteBase3D" category="Core" version="3.1"> <brief_description> 2D Sprite node in 3D world. </brief_description> diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml index d91314e236..5eb4eb09af 100644 --- a/doc/classes/SpriteBase3D.xml +++ b/doc/classes/SpriteBase3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SpriteBase3D" inherits="GeometryInstance" category="Core" version="3.0-stable"> +<class name="SpriteBase3D" inherits="GeometryInstance" category="Core" version="3.1"> <brief_description> 2D Sprite node in 3D environment. </brief_description> diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml index f76212b0d2..e806547b7d 100644 --- a/doc/classes/SpriteFrames.xml +++ b/doc/classes/SpriteFrames.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SpriteFrames" inherits="Resource" category="Core" version="3.0-stable"> +<class name="SpriteFrames" inherits="Resource" category="Core" version="3.1"> <brief_description> Sprite frame library for AnimatedSprite. </brief_description> diff --git a/doc/classes/StaticBody.xml b/doc/classes/StaticBody.xml index e5b9d1c0d9..26b4857670 100644 --- a/doc/classes/StaticBody.xml +++ b/doc/classes/StaticBody.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StaticBody" inherits="PhysicsBody" category="Core" version="3.0-stable"> +<class name="StaticBody" inherits="PhysicsBody" category="Core" version="3.1"> <brief_description> Static body for 3D Physics. </brief_description> diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml index d9e750f4f6..95acda79df 100644 --- a/doc/classes/StaticBody2D.xml +++ b/doc/classes/StaticBody2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StaticBody2D" inherits="PhysicsBody2D" category="Core" version="3.0-stable"> +<class name="StaticBody2D" inherits="PhysicsBody2D" category="Core" version="3.1"> <brief_description> Static body for 2D Physics. </brief_description> diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml index 49aa26a601..ebe29c7e24 100644 --- a/doc/classes/StreamPeer.xml +++ b/doc/classes/StreamPeer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamPeer" inherits="Reference" category="Core" version="3.0-stable"> +<class name="StreamPeer" inherits="Reference" category="Core" version="3.1"> <brief_description> Abstraction and base class for stream-based protocols. </brief_description> diff --git a/doc/classes/StreamPeerBuffer.xml b/doc/classes/StreamPeerBuffer.xml index 2c95a8a3cf..3d9bdce762 100644 --- a/doc/classes/StreamPeerBuffer.xml +++ b/doc/classes/StreamPeerBuffer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamPeerBuffer" inherits="StreamPeer" category="Core" version="3.0-stable"> +<class name="StreamPeerBuffer" inherits="StreamPeer" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/StreamPeerSSL.xml b/doc/classes/StreamPeerSSL.xml index 62e5240c7f..d7350ac1d5 100644 --- a/doc/classes/StreamPeerSSL.xml +++ b/doc/classes/StreamPeerSSL.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamPeerSSL" inherits="StreamPeer" category="Core" version="3.0-stable"> +<class name="StreamPeerSSL" inherits="StreamPeer" category="Core" version="3.1"> <brief_description> SSL Stream peer. </brief_description> diff --git a/doc/classes/StreamPeerTCP.xml b/doc/classes/StreamPeerTCP.xml index 73e9b97367..5fc8e99ced 100644 --- a/doc/classes/StreamPeerTCP.xml +++ b/doc/classes/StreamPeerTCP.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamPeerTCP" inherits="StreamPeer" category="Core" version="3.0-stable"> +<class name="StreamPeerTCP" inherits="StreamPeer" category="Core" version="3.1"> <brief_description> TCP Stream peer. </brief_description> @@ -29,16 +29,6 @@ Disconnect from host. </description> </method> - <method name="set_no_delay"> - <return type="void"> - </return> - <argument index="0" name="enabled" type="bool"> - </argument> - <description> - Disable Nagle algorithm to improve latency for small packets. - Note that for applications that send large packets, or need to transfer a lot of data, this can reduce total bandwidth. - </description> - </method> <method name="get_connected_host" qualifiers="const"> <return type="String"> </return> @@ -66,6 +56,16 @@ <description> </description> </method> + <method name="set_no_delay"> + <return type="void"> + </return> + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + Disable Nagle algorithm to improve latency for small packets. + Note that for applications that send large packets, or need to transfer a lot of data, this can reduce total bandwidth. + </description> + </method> </methods> <constants> <constant name="STATUS_NONE" value="0" enum="Status"> diff --git a/doc/classes/StreamTexture.xml b/doc/classes/StreamTexture.xml index c37b5d6fe4..3b44d0f00f 100644 --- a/doc/classes/StreamTexture.xml +++ b/doc/classes/StreamTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StreamTexture" inherits="Texture" category="Core" version="3.0-stable"> +<class name="StreamTexture" inherits="Texture" category="Core" version="3.1"> <brief_description> A .stex texture. </brief_description> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index bad4ada144..d8d432e30f 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="String" category="Built-In Types" version="3.0-stable"> +<class name="String" category="Built-In Types" version="3.1"> <brief_description> Built-in string class. </brief_description> diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml index a816b6a030..dee3e6db49 100644 --- a/doc/classes/StyleBox.xml +++ b/doc/classes/StyleBox.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StyleBox" inherits="Resource" category="Core" version="3.0-stable"> +<class name="StyleBox" inherits="Resource" category="Core" version="3.1"> <brief_description> Base class for drawing stylized boxes for the UI. </brief_description> diff --git a/doc/classes/StyleBoxEmpty.xml b/doc/classes/StyleBoxEmpty.xml index cd0bd9bf9d..a9eeeddd93 100644 --- a/doc/classes/StyleBoxEmpty.xml +++ b/doc/classes/StyleBoxEmpty.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StyleBoxEmpty" inherits="StyleBox" category="Core" version="3.0-stable"> +<class name="StyleBoxEmpty" inherits="StyleBox" category="Core" version="3.1"> <brief_description> Empty stylebox (does not display anything). </brief_description> diff --git a/doc/classes/StyleBoxFlat.xml b/doc/classes/StyleBoxFlat.xml index 2f26032c45..641d6214a4 100644 --- a/doc/classes/StyleBoxFlat.xml +++ b/doc/classes/StyleBoxFlat.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StyleBoxFlat" inherits="StyleBox" category="Core" version="3.0-stable"> +<class name="StyleBoxFlat" inherits="StyleBox" category="Core" version="3.1"> <brief_description> Customizable Stylebox with a given set of parameters. (no texture required) </brief_description> diff --git a/doc/classes/StyleBoxLine.xml b/doc/classes/StyleBoxLine.xml index ddabe9aede..c891c8cf83 100644 --- a/doc/classes/StyleBoxLine.xml +++ b/doc/classes/StyleBoxLine.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StyleBoxLine" inherits="StyleBox" category="Core" version="3.0-stable"> +<class name="StyleBoxLine" inherits="StyleBox" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/StyleBoxTexture.xml b/doc/classes/StyleBoxTexture.xml index 8bac0fc77e..d8c378fde2 100644 --- a/doc/classes/StyleBoxTexture.xml +++ b/doc/classes/StyleBoxTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="StyleBoxTexture" inherits="StyleBox" category="Core" version="3.0-stable"> +<class name="StyleBoxTexture" inherits="StyleBox" category="Core" version="3.1"> <brief_description> Texture Based 3x3 scale style. </brief_description> @@ -59,11 +59,11 @@ </member> <member name="modulate_color" type="Color" setter="set_modulate" getter="get_modulate"> </member> - <member name="normal_map" type="Resource" setter="set_normal_map" getter="get_normal_map"> + <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map"> </member> <member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect"> </member> - <member name="texture" type="Resource" setter="set_texture" getter="get_texture"> + <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> </member> </members> <signals> diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index 64978a8bef..d8644c5419 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SurfaceTool" inherits="Reference" category="Core" version="3.0-stable"> +<class name="SurfaceTool" inherits="Reference" category="Core" version="3.1"> <brief_description> Helper tool to create geometry. </brief_description> diff --git a/doc/classes/TCP_Server.xml b/doc/classes/TCP_Server.xml index b3db65de59..4e3544ce5c 100644 --- a/doc/classes/TCP_Server.xml +++ b/doc/classes/TCP_Server.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TCP_Server" inherits="Reference" category="Core" version="3.0-stable"> +<class name="TCP_Server" inherits="Reference" category="Core" version="3.1"> <brief_description> TCP Server. </brief_description> diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index 9806c03349..330487adf7 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TabContainer" inherits="Control" category="Core" version="3.0-stable"> +<class name="TabContainer" inherits="Control" category="Core" version="3.1"> <brief_description> Tabbed Container. </brief_description> diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml index e4df4d0a31..615bc83c2d 100644 --- a/doc/classes/Tabs.xml +++ b/doc/classes/Tabs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Tabs" inherits="Control" category="Core" version="3.0-stable"> +<class name="Tabs" inherits="Control" category="Core" version="3.1"> <brief_description> Tabs Control. </brief_description> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index f84ebede1c..8a71cb2059 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TextEdit" inherits="Control" category="Core" version="3.0-stable"> +<class name="TextEdit" inherits="Control" category="Core" version="3.1"> <brief_description> Multiline text editing control. </brief_description> diff --git a/doc/classes/Texture.xml b/doc/classes/Texture.xml index f21b41f939..3d3ceca150 100644 --- a/doc/classes/Texture.xml +++ b/doc/classes/Texture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Texture" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Texture" inherits="Resource" category="Core" version="3.1"> <brief_description> Texture for 2D and 3D. </brief_description> diff --git a/doc/classes/TextureButton.xml b/doc/classes/TextureButton.xml index 3bda04fe58..7e54ab9fe8 100644 --- a/doc/classes/TextureButton.xml +++ b/doc/classes/TextureButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TextureButton" inherits="BaseButton" category="Core" version="3.0-stable"> +<class name="TextureButton" inherits="BaseButton" category="Core" version="3.1"> <brief_description> Texture-based button. Supports Pressed, Hover, Disabled and Focused states. </brief_description> diff --git a/doc/classes/TextureProgress.xml b/doc/classes/TextureProgress.xml index 2456653786..18bd886b0b 100644 --- a/doc/classes/TextureProgress.xml +++ b/doc/classes/TextureProgress.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TextureProgress" inherits="Range" category="Core" version="3.0-stable"> +<class name="TextureProgress" inherits="Range" category="Core" version="3.1"> <brief_description> Texture-based progress bar. Useful for loading screens and life or stamina bars. </brief_description> diff --git a/doc/classes/TextureRect.xml b/doc/classes/TextureRect.xml index 8b0fc09a6d..7a4208ccea 100644 --- a/doc/classes/TextureRect.xml +++ b/doc/classes/TextureRect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TextureRect" inherits="Control" category="Core" version="3.0-stable"> +<class name="TextureRect" inherits="Control" category="Core" version="3.1"> <brief_description> Draws a sprite or a texture inside a User Interface. The texture can tile or not. </brief_description> diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml index 037f8cbd48..fe43b54d5e 100644 --- a/doc/classes/Theme.xml +++ b/doc/classes/Theme.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Theme" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Theme" inherits="Resource" category="Core" version="3.1"> <brief_description> Theme for controls. </brief_description> diff --git a/doc/classes/Thread.xml b/doc/classes/Thread.xml index c3d1d1b24f..48d075c7f5 100644 --- a/doc/classes/Thread.xml +++ b/doc/classes/Thread.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Thread" inherits="Reference" category="Core" version="3.0-stable"> +<class name="Thread" inherits="Reference" category="Core" version="3.1"> <brief_description> A unit of execution in a process. </brief_description> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index 058a92d99c..6ee9489995 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TileMap" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="TileMap" inherits="Node2D" category="Core" version="3.1"> <brief_description> Node for 2D tile-based maps. </brief_description> @@ -19,6 +19,13 @@ Clear all cells. </description> </method> + <method name="fix_invalid_tiles"> + <return type="void"> + </return> + <description> + Clear cells that does not exist in the tileset. + </description> + </method> <method name="get_cell" qualifiers="const"> <return type="int"> </return> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index 95a5e55176..10978970e9 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TileSet" inherits="Resource" category="Core" version="3.0-stable"> +<class name="TileSet" inherits="Resource" category="Core" version="3.1"> <brief_description> Tile library for tilemaps. </brief_description> diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml index 383d3199f5..aba1b78188 100644 --- a/doc/classes/Timer.xml +++ b/doc/classes/Timer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Timer" inherits="Node" category="Core" version="3.0-stable"> +<class name="Timer" inherits="Node" category="Core" version="3.1"> <brief_description> A countdown timer. </brief_description> diff --git a/doc/classes/ToolButton.xml b/doc/classes/ToolButton.xml index 6597dc96e0..1dbfd63010 100644 --- a/doc/classes/ToolButton.xml +++ b/doc/classes/ToolButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ToolButton" inherits="Button" category="Core" version="3.0-stable"> +<class name="ToolButton" inherits="Button" category="Core" version="3.1"> <brief_description> Flat button helper class. </brief_description> diff --git a/doc/classes/TouchScreenButton.xml b/doc/classes/TouchScreenButton.xml index c187274a9d..1b37ce95ba 100644 --- a/doc/classes/TouchScreenButton.xml +++ b/doc/classes/TouchScreenButton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TouchScreenButton" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="TouchScreenButton" inherits="Node2D" category="Core" version="3.1"> <brief_description> Button for touch screen devices. </brief_description> diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml index cf1c9ea032..df5c2ab3ae 100644 --- a/doc/classes/Transform.xml +++ b/doc/classes/Transform.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Transform" category="Built-In Types" version="3.0-stable"> +<class name="Transform" category="Built-In Types" version="3.1"> <brief_description> 3D Transformation. 3x4 matrix. </brief_description> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index e20f48ba14..d5427ad7f8 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Transform2D" category="Built-In Types" version="3.0-stable"> +<class name="Transform2D" category="Built-In Types" version="3.1"> <brief_description> 2D Transformation. 3x2 matrix. </brief_description> diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml index 53106f9c08..c4e9dbfb70 100644 --- a/doc/classes/Translation.xml +++ b/doc/classes/Translation.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Translation" inherits="Resource" category="Core" version="3.0-stable"> +<class name="Translation" inherits="Resource" category="Core" version="3.1"> <brief_description> Language Translation. </brief_description> diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml index 5b61f46f96..52d2b2cc47 100644 --- a/doc/classes/TranslationServer.xml +++ b/doc/classes/TranslationServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TranslationServer" inherits="Object" category="Core" version="3.0-stable"> +<class name="TranslationServer" inherits="Object" category="Core" version="3.1"> <brief_description> Server that manages all translations. Translations can be set to it and removed from it. </brief_description> diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index 09af7ee49a..25426ee72c 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Tree" inherits="Control" category="Core" version="3.0-stable"> +<class name="Tree" inherits="Control" category="Core" version="3.1"> <brief_description> Control to show a tree of items. </brief_description> @@ -280,7 +280,7 @@ </signal> <signal name="item_activated"> <description> - Emitted when an item is activated (double-clicked). + Emitted when an item's label is double-clicked. </description> </signal> <signal name="item_collapsed"> @@ -296,7 +296,7 @@ </signal> <signal name="item_double_clicked"> <description> - Emitted when an item is double clicked. + Emitted when an item's icon is double-clicked. </description> </signal> <signal name="item_edited"> diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index c41cfac37c..6448b26972 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TreeItem" inherits="Object" category="Core" version="3.0-stable"> +<class name="TreeItem" inherits="Object" category="Core" version="3.1"> <brief_description> Control for a single item inside a [Tree]. </brief_description> diff --git a/doc/classes/TriangleMesh.xml b/doc/classes/TriangleMesh.xml index 0a4ea1fa8f..2bdc7b61f4 100644 --- a/doc/classes/TriangleMesh.xml +++ b/doc/classes/TriangleMesh.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="TriangleMesh" inherits="Reference" category="Core" version="3.0-stable"> +<class name="TriangleMesh" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index d843c8341f..54e445d3ee 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Tween" inherits="Node" category="Core" version="3.0-stable"> +<class name="Tween" inherits="Node" category="Core" version="3.1"> <brief_description> Node useful for animations with unknown start and end points. </brief_description> diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml index c95723e083..a1a6d7f465 100644 --- a/doc/classes/UndoRedo.xml +++ b/doc/classes/UndoRedo.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="UndoRedo" inherits="Object" category="Core" version="3.0-stable"> +<class name="UndoRedo" inherits="Object" category="Core" version="3.1"> <brief_description> Helper to manage UndoRedo in the editor or custom tools. </brief_description> diff --git a/doc/classes/VBoxContainer.xml b/doc/classes/VBoxContainer.xml index f92335eef1..43a7be74c3 100644 --- a/doc/classes/VBoxContainer.xml +++ b/doc/classes/VBoxContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VBoxContainer" inherits="BoxContainer" category="Core" version="3.0-stable"> +<class name="VBoxContainer" inherits="BoxContainer" category="Core" version="3.1"> <brief_description> Vertical box container. </brief_description> diff --git a/doc/classes/VScrollBar.xml b/doc/classes/VScrollBar.xml index d533db98be..5486140870 100644 --- a/doc/classes/VScrollBar.xml +++ b/doc/classes/VScrollBar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VScrollBar" inherits="ScrollBar" category="Core" version="3.0-stable"> +<class name="VScrollBar" inherits="ScrollBar" category="Core" version="3.1"> <brief_description> Vertical version of [ScrollBar], which goes from left (min) to right (max). </brief_description> diff --git a/doc/classes/VSeparator.xml b/doc/classes/VSeparator.xml index c6082a905d..4890b2d930 100644 --- a/doc/classes/VSeparator.xml +++ b/doc/classes/VSeparator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VSeparator" inherits="Separator" category="Core" version="3.0-stable"> +<class name="VSeparator" inherits="Separator" category="Core" version="3.1"> <brief_description> Vertical version of [Separator]. </brief_description> diff --git a/doc/classes/VSlider.xml b/doc/classes/VSlider.xml index b91c8a7c2a..1dc1b795f7 100644 --- a/doc/classes/VSlider.xml +++ b/doc/classes/VSlider.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VSlider" inherits="Slider" category="Core" version="3.0-stable"> +<class name="VSlider" inherits="Slider" category="Core" version="3.1"> <brief_description> Vertical slider. </brief_description> diff --git a/doc/classes/VSplitContainer.xml b/doc/classes/VSplitContainer.xml index e6e6e189e8..2203035db3 100644 --- a/doc/classes/VSplitContainer.xml +++ b/doc/classes/VSplitContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VSplitContainer" inherits="SplitContainer" category="Core" version="3.0-stable"> +<class name="VSplitContainer" inherits="SplitContainer" category="Core" version="3.1"> <brief_description> Vertical split container. </brief_description> diff --git a/doc/classes/Variant.xml b/doc/classes/Variant.xml index f27f358015..b2d21921a1 100644 --- a/doc/classes/Variant.xml +++ b/doc/classes/Variant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Variant" category="Core" version="3.0-stable"> +<class name="Variant" category="Core" version="3.1"> <brief_description> The most important data type in Godot. </brief_description> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 6a87bbf66c..b293ec3368 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Vector2" category="Built-In Types" version="3.0-stable"> +<class name="Vector2" category="Built-In Types" version="3.1"> <brief_description> Vector used for 2D Math. </brief_description> @@ -81,6 +81,15 @@ Returns the vector with a maximum length. </description> </method> + <method name="cross"> + <return type="float"> + </return> + <argument index="0" name="b" type="Vector2"> + </argument> + <description> + Returns the 2-dimensional analog of the cross product with [code]b[/code]. + </description> + </method> <method name="cubic_interpolate"> <return type="Vector2"> </return> diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 0dc808329f..940d4dd6cf 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Vector3" category="Built-In Types" version="3.0-stable"> +<class name="Vector3" category="Built-In Types" version="3.1"> <brief_description> Vector class, which performs basic 3D vector math operations. </brief_description> diff --git a/doc/classes/VehicleBody.xml b/doc/classes/VehicleBody.xml index fe58806344..3ce0cadde9 100644 --- a/doc/classes/VehicleBody.xml +++ b/doc/classes/VehicleBody.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VehicleBody" inherits="RigidBody" category="Core" version="3.0-stable"> +<class name="VehicleBody" inherits="RigidBody" category="Core" version="3.1"> <brief_description> + Physics body that simulates the behaviour of a car. </brief_description> <description> + This nodes implements all the physics logic needed to simulate a car. It is based on the raycast vehicle system commonly found in physics engines. You will need to add a [CollisionShape] for the main body of your vehicle and add [VehicleWheel] nodes for the wheels. You should also add a [MeshInstance] to this node for the 3D model of your car but this model should not include meshes for the wheels. You should control the vehicle by using the [member brake], [member engine_force], and [member steering] properties and not change the position or orientation of this node directly. + Note that the origin point of your VehicleBody will determine the center of gravity of your vehicle so it is better to keep this low and move the [CollisionShape] and [MeshInstance] upwards. </description> <tutorials> </tutorials> @@ -12,10 +15,14 @@ </methods> <members> <member name="brake" type="float" setter="set_brake" getter="get_brake"> + Slows down the vehicle by applying a braking force. The vehicle is only slowed down if the wheels are in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidBody.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. </member> <member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force"> + Accelerates the vehicle by applying an engine force. The vehicle is only speed up if the wheels that have [member VehicleWheel.set_use_as_traction] set to true and are in contact with a surface. The [member RigidBody.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. Note that the simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. + A negative value will result in the vehicle reversing. </member> <member name="steering" type="float" setter="set_steering" getter="get_steering"> + The steering angle for the vehicle. Setting this to a non-zero value will result in the vehicle turning when it's moving. Wheels that have [member VehicleWheel.set_use_as_steering] set to true will automatically be rotated. </member> </members> <constants> diff --git a/doc/classes/VehicleWheel.xml b/doc/classes/VehicleWheel.xml index e36a1abe9d..6f9f5ea2c5 100644 --- a/doc/classes/VehicleWheel.xml +++ b/doc/classes/VehicleWheel.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VehicleWheel" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="VehicleWheel" inherits="Spatial" category="Core" version="3.1"> <brief_description> + Physics object that simulates the behaviour of a wheel. </brief_description> <description> + This node needs to be used as a child node of [VehicleBody] and simulates the behaviour of one of its wheels. This node also acts as a collider to detect if the wheel is touching a surface. </description> <tutorials> </tutorials> @@ -13,37 +15,51 @@ <return type="float"> </return> <description> + Returns a value between 0.0 and 1.0 that indicates whether this wheel is skidding. 0.0 is not skidding, 1.0 means the wheel has lost grip. </description> </method> <method name="is_in_contact" qualifiers="const"> <return type="bool"> </return> <description> + Returns true if this wheel is in contact with a surface. </description> </method> </methods> <members> <member name="damping_compression" type="float" setter="set_damping_compression" getter="get_damping_compression"> + The damping applied to the spring when the spring is being compressed. This value should be between 0.0 (no damping) and 1.0. A value of 0.0 means the car will keep bouncing as the spring keeps its energy. A good value for this is around 0.3 for a normal car, 0.5 for a race car. </member> <member name="damping_relaxation" type="float" setter="set_damping_relaxation" getter="get_damping_relaxation"> + The damping applied to the spring when relaxing. This value should be between 0.0 (no damping) and 1.0. This value should always be slighly higher then the [member damping_compression] property. For a [member damping_compression] value of 0.3, try a relaxation value of 0.5 </member> <member name="suspension_max_force" type="float" setter="set_suspension_max_force" getter="get_suspension_max_force"> + The maximum force the spring can resist. This value should be higher then a quarter of the [member RigidBody.mass] of the [VehicleBody] or the spring will not carry the weight of the vehicle. Good results are often obtained by a value that is about 3x to 4x this number. </member> <member name="suspension_stiffness" type="float" setter="set_suspension_stiffness" getter="get_suspension_stiffness"> + This value defines the stiffness of the suspension. Use a value lower then 50 for an offroad car, a value between 50 and 100 for a race car and try something around 200 for something like a Formula 1 car. </member> <member name="suspension_travel" type="float" setter="set_suspension_travel" getter="get_suspension_travel"> + This is the distance the suspension can travel. As Godots measures are in meters keep this setting relatively low. Try a value between 0.1 and 0.3 depending on the type of car . </member> <member name="use_as_steering" type="bool" setter="set_use_as_steering" getter="is_used_as_steering"> + If true this wheel will be turned when the car steers. </member> <member name="use_as_traction" type="bool" setter="set_use_as_traction" getter="is_used_as_traction"> + If true this wheel transfers engine force to the ground to propel the vehicle forward. </member> <member name="wheel_friction_slip" type="float" setter="set_friction_slip" getter="get_friction_slip"> + This determines how much grip this wheel has. It is combined with the friction setting of the surface the wheel is in contact with. 0.0 means no grip, 1.0 is normal grip. For a drift car setup, try setting the grip of the rear wheels slightly lower then the front wheels, or use a lower value to simulate tire wear. + It's best to set this to 1.0 when starting out. </member> <member name="wheel_radius" type="float" setter="set_radius" getter="get_radius"> + The radius of the wheel in meters. </member> <member name="wheel_rest_length" type="float" setter="set_suspension_rest_length" getter="get_suspension_rest_length"> + This is the distance in meters the wheel is lowered from its origin point. Don't set this to 0.0 and move the wheel into position, instead move the origin point of your wheel (the gizmo in Godot) to the position the wheel will take when bottoming out, then use the rest lenght to move the wheel down to the position it should be in when the car is in rest. </member> <member name="wheel_roll_influence" type="float" setter="set_roll_influence" getter="get_roll_influence"> + This value effects the roll of your vehicle. If set to 0.0 for all wheels your vehicle will be prone to rolling over while a value of 1.0 will resist body roll. </member> </members> <constants> diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml index 55755ca5df..48d09ccd95 100644 --- a/doc/classes/VideoPlayer.xml +++ b/doc/classes/VideoPlayer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VideoPlayer" inherits="Control" category="Core" version="3.0-stable"> +<class name="VideoPlayer" inherits="Control" category="Core" version="3.1"> <brief_description> Control to play video files. </brief_description> diff --git a/doc/classes/VideoStream.xml b/doc/classes/VideoStream.xml index a4e4ee3452..6bfa48511b 100644 --- a/doc/classes/VideoStream.xml +++ b/doc/classes/VideoStream.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VideoStream" inherits="Resource" category="Core" version="3.0-stable"> +<class name="VideoStream" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 0698a61529..a485205736 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Viewport" inherits="Node" category="Core" version="3.0-stable"> +<class name="Viewport" inherits="Node" category="Core" version="3.1"> <brief_description> Creates a sub-view into the screen. </brief_description> @@ -123,7 +123,7 @@ <return type="bool"> </return> <description> - Get the enabled status of the size strech override set with [method set_size_override_stretch]. + Get the enabled status of the size stretch override set with [method set_size_override_stretch]. </description> </method> <method name="set_attach_to_screen_rect"> @@ -302,7 +302,7 @@ Amount of objects in frame. </constant> <constant name="RENDER_INFO_VERTICES_IN_FRAME" value="1" enum="RenderInfo"> - Amount of vertices in frame. + Amount of vertices in frame. </constant> <constant name="RENDER_INFO_MATERIAL_CHANGES_IN_FRAME" value="2" enum="RenderInfo"> Amount of material changes in frame. diff --git a/doc/classes/ViewportContainer.xml b/doc/classes/ViewportContainer.xml index a2cd9a0217..8c60fb473d 100644 --- a/doc/classes/ViewportContainer.xml +++ b/doc/classes/ViewportContainer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ViewportContainer" inherits="Container" category="Core" version="3.0-stable"> +<class name="ViewportContainer" inherits="Container" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/ViewportTexture.xml b/doc/classes/ViewportTexture.xml index 5943759c55..83ffc6bcfd 100644 --- a/doc/classes/ViewportTexture.xml +++ b/doc/classes/ViewportTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ViewportTexture" inherits="Texture" category="Core" version="3.0-stable"> +<class name="ViewportTexture" inherits="Texture" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/VisibilityEnabler.xml b/doc/classes/VisibilityEnabler.xml index faf0451bae..83ba9495e5 100644 --- a/doc/classes/VisibilityEnabler.xml +++ b/doc/classes/VisibilityEnabler.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisibilityEnabler" inherits="VisibilityNotifier" category="Core" version="3.0-stable"> +<class name="VisibilityEnabler" inherits="VisibilityNotifier" category="Core" version="3.1"> <brief_description> Enable certain nodes only when visible. </brief_description> diff --git a/doc/classes/VisibilityEnabler2D.xml b/doc/classes/VisibilityEnabler2D.xml index acd9d86c2a..8dfbaec6e8 100644 --- a/doc/classes/VisibilityEnabler2D.xml +++ b/doc/classes/VisibilityEnabler2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisibilityEnabler2D" inherits="VisibilityNotifier2D" category="Core" version="3.0-stable"> +<class name="VisibilityEnabler2D" inherits="VisibilityNotifier2D" category="Core" version="3.1"> <brief_description> Enable certain nodes only when visible. </brief_description> diff --git a/doc/classes/VisibilityNotifier.xml b/doc/classes/VisibilityNotifier.xml index 94b08b78ed..2f22dc99bf 100644 --- a/doc/classes/VisibilityNotifier.xml +++ b/doc/classes/VisibilityNotifier.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisibilityNotifier" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="VisibilityNotifier" inherits="Spatial" category="Core" version="3.1"> <brief_description> Detects when the node is visible on screen. </brief_description> diff --git a/doc/classes/VisibilityNotifier2D.xml b/doc/classes/VisibilityNotifier2D.xml index bcd52cf9ca..b98f2794d2 100644 --- a/doc/classes/VisibilityNotifier2D.xml +++ b/doc/classes/VisibilityNotifier2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisibilityNotifier2D" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="VisibilityNotifier2D" inherits="Node2D" category="Core" version="3.1"> <brief_description> Detects when the node is visible on screen. </brief_description> diff --git a/doc/classes/VisualInstance.xml b/doc/classes/VisualInstance.xml index 1c54cb53ac..502209fac5 100644 --- a/doc/classes/VisualInstance.xml +++ b/doc/classes/VisualInstance.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualInstance" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="VisualInstance" inherits="Spatial" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index a546b86c57..bd1a9fb3e5 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualServer" inherits="Object" category="Core" version="3.0-stable"> +<class name="VisualServer" inherits="Object" category="Core" version="3.1"> <brief_description> Server for anything visible. </brief_description> @@ -42,6 +42,80 @@ Sets margin size, where black bars (or images, if [method black_bars_set_images] was used) are rendered. </description> </method> + <method name="camera_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="camera_set_cull_mask"> + <return type="void"> + </return> + <argument index="0" name="camera" type="RID"> + </argument> + <argument index="1" name="layers" type="int"> + </argument> + <description> + </description> + </method> + <method name="camera_set_environment"> + <return type="void"> + </return> + <argument index="0" name="camera" type="RID"> + </argument> + <argument index="1" name="env" type="RID"> + </argument> + <description> + </description> + </method> + <method name="camera_set_orthogonal"> + <return type="void"> + </return> + <argument index="0" name="camera" type="RID"> + </argument> + <argument index="1" name="size" type="float"> + </argument> + <argument index="2" name="z_near" type="float"> + </argument> + <argument index="3" name="z_far" type="float"> + </argument> + <description> + </description> + </method> + <method name="camera_set_perspective"> + <return type="void"> + </return> + <argument index="0" name="camera" type="RID"> + </argument> + <argument index="1" name="fovy_degrees" type="float"> + </argument> + <argument index="2" name="z_near" type="float"> + </argument> + <argument index="3" name="z_far" type="float"> + </argument> + <description> + </description> + </method> + <method name="camera_set_transform"> + <return type="void"> + </return> + <argument index="0" name="camera" type="RID"> + </argument> + <argument index="1" name="transform" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="camera_set_use_vertical_aspect"> + <return type="void"> + </return> + <argument index="0" name="camera" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> <method name="canvas_create"> <return type="RID"> </return> @@ -101,7 +175,9 @@ </argument> <argument index="1" name="mesh" type="RID"> </argument> - <argument index="2" name="skeleton" type="RID"> + <argument index="2" name="texture" type="RID"> + </argument> + <argument index="3" name="normal_map" type="RID"> </argument> <description> Adds a [Mesh] to the [CanvasItem]'s draw commands. Only affects its aabb at the moment. @@ -114,7 +190,9 @@ </argument> <argument index="1" name="mesh" type="RID"> </argument> - <argument index="2" name="skeleton" type="RID"> + <argument index="2" name="texture" type="RID"> + </argument> + <argument index="3" name="normal_map" type="RID"> </argument> <description> Adds a [MultiMesh] to the [CanvasItem]'s draw commands. Only affects its aabb at the moment. @@ -881,6 +959,12 @@ Modulates all colors in the given canvas. </description> </method> + <method name="directional_light_create"> + <return type="RID"> + </return> + <description> + </description> + </method> <method name="draw"> <return type="void"> </return> @@ -890,6 +974,290 @@ Draws a frame. </description> </method> + <method name="environment_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="environment_set_adjustment"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="brightness" type="float"> + </argument> + <argument index="3" name="contrast" type="float"> + </argument> + <argument index="4" name="saturation" type="float"> + </argument> + <argument index="5" name="ramp" type="RID"> + </argument> + <description> + </description> + </method> + <method name="environment_set_ambient_light"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="color" type="Color"> + </argument> + <argument index="2" name="energy" type="float" default="1.0"> + </argument> + <argument index="3" name="sky_contibution" type="float" default="0.0"> + </argument> + <description> + </description> + </method> + <method name="environment_set_background"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="bg" type="int" enum="VisualServer.EnvironmentBG"> + </argument> + <description> + </description> + </method> + <method name="environment_set_bg_color"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="environment_set_bg_energy"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="energy" type="float"> + </argument> + <description> + </description> + </method> + <method name="environment_set_canvas_max_layer"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="max_layer" type="int"> + </argument> + <description> + </description> + </method> + <method name="environment_set_dof_blur_far"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="distance" type="float"> + </argument> + <argument index="3" name="transition" type="float"> + </argument> + <argument index="4" name="far_amount" type="float"> + </argument> + <argument index="5" name="quality" type="int" enum="VisualServer.EnvironmentDOFBlurQuality"> + </argument> + <description> + </description> + </method> + <method name="environment_set_dof_blur_near"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="distance" type="float"> + </argument> + <argument index="3" name="transition" type="float"> + </argument> + <argument index="4" name="far_amount" type="float"> + </argument> + <argument index="5" name="quality" type="int" enum="VisualServer.EnvironmentDOFBlurQuality"> + </argument> + <description> + </description> + </method> + <method name="environment_set_fog"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="color" type="Color"> + </argument> + <argument index="3" name="sun_color" type="Color"> + </argument> + <argument index="4" name="sun_amount" type="float"> + </argument> + <description> + </description> + </method> + <method name="environment_set_fog_depth"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="depth_begin" type="float"> + </argument> + <argument index="3" name="depth_curve" type="float"> + </argument> + <argument index="4" name="transmit" type="bool"> + </argument> + <argument index="5" name="transmit_curve" type="float"> + </argument> + <description> + </description> + </method> + <method name="environment_set_fog_height"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="min_height" type="float"> + </argument> + <argument index="3" name="max_height" type="float"> + </argument> + <argument index="4" name="height_curve" type="float"> + </argument> + <description> + </description> + </method> + <method name="environment_set_glow"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="level_flags" type="int"> + </argument> + <argument index="3" name="intensity" type="float"> + </argument> + <argument index="4" name="strength" type="float"> + </argument> + <argument index="5" name="bloom_threshold" type="float"> + </argument> + <argument index="6" name="blend_mode" type="int" enum="VisualServer.EnvironmentGlowBlendMode"> + </argument> + <argument index="7" name="hdr_bleed_threshold" type="float"> + </argument> + <argument index="8" name="hdr_bleed_scale" type="float"> + </argument> + <argument index="9" name="bicubic_upscale" type="bool"> + </argument> + <description> + </description> + </method> + <method name="environment_set_sky"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="sky" type="RID"> + </argument> + <description> + </description> + </method> + <method name="environment_set_sky_custom_fov"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="scale" type="float"> + </argument> + <description> + </description> + </method> + <method name="environment_set_ssao"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="radius" type="float"> + </argument> + <argument index="3" name="intensity" type="float"> + </argument> + <argument index="4" name="radius2" type="float"> + </argument> + <argument index="5" name="intensity2" type="float"> + </argument> + <argument index="6" name="bias" type="float"> + </argument> + <argument index="7" name="light_affect" type="float"> + </argument> + <argument index="8" name="color" type="Color"> + </argument> + <argument index="9" name="quality" type="int" enum="VisualServer.EnvironmentSSAOQuality"> + </argument> + <argument index="10" name="blur" type="int" enum="VisualServer.EnvironmentSSAOBlur"> + </argument> + <argument index="11" name="bilateral_sharpness" type="float"> + </argument> + <description> + </description> + </method> + <method name="environment_set_ssr"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <argument index="2" name="max_steps" type="int"> + </argument> + <argument index="3" name="fade_in" type="float"> + </argument> + <argument index="4" name="fade_out" type="float"> + </argument> + <argument index="5" name="depth_tolerance" type="float"> + </argument> + <argument index="6" name="roughness" type="bool"> + </argument> + <description> + </description> + </method> + <method name="environment_set_tonemap"> + <return type="void"> + </return> + <argument index="0" name="env" type="RID"> + </argument> + <argument index="1" name="tone_mapper" type="int" enum="VisualServer.EnvironmentToneMapper"> + </argument> + <argument index="2" name="exposure" type="float"> + </argument> + <argument index="3" name="white" type="float"> + </argument> + <argument index="4" name="auto_exposure" type="bool"> + </argument> + <argument index="5" name="min_luminance" type="float"> + </argument> + <argument index="6" name="max_luminance" type="float"> + </argument> + <argument index="7" name="auto_exp_speed" type="float"> + </argument> + <argument index="8" name="auto_exp_grey" type="float"> + </argument> + <description> + </description> + </method> <method name="finish"> <return type="void"> </return> @@ -910,7 +1278,7 @@ <return type="void"> </return> <description> - Syncronizes threads. + Synchronizes threads. </description> </method> <method name="free_rid"> @@ -952,6 +1320,210 @@ Returns the id of a white texture. Creates one if none exists. </description> </method> + <method name="gi_probe_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="gi_probe_get_bias" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_get_bounds" qualifiers="const"> + <return type="AABB"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_get_cell_size" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_get_dynamic_data" qualifiers="const"> + <return type="PoolIntArray"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_get_dynamic_range" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_get_energy" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_get_normal_bias" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_get_propagation" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_get_to_cell_xform" qualifiers="const"> + <return type="Transform"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_is_compressed" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_is_interior" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="arg0" type="RID"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_bias"> + <return type="void"> + </return> + <argument index="0" name="bias" type="RID"> + </argument> + <argument index="1" name="arg1" type="float"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_bounds"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="bounds" type="AABB"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_cell_size"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="range" type="float"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_compress"> + <return type="void"> + </return> + <argument index="0" name="enable" type="RID"> + </argument> + <argument index="1" name="arg1" type="bool"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_dynamic_data"> + <return type="void"> + </return> + <argument index="0" name="data" type="RID"> + </argument> + <argument index="1" name="arg1" type="PoolIntArray"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_dynamic_range"> + <return type="void"> + </return> + <argument index="0" name="range" type="RID"> + </argument> + <argument index="1" name="arg1" type="int"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_energy"> + <return type="void"> + </return> + <argument index="0" name="energy" type="RID"> + </argument> + <argument index="1" name="arg1" type="float"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_interior"> + <return type="void"> + </return> + <argument index="0" name="enable" type="RID"> + </argument> + <argument index="1" name="arg1" type="bool"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_normal_bias"> + <return type="void"> + </return> + <argument index="0" name="bias" type="RID"> + </argument> + <argument index="1" name="arg1" type="float"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_propagation"> + <return type="void"> + </return> + <argument index="0" name="propagation" type="RID"> + </argument> + <argument index="1" name="arg1" type="float"> + </argument> + <description> + </description> + </method> + <method name="gi_probe_set_to_cell_xform"> + <return type="void"> + </return> + <argument index="0" name="xform" type="RID"> + </argument> + <argument index="1" name="arg1" type="Transform"> + </argument> + <description> + </description> + </method> <method name="has_changed" qualifiers="const"> <return type="bool"> </return> @@ -976,6 +1548,128 @@ Returns true, if the OS supports a certain feature. Features might be s3tc, etc, etc2 and pvrtc, </description> </method> + <method name="immediate_begin"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="primitive" type="int" enum="VisualServer.PrimitiveType"> + </argument> + <argument index="2" name="texture" type="RID"> + </argument> + <description> + </description> + </method> + <method name="immediate_clear"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <description> + </description> + </method> + <method name="immediate_color"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="immediate_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="immediate_end"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <description> + </description> + </method> + <method name="immediate_get_material" qualifiers="const"> + <return type="RID"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <description> + </description> + </method> + <method name="immediate_normal"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="normal" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="immediate_set_material"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="material" type="RID"> + </argument> + <description> + </description> + </method> + <method name="immediate_tangent"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="tangent" type="Plane"> + </argument> + <description> + </description> + </method> + <method name="immediate_uv"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="tex_uv" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="immediate_uv2"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="tex_uv" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="immediate_vertex"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="vertex" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="immediate_vertex_2d"> + <return type="void"> + </return> + <argument index="0" name="immediate" type="RID"> + </argument> + <argument index="1" name="vertex" type="Vector2"> + </argument> + <description> + </description> + </method> <method name="init"> <return type="void"> </return> @@ -983,6 +1677,476 @@ Initializes the visual server. </description> </method> + <method name="instance_attach_object_instance_id"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="instance_attach_skeleton"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="skeleton" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instance_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="instance_create2"> + <return type="RID"> + </return> + <argument index="0" name="base" type="RID"> + </argument> + <argument index="1" name="scenario" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instance_geometry_set_as_instance_lod"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="as_lod_of_instance" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instance_geometry_set_cast_shadows_setting"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="shadow_casting_setting" type="int" enum="VisualServer.ShadowCastingSetting"> + </argument> + <description> + </description> + </method> + <method name="instance_geometry_set_draw_range"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="min" type="float"> + </argument> + <argument index="2" name="max" type="float"> + </argument> + <argument index="3" name="min_margin" type="float"> + </argument> + <argument index="4" name="max_margin" type="float"> + </argument> + <description> + </description> + </method> + <method name="instance_geometry_set_flag"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="flag" type="int" enum="VisualServer.InstanceFlags"> + </argument> + <argument index="2" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="instance_geometry_set_material_override"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="material" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instance_set_base"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="base" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instance_set_blend_shape_weight"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="shape" type="int"> + </argument> + <argument index="2" name="weight" type="float"> + </argument> + <description> + </description> + </method> + <method name="instance_set_custom_aabb"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="aabb" type="AABB"> + </argument> + <description> + </description> + </method> + <method name="instance_set_exterior"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="instance_set_extra_visibility_margin"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="margin" type="float"> + </argument> + <description> + </description> + </method> + <method name="instance_set_layer_mask"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="instance_set_scenario"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="scenario" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instance_set_surface_material"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="surface" type="int"> + </argument> + <argument index="2" name="material" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instance_set_transform"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="transform" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="instance_set_use_lightmap"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="lightmap_instance" type="RID"> + </argument> + <argument index="2" name="lightmap" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instance_set_visible"> + <return type="void"> + </return> + <argument index="0" name="instance" type="RID"> + </argument> + <argument index="1" name="visible" type="bool"> + </argument> + <description> + </description> + </method> + <method name="instances_cull_aabb" qualifiers="const"> + <return type="Array"> + </return> + <argument index="0" name="aabb" type="AABB"> + </argument> + <argument index="1" name="scenario" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instances_cull_convex" qualifiers="const"> + <return type="Array"> + </return> + <argument index="0" name="convex" type="Array"> + </argument> + <argument index="1" name="scenario" type="RID"> + </argument> + <description> + </description> + </method> + <method name="instances_cull_ray" qualifiers="const"> + <return type="Array"> + </return> + <argument index="0" name="from" type="Vector3"> + </argument> + <argument index="1" name="to" type="Vector3"> + </argument> + <argument index="2" name="scenario" type="RID"> + </argument> + <description> + </description> + </method> + <method name="light_directional_set_blend_splits"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="light_directional_set_shadow_depth_range_mode"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="range_mode" type="int" enum="VisualServer.LightDirectionalShadowDepthRangeMode"> + </argument> + <description> + </description> + </method> + <method name="light_directional_set_shadow_mode"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="mode" type="int" enum="VisualServer.LightDirectionalShadowMode"> + </argument> + <description> + </description> + </method> + <method name="light_omni_set_shadow_detail"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="detail" type="int" enum="VisualServer.LightOmniShadowDetail"> + </argument> + <description> + </description> + </method> + <method name="light_omni_set_shadow_mode"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="mode" type="int" enum="VisualServer.LightOmniShadowMode"> + </argument> + <description> + </description> + </method> + <method name="light_set_color"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="light_set_cull_mask"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="light_set_negative"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="light_set_param"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="param" type="int" enum="VisualServer.LightParam"> + </argument> + <argument index="2" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="light_set_projector"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="texture" type="RID"> + </argument> + <description> + </description> + </method> + <method name="light_set_reverse_cull_face_mode"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="light_set_shadow"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="light_set_shadow_color"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="lightmap_capture_get_bounds" qualifiers="const"> + <return type="AABB"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_get_energy" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_get_octree" qualifiers="const"> + <return type="PoolByteArray"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_get_octree_cell_subdiv" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_get_octree_cell_transform" qualifiers="const"> + <return type="Transform"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_set_bounds"> + <return type="void"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <argument index="1" name="bounds" type="AABB"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_set_energy"> + <return type="void"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <argument index="1" name="energy" type="float"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_set_octree"> + <return type="void"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <argument index="1" name="octree" type="PoolByteArray"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_set_octree_cell_subdiv"> + <return type="void"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <argument index="1" name="subdiv" type="int"> + </argument> + <description> + </description> + </method> + <method name="lightmap_capture_set_octree_cell_transform"> + <return type="void"> + </return> + <argument index="0" name="capture" type="RID"> + </argument> + <argument index="1" name="xform" type="Transform"> + </argument> + <description> + </description> + </method> <method name="make_sphere_mesh"> <return type="RID"> </return> @@ -1327,6 +2491,472 @@ Sets a mesh's surface's material. </description> </method> + <method name="multimesh_allocate"> + <return type="void"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="instances" type="int"> + </argument> + <argument index="2" name="transform_format" type="int" enum="VisualServer.MultimeshTransformFormat"> + </argument> + <argument index="3" name="color_format" type="int" enum="VisualServer.MultimeshColorFormat"> + </argument> + <description> + </description> + </method> + <method name="multimesh_get_aabb" qualifiers="const"> + <return type="AABB"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <description> + </description> + </method> + <method name="multimesh_get_instance_count" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <description> + </description> + </method> + <method name="multimesh_get_mesh" qualifiers="const"> + <return type="RID"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <description> + </description> + </method> + <method name="multimesh_get_visible_instances" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <description> + </description> + </method> + <method name="multimesh_instance_get_color" qualifiers="const"> + <return type="Color"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="multimesh_instance_get_transform" qualifiers="const"> + <return type="Transform"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="multimesh_instance_get_transform_2d" qualifiers="const"> + <return type="Transform2D"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="index" type="int"> + </argument> + <description> + </description> + </method> + <method name="multimesh_instance_set_color"> + <return type="void"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="index" type="int"> + </argument> + <argument index="2" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="multimesh_instance_set_transform"> + <return type="void"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="index" type="int"> + </argument> + <argument index="2" name="transform" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="multimesh_instance_set_transform_2d"> + <return type="void"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="index" type="int"> + </argument> + <argument index="2" name="transform" type="Transform2D"> + </argument> + <description> + </description> + </method> + <method name="multimesh_set_mesh"> + <return type="void"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="mesh" type="RID"> + </argument> + <description> + </description> + </method> + <method name="multimesh_set_visible_instances"> + <return type="void"> + </return> + <argument index="0" name="multimesh" type="RID"> + </argument> + <argument index="1" name="visible" type="int"> + </argument> + <description> + </description> + </method> + <method name="omni_light_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="particles_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="particles_get_current_aabb"> + <return type="AABB"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <description> + </description> + </method> + <method name="particles_get_emitting"> + <return type="bool"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <description> + </description> + </method> + <method name="particles_restart"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <description> + </description> + </method> + <method name="particles_set_amount"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="amount" type="int"> + </argument> + <description> + </description> + </method> + <method name="particles_set_custom_aabb"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="aabb" type="AABB"> + </argument> + <description> + </description> + </method> + <method name="particles_set_draw_order"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="order" type="int" enum="VisualServer.ParticlesDrawOrder"> + </argument> + <description> + </description> + </method> + <method name="particles_set_draw_pass_mesh"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="pass" type="int"> + </argument> + <argument index="2" name="mesh" type="RID"> + </argument> + <description> + </description> + </method> + <method name="particles_set_draw_passes"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="count" type="int"> + </argument> + <description> + </description> + </method> + <method name="particles_set_emission_transform"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="transform" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="particles_set_emitting"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="emitting" type="bool"> + </argument> + <description> + </description> + </method> + <method name="particles_set_explosiveness_ratio"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="ratio" type="float"> + </argument> + <description> + </description> + </method> + <method name="particles_set_fixed_fps"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="fps" type="int"> + </argument> + <description> + </description> + </method> + <method name="particles_set_fractional_delta"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="particles_set_lifetime"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="lifetime" type="float"> + </argument> + <description> + </description> + </method> + <method name="particles_set_one_shot"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="one_shot" type="bool"> + </argument> + <description> + </description> + </method> + <method name="particles_set_pre_process_time"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="time" type="float"> + </argument> + <description> + </description> + </method> + <method name="particles_set_process_material"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="material" type="RID"> + </argument> + <description> + </description> + </method> + <method name="particles_set_randomness_ratio"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="ratio" type="float"> + </argument> + <description> + </description> + </method> + <method name="particles_set_speed_scale"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="scale" type="float"> + </argument> + <description> + </description> + </method> + <method name="particles_set_use_local_coordinates"> + <return type="void"> + </return> + <argument index="0" name="particles" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="reflection_probe_set_as_interior"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_cull_mask"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="layers" type="int"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_enable_box_projection"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_enable_shadows"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_extents"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="extents" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_intensity"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="intensity" type="float"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_interior_ambient"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_interior_ambient_energy"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="energy" type="float"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_interior_ambient_probe_contribution"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="contrib" type="float"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_max_distance"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="distance" type="float"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_origin_offset"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="offset" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="reflection_probe_set_update_mode"> + <return type="void"> + </return> + <argument index="0" name="probe" type="RID"> + </argument> + <argument index="1" name="mode" type="int" enum="VisualServer.ReflectionProbeUpdateMode"> + </argument> + <description> + </description> + </method> <method name="request_frame_drawn_callback"> <return type="void"> </return> @@ -1341,6 +2971,54 @@ The callback method must use only 1 argument which will be called with 'userdata'. </description> </method> + <method name="scenario_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="scenario_set_debug"> + <return type="void"> + </return> + <argument index="0" name="scenario" type="RID"> + </argument> + <argument index="1" name="debug_mode" type="int" enum="VisualServer.ScenarioDebugMode"> + </argument> + <description> + </description> + </method> + <method name="scenario_set_environment"> + <return type="void"> + </return> + <argument index="0" name="scenario" type="RID"> + </argument> + <argument index="1" name="environment" type="RID"> + </argument> + <description> + </description> + </method> + <method name="scenario_set_fallback_environment"> + <return type="void"> + </return> + <argument index="0" name="scenario" type="RID"> + </argument> + <argument index="1" name="environment" type="RID"> + </argument> + <description> + </description> + </method> + <method name="scenario_set_reflection_atlas_size"> + <return type="void"> + </return> + <argument index="0" name="scenario" type="RID"> + </argument> + <argument index="1" name="p_size" type="int"> + </argument> + <argument index="2" name="subdiv" type="int"> + </argument> + <description> + </description> + </method> <method name="set_boot_image"> <return type="void"> </return> @@ -1430,6 +3108,76 @@ Sets a shader's default texture. Overwrites the texture given by name. </description> </method> + <method name="skeleton_allocate"> + <return type="void"> + </return> + <argument index="0" name="skeleton" type="RID"> + </argument> + <argument index="1" name="bones" type="int"> + </argument> + <argument index="2" name="is_2d_skeleton" type="bool" default="false"> + </argument> + <description> + </description> + </method> + <method name="skeleton_bone_get_transform" qualifiers="const"> + <return type="Transform"> + </return> + <argument index="0" name="skeleton" type="RID"> + </argument> + <argument index="1" name="bone" type="int"> + </argument> + <description> + </description> + </method> + <method name="skeleton_bone_get_transform_2d" qualifiers="const"> + <return type="Transform2D"> + </return> + <argument index="0" name="skeleton" type="RID"> + </argument> + <argument index="1" name="bone" type="int"> + </argument> + <description> + </description> + </method> + <method name="skeleton_bone_set_transform"> + <return type="void"> + </return> + <argument index="0" name="skeleton" type="RID"> + </argument> + <argument index="1" name="bone" type="int"> + </argument> + <argument index="2" name="transform" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="skeleton_bone_set_transform_2d"> + <return type="void"> + </return> + <argument index="0" name="skeleton" type="RID"> + </argument> + <argument index="1" name="bone" type="int"> + </argument> + <argument index="2" name="transform" type="Transform2D"> + </argument> + <description> + </description> + </method> + <method name="skeleton_create"> + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="skeleton_get_bone_count" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="skeleton" type="RID"> + </argument> + <description> + </description> + </method> <method name="sky_create"> <return type="RID"> </return> @@ -1450,6 +3198,12 @@ Sets a sky's texture. </description> </method> + <method name="spot_light_create"> + <return type="RID"> + </return> + <description> + </description> + </method> <method name="sync"> <return type="void"> </return> @@ -2214,6 +3968,24 @@ <constant name="LIGHT_PARAM_MAX" value="15" enum="LightParam"> The light parameters endpoint. Used internally. </constant> + <constant name="LIGHT_OMNI_SHADOW_DUAL_PARABOLOID" value="0" enum="LightOmniShadowMode"> + </constant> + <constant name="LIGHT_OMNI_SHADOW_CUBE" value="1" enum="LightOmniShadowMode"> + </constant> + <constant name="LIGHT_OMNI_SHADOW_DETAIL_VERTICAL" value="0" enum="LightOmniShadowDetail"> + </constant> + <constant name="LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL" value="1" enum="LightOmniShadowDetail"> + </constant> + <constant name="LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL" value="0" enum="LightDirectionalShadowMode"> + </constant> + <constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS" value="1" enum="LightDirectionalShadowMode"> + </constant> + <constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS" value="2" enum="LightDirectionalShadowMode"> + </constant> + <constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE" value="0" enum="LightDirectionalShadowDepthRangeMode"> + </constant> + <constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED" value="1" enum="LightDirectionalShadowDepthRangeMode"> + </constant> <constant name="VIEWPORT_UPDATE_DISABLED" value="0" enum="ViewportUpdateMode"> </constant> <constant name="VIEWPORT_UPDATE_ONCE" value="1" enum="ViewportUpdateMode"> @@ -2323,6 +4095,18 @@ <constant name="INSTANCE_GEOMETRY_MASK" value="30" enum="InstanceType"> A combination of the flags of geometry instances (mesh, multimesh, immediate and particles). </constant> + <constant name="INSTANCE_FLAG_USE_BAKED_LIGHT" value="0" enum="InstanceFlags"> + </constant> + <constant name="INSTANCE_FLAG_MAX" value="1" enum="InstanceFlags"> + </constant> + <constant name="SHADOW_CASTING_SETTING_OFF" value="0" enum="ShadowCastingSetting"> + </constant> + <constant name="SHADOW_CASTING_SETTING_ON" value="1" enum="ShadowCastingSetting"> + </constant> + <constant name="SHADOW_CASTING_SETTING_DOUBLE_SIDED" value="2" enum="ShadowCastingSetting"> + </constant> + <constant name="SHADOW_CASTING_SETTING_SHADOWS_ONLY" value="3" enum="ShadowCastingSetting"> + </constant> <constant name="NINE_PATCH_STRETCH" value="0" enum="NinePatchAxisMode"> The nine patch gets stretched where needed. </constant> @@ -2398,5 +4182,75 @@ </constant> <constant name="FEATURE_MULTITHREADED" value="1" enum="Features"> </constant> + <constant name="MULTIMESH_TRANSFORM_2D" value="0" enum="MultimeshTransformFormat"> + </constant> + <constant name="MULTIMESH_TRANSFORM_3D" value="1" enum="MultimeshTransformFormat"> + </constant> + <constant name="MULTIMESH_COLOR_NONE" value="0" enum="MultimeshColorFormat"> + </constant> + <constant name="MULTIMESH_COLOR_8BIT" value="1" enum="MultimeshColorFormat"> + </constant> + <constant name="MULTIMESH_COLOR_FLOAT" value="2" enum="MultimeshColorFormat"> + </constant> + <constant name="REFLECTION_PROBE_UPDATE_ONCE" value="0" enum="ReflectionProbeUpdateMode"> + </constant> + <constant name="REFLECTION_PROBE_UPDATE_ALWAYS" value="1" enum="ReflectionProbeUpdateMode"> + </constant> + <constant name="PARTICLES_DRAW_ORDER_INDEX" value="0" enum="ParticlesDrawOrder"> + </constant> + <constant name="PARTICLES_DRAW_ORDER_LIFETIME" value="1" enum="ParticlesDrawOrder"> + </constant> + <constant name="PARTICLES_DRAW_ORDER_VIEW_DEPTH" value="2" enum="ParticlesDrawOrder"> + </constant> + <constant name="ENV_BG_CLEAR_COLOR" value="0" enum="EnvironmentBG"> + </constant> + <constant name="ENV_BG_COLOR" value="1" enum="EnvironmentBG"> + </constant> + <constant name="ENV_BG_SKY" value="2" enum="EnvironmentBG"> + </constant> + <constant name="ENV_BG_COLOR_SKY" value="3" enum="EnvironmentBG"> + </constant> + <constant name="ENV_BG_CANVAS" value="4" enum="EnvironmentBG"> + </constant> + <constant name="ENV_BG_KEEP" value="5" enum="EnvironmentBG"> + </constant> + <constant name="ENV_BG_MAX" value="6" enum="EnvironmentBG"> + </constant> + <constant name="ENV_DOF_BLUR_QUALITY_LOW" value="0" enum="EnvironmentDOFBlurQuality"> + </constant> + <constant name="ENV_DOF_BLUR_QUALITY_MEDIUM" value="1" enum="EnvironmentDOFBlurQuality"> + </constant> + <constant name="ENV_DOF_BLUR_QUALITY_HIGH" value="2" enum="EnvironmentDOFBlurQuality"> + </constant> + <constant name="GLOW_BLEND_MODE_ADDITIVE" value="0" enum="EnvironmentGlowBlendMode"> + </constant> + <constant name="GLOW_BLEND_MODE_SCREEN" value="1" enum="EnvironmentGlowBlendMode"> + </constant> + <constant name="GLOW_BLEND_MODE_SOFTLIGHT" value="2" enum="EnvironmentGlowBlendMode"> + </constant> + <constant name="GLOW_BLEND_MODE_REPLACE" value="3" enum="EnvironmentGlowBlendMode"> + </constant> + <constant name="ENV_TONE_MAPPER_LINEAR" value="0" enum="EnvironmentToneMapper"> + </constant> + <constant name="ENV_TONE_MAPPER_REINHARDT" value="1" enum="EnvironmentToneMapper"> + </constant> + <constant name="ENV_TONE_MAPPER_FILMIC" value="2" enum="EnvironmentToneMapper"> + </constant> + <constant name="ENV_TONE_MAPPER_ACES" value="3" enum="EnvironmentToneMapper"> + </constant> + <constant name="ENV_SSAO_QUALITY_LOW" value="0" enum="EnvironmentSSAOQuality"> + </constant> + <constant name="ENV_SSAO_QUALITY_MEDIUM" value="1" enum="EnvironmentSSAOQuality"> + </constant> + <constant name="ENV_SSAO_QUALITY_HIGH" value="2" enum="EnvironmentSSAOQuality"> + </constant> + <constant name="ENV_SSAO_BLUR_DISABLED" value="0" enum="EnvironmentSSAOBlur"> + </constant> + <constant name="ENV_SSAO_BLUR_1x1" value="1" enum="EnvironmentSSAOBlur"> + </constant> + <constant name="ENV_SSAO_BLUR_2x2" value="2" enum="EnvironmentSSAOBlur"> + </constant> + <constant name="ENV_SSAO_BLUR_3x3" value="3" enum="EnvironmentSSAOBlur"> + </constant> </constants> </class> diff --git a/doc/classes/WeakRef.xml b/doc/classes/WeakRef.xml index 0c4801b66e..4a0f3588c2 100644 --- a/doc/classes/WeakRef.xml +++ b/doc/classes/WeakRef.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="WeakRef" inherits="Reference" category="Core" version="3.0-stable"> +<class name="WeakRef" inherits="Reference" category="Core" version="3.1"> <brief_description> Holds an [Object], but does not contribute to the reference count if the object is a reference. </brief_description> diff --git a/doc/classes/WebSocketClient.xml b/doc/classes/WebSocketClient.xml new file mode 100644 index 0000000000..79313c90c7 --- /dev/null +++ b/doc/classes/WebSocketClient.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketClient" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="connect_to_url"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="url" type="String"> + </argument> + <argument index="1" name="protocols" type="PoolStringArray" default="PoolStringArray( )"> + </argument> + <argument index="2" name="gd_mp_api" type="bool" default="false"> + </argument> + <description> + </description> + </method> + <method name="disconnect_from_host"> + <return type="void"> + </return> + <description> + </description> + </method> + </methods> + <signals> + <signal name="connection_closed"> + <description> + </description> + </signal> + <signal name="connection_error"> + <description> + </description> + </signal> + <signal name="connection_established"> + <argument index="0" name="protocol" type="String"> + </argument> + <description> + </description> + </signal> + <signal name="data_received"> + <description> + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/doc/classes/WebSocketMultiplayerPeer.xml b/doc/classes/WebSocketMultiplayerPeer.xml new file mode 100644 index 0000000000..a1014350f5 --- /dev/null +++ b/doc/classes/WebSocketMultiplayerPeer.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketMultiplayerPeer" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="get_peer" qualifiers="const"> + <return type="WebSocketPeer"> + </return> + <argument index="0" name="peer_id" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <signals> + <signal name="peer_packet"> + <argument index="0" name="peer_source" type="int"> + </argument> + <description> + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/doc/classes/WebSocketPeer.xml b/doc/classes/WebSocketPeer.xml new file mode 100644 index 0000000000..276249e65a --- /dev/null +++ b/doc/classes/WebSocketPeer.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketPeer" inherits="PacketPeer" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="close"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="get_write_mode" qualifiers="const"> + <return type="int" enum="WebSocketPeer.WriteMode"> + </return> + <description> + </description> + </method> + <method name="is_connected_to_host" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_write_mode"> + <return type="void"> + </return> + <argument index="0" name="mode" type="int" enum="WebSocketPeer.WriteMode"> + </argument> + <description> + </description> + </method> + <method name="was_string_packet" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> + </methods> + <constants> + <constant name="WRITE_MODE_TEXT" value="0" enum="WriteMode"> + </constant> + <constant name="WRITE_MODE_BINARY" value="1" enum="WriteMode"> + </constant> + </constants> +</class> diff --git a/doc/classes/WebSocketServer.xml b/doc/classes/WebSocketServer.xml new file mode 100644 index 0000000000..9a7108952f --- /dev/null +++ b/doc/classes/WebSocketServer.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="WebSocketServer" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="has_peer" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_listening" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="listen"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="port" type="int"> + </argument> + <argument index="1" name="protocols" type="PoolStringArray" default="PoolStringArray( )"> + </argument> + <argument index="2" name="gd_mp_api" type="bool" default="false"> + </argument> + <description> + </description> + </method> + <method name="stop"> + <return type="void"> + </return> + <description> + </description> + </method> + </methods> + <signals> + <signal name="client_connected"> + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="protocol" type="String"> + </argument> + <description> + </description> + </signal> + <signal name="client_disconnected"> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </signal> + <signal name="data_received"> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </signal> + </signals> + <constants> + </constants> +</class> diff --git a/doc/classes/WindowDialog.xml b/doc/classes/WindowDialog.xml index 891e489be5..39487f5020 100644 --- a/doc/classes/WindowDialog.xml +++ b/doc/classes/WindowDialog.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="WindowDialog" inherits="Popup" category="Core" version="3.0-stable"> +<class name="WindowDialog" inherits="Popup" category="Core" version="3.1"> <brief_description> Base class for window dialogs. </brief_description> diff --git a/doc/classes/World.xml b/doc/classes/World.xml index cad286a1ac..9fc0e139b5 100644 --- a/doc/classes/World.xml +++ b/doc/classes/World.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="World" inherits="Resource" category="Core" version="3.0-stable"> +<class name="World" inherits="Resource" category="Core" version="3.1"> <brief_description> Class that has everything pertaining to a world. </brief_description> diff --git a/doc/classes/World2D.xml b/doc/classes/World2D.xml index 1a2745e6cb..5f6a5b8ad4 100644 --- a/doc/classes/World2D.xml +++ b/doc/classes/World2D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="World2D" inherits="Resource" category="Core" version="3.0-stable"> +<class name="World2D" inherits="Resource" category="Core" version="3.1"> <brief_description> Class that has everything pertaining to a 2D world. </brief_description> diff --git a/doc/classes/WorldEnvironment.xml b/doc/classes/WorldEnvironment.xml index 468e618e72..422ca3a558 100644 --- a/doc/classes/WorldEnvironment.xml +++ b/doc/classes/WorldEnvironment.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="WorldEnvironment" inherits="Node" category="Core" version="3.0-stable"> +<class name="WorldEnvironment" inherits="Node" category="Core" version="3.1"> <brief_description> Default environment properties for the entire scene (post-processing effects, lightning and background settings). </brief_description> diff --git a/doc/classes/XMLParser.xml b/doc/classes/XMLParser.xml index a404074401..fb03ab1692 100644 --- a/doc/classes/XMLParser.xml +++ b/doc/classes/XMLParser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="XMLParser" inherits="Reference" category="Core" version="3.0-stable"> +<class name="XMLParser" inherits="Reference" category="Core" version="3.1"> <brief_description> Low-level class for creating parsers for XML files. </brief_description> diff --git a/doc/classes/YSort.xml b/doc/classes/YSort.xml index e4818df62b..12b9cb623f 100644 --- a/doc/classes/YSort.xml +++ b/doc/classes/YSort.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="YSort" inherits="Node2D" category="Core" version="3.0-stable"> +<class name="YSort" inherits="Node2D" category="Core" version="3.1"> <brief_description> Sort all child nodes based on their Y positions. </brief_description> diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml index cce5dd3b45..0fec8eb530 100644 --- a/doc/classes/bool.xml +++ b/doc/classes/bool.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="bool" category="Built-In Types" version="3.0-stable"> +<class name="bool" category="Built-In Types" version="3.1"> <brief_description> Boolean built-in type </brief_description> diff --git a/doc/classes/float.xml b/doc/classes/float.xml index 812bd9b3a9..ef3c3d72eb 100644 --- a/doc/classes/float.xml +++ b/doc/classes/float.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="float" category="Built-In Types" version="3.0-stable"> +<class name="float" category="Built-In Types" version="3.1"> <brief_description> Float built-in type </brief_description> diff --git a/doc/classes/int.xml b/doc/classes/int.xml index 49b8b3949a..4855fa2848 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="int" category="Built-In Types" version="3.0-stable"> +<class name="int" category="Built-In Types" version="3.1"> <brief_description> Integer built-in type. </brief_description> diff --git a/doc/tools/makemd.py b/doc/tools/makemd.py index b2444eb47b..056f1ca82d 100644 --- a/doc/tools/makemd.py +++ b/doc/tools/makemd.py @@ -2,12 +2,19 @@ # -*- coding: utf-8 -*- import sys +import os.path as path +import os import xml.etree.ElementTree as ET input_list = [] for arg in sys.argv[1:]: - input_list.append(arg) + if not path.exists(arg): + exit("path {} doesn't exist".format(arg)) + elif path.isdir(arg): + input_list += filter(path.isfile, [path.join(arg, f) for f in os.listdir(arg)]) + else: # assuming is a file + input_list.append(arg) if len(input_list) < 1: print 'usage: makemd.py <classes.xml>' @@ -29,7 +36,6 @@ def make_class_list(class_list, columns): f = open('class_list.md', 'wb') prev = 0 col_max = len(class_list) / columns + 1 - print ('col max is ', col_max) col_count = 0 row_count = 0 last_initial = '' @@ -87,6 +93,8 @@ def make_class_list(class_list, columns): s += '\n' f.write(s) + f.close() + def dokuize_text(txt): @@ -324,6 +332,8 @@ def make_doku_class(node): f.write('\n') f.write(dokuize_text(d.text.strip())) f.write('\n') + + f.close() for file in input_list: @@ -335,12 +345,11 @@ for file in input_list: sys.exit(255) version = doc.attrib['version'] - - for c in list(doc): - if c.attrib['name'] in class_names: - continue - class_names.append(c.attrib['name']) - classes[c.attrib['name']] = c + class_name = doc.attrib['name'] + if class_name in class_names: + continue + class_names.append(class_name) + classes[class_name] = doc class_names.sort() diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index 9e767bf3d6..8074ce45ea 100644 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -104,6 +104,7 @@ def make_class_list(class_list, columns): f.write("--+-------+") f.write("\n") + f.close() def rstize_text(text, cclass): # Linebreak + tabs in the XML should become two line breaks unless in a "codeblock" @@ -572,6 +573,8 @@ def make_rst_class(node): f.write("\n\n") f.write('\n') + f.close() + file_list = [] diff --git a/drivers/SCsub b/drivers/SCsub index fc017f4891..2c5e9434e8 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -24,6 +24,7 @@ if env['xaudio2']: # Graphics drivers if (env["platform"] != "server"): SConscript('gles3/SCsub') + SConscript('gles2/SCsub') SConscript('gl_context/SCsub') else: SConscript('dummy/SCsub') diff --git a/drivers/convex_decomp/b2d_decompose.cpp b/drivers/convex_decomp/b2d_decompose.cpp index d1f7a4d3c3..14456144a6 100644 --- a/drivers/convex_decomp/b2d_decompose.cpp +++ b/drivers/convex_decomp/b2d_decompose.cpp @@ -94,7 +94,7 @@ static Vector<Vector<Vector2> > _b2d_decompose(const Vector<Vector2> &p_polygon) float32 dot = dx0 * dx1 + dy0 * dy1; if (fabs(cross) < b2_angularSlop && dot > 0) { //Angle too close, split the triangle across from this point. - //This is guaranteed to result in two triangles that satify + //This is guaranteed to result in two triangles that satisfy //the tolerance (one of the angles is 90 degrees) float32 dx2 = curr.x[lower] - curr.x[upper]; float32 dy2 = curr.y[lower] - curr.y[upper]; diff --git a/drivers/dummy/audio_driver_dummy.h b/drivers/dummy/audio_driver_dummy.h index c3d8e10767..b3f0fcee07 100644 --- a/drivers/dummy/audio_driver_dummy.h +++ b/drivers/dummy/audio_driver_dummy.h @@ -43,13 +43,13 @@ public: virtual Error init() { return OK; } virtual void start(){}; - virtual int get_mix_rate() const {}; - virtual SpeakerMode get_speaker_mode() const {}; + virtual int get_mix_rate() const { return DEFAULT_MIX_RATE; }; + virtual SpeakerMode get_speaker_mode() const { return SPEAKER_MODE_STEREO; }; virtual void lock(){}; virtual void unlock(){}; virtual void finish(){}; - virtual float get_latency(){}; + virtual float get_latency() { return 0; }; AudioDriverDummy(){}; ~AudioDriverDummy(){}; diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 4a7b8fd3a4..ea0d3ec706 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -269,7 +269,10 @@ public: PoolVector<uint8_t> p; return p; } - PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const {} + PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const { + PoolVector<uint8_t> p; + return p; + } uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const { return 0; } VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { return VS::PRIMITIVE_POINTS; } @@ -301,9 +304,9 @@ public: RID multimesh_get_mesh(RID p_multimesh) const { return RID(); } - Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const {} - Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {} - Color multimesh_instance_get_color(RID p_multimesh, int p_index) const {} + Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const { return Transform(); } + Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { return Transform2D(); } + Color multimesh_instance_get_color(RID p_multimesh, int p_index) const { return Color(); } void multimesh_set_visible_instances(RID p_multimesh, int p_visible) {} int multimesh_get_visible_instances(RID p_multimesh) const { return 0; } @@ -370,7 +373,7 @@ public: VS::LightType light_get_type(RID p_light) const { return VS::LIGHT_OMNI; } AABB light_get_aabb(RID p_light) const { return AABB(); } float light_get_param(RID p_light, VS::LightParam p_param) { return 0.0; } - Color light_get_color(RID p_light) {} + Color light_get_color(RID p_light) { return Color(); } uint64_t light_get_version(RID p_light) const { return 0; } /* PROBE API */ @@ -391,7 +394,7 @@ public: void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {} AABB reflection_probe_get_aabb(RID p_probe) const { return AABB(); } - VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const {} + VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const { return VisualServer::REFLECTION_PROBE_UPDATE_ONCE; } uint32_t reflection_probe_get_cull_mask(RID p_probe) const { return 0; } Vector3 reflection_probe_get_extents(RID p_probe) const { return Vector3(); } Vector3 reflection_probe_get_origin_offset(RID p_probe) const { return Vector3(); } @@ -581,7 +584,7 @@ public: RID canvas_light_occluder_create() { return RID(); } void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) {} - VS::InstanceType get_base_type(RID p_rid) const {} + VS::InstanceType get_base_type(RID p_rid) const { return VS::INSTANCE_NONE; } bool free(RID p_rid) { if (texture_owner.owns(p_rid)) { @@ -590,9 +593,10 @@ public: texture_owner.free(p_rid); memdelete(texture); } + return true; } - bool has_os_feature(const String &p_feature) const {} + bool has_os_feature(const String &p_feature) const { return false; } void update_dirty_resources() {} @@ -600,9 +604,9 @@ public: void render_info_begin_capture() {} void render_info_end_capture() {} - int get_captured_render_info(VS::RenderInfo p_info) {} + int get_captured_render_info(VS::RenderInfo p_info) { return 0; } - int get_render_info(VS::RenderInfo p_info) {} + int get_render_info(VS::RenderInfo p_info) { return 0; } static RasterizerStorage *base_singleton; @@ -619,7 +623,7 @@ public: void canvas_begin(){}; void canvas_end(){}; - void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light){}; + void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform){}; void canvas_debug_viewport_shadows(Light *p_lights_with_shadow){}; void 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/gles2/SCsub b/drivers/gles2/SCsub new file mode 100644 index 0000000000..2471dd3739 --- /dev/null +++ b/drivers/gles2/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import('env') + +env.add_source_files(env.drivers_sources,"*.cpp") + +SConscript("shaders/SCsub") diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp new file mode 100644 index 0000000000..cc8e3277b9 --- /dev/null +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -0,0 +1,1147 @@ +/*************************************************************************/ +/* rasterizer_canvas_gles2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "rasterizer_canvas_gles2.h" +#include "os/os.h" +#include "project_settings.h" +#include "rasterizer_scene_gles2.h" +#include "servers/visual/visual_server_raster.h" +#ifndef GLES_OVER_GL +#define glClearDepth glClearDepthf +#endif + +RID RasterizerCanvasGLES2::light_internal_create() { + + return RID(); +} + +void RasterizerCanvasGLES2::light_internal_update(RID p_rid, Light *p_light) { +} + +void RasterizerCanvasGLES2::light_internal_free(RID p_rid) { +} + +void RasterizerCanvasGLES2::_set_uniforms() { + + state.canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX, state.uniforms.projection_matrix); + state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); + state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, state.uniforms.extra_matrix); + + state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE, state.uniforms.final_modulate); +} + +void RasterizerCanvasGLES2::canvas_begin() { + + if (storage->frame.clear_request) { + glClearColor(storage->frame.clear_request_color.r, + storage->frame.clear_request_color.g, + storage->frame.clear_request_color.b, + storage->frame.clear_request_color.a); + glClear(GL_COLOR_BUFFER_BIT); + storage->frame.clear_request = false; + } + + if (storage->frame.current_rt) { + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); + glColorMask(1, 1, 1, 1); + } + + reset_canvas(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); + + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + glDisableVertexAttribArray(VS::ARRAY_COLOR); + + // set up default uniforms + + Transform canvas_transform; + + if (storage->frame.current_rt) { + + float csy = 1.0; + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { + csy = -1.0; + } + canvas_transform.translate(-(storage->frame.current_rt->width / 2.0f), -(storage->frame.current_rt->height / 2.0f), 0.0f); + canvas_transform.scale(Vector3(2.0f / storage->frame.current_rt->width, csy * -2.0f / storage->frame.current_rt->height, 1.0f)); + } else { + Vector2 ssize = OS::get_singleton()->get_window_size(); + canvas_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); + canvas_transform.scale(Vector3(2.0f / ssize.width, -2.0f / ssize.height, 1.0f)); + } + + state.uniforms.projection_matrix = canvas_transform; + + state.uniforms.final_modulate = Color(1, 1, 1, 1); + + state.uniforms.modelview_matrix = Transform2D(); + state.uniforms.extra_matrix = Transform2D(); + + _set_uniforms(); + _bind_quad_buffer(); +} + +void RasterizerCanvasGLES2::canvas_end() { + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + for (int i = 0; i < VS::ARRAY_MAX; i++) { + glDisableVertexAttribArray(i); + } + + state.using_texture_rect = false; + state.using_ninepatch = false; +} + +RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) { + + RasterizerStorageGLES2::Texture *tex_return = NULL; + + if (p_texture.is_valid()) { + + RasterizerStorageGLES2::Texture *texture = storage->texture_owner.getornull(p_texture); + + if (!texture) { + state.current_tex = RID(); + state.current_tex_ptr = NULL; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); + + } else { + + texture = texture->get_ptr(); + + if (texture->render_target) { + texture->render_target->used_in_frame = true; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->tex_id); + + state.current_tex = p_texture; + state.current_tex_ptr = texture; + + tex_return = texture; + } + } else { + state.current_tex = RID(); + state.current_tex_ptr = NULL; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); + } + + return tex_return; +} + +void RasterizerCanvasGLES2::_set_texture_rect_mode(bool p_enable, bool p_ninepatch) { +} + +void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { + + glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); + + uint32_t buffer_ofs = 0; + + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices); + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + + if (p_singlecolor) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + Color m = *p_colors; + glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + } else if (!p_colors) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + } else { + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(Color) * p_vertex_count; + } + + if (p_uvs) { + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); + + glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void RasterizerCanvasGLES2::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { + + glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); + + uint32_t buffer_ofs = 0; + + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices); + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), (uint8_t *)0); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + + if (p_singlecolor) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + Color m = *p_colors; + glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + } else if (!p_colors) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + } else { + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(Color) * p_vertex_count; + } + + if (p_uvs) { + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glDrawArrays(p_primitive, 0, p_vertex_count); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void RasterizerCanvasGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) { + + static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; + + int color_offset = 0; + int uv_offset = 0; + int stride = 2; + + if (p_colors) { + color_offset = stride; + stride += 4; + } + + if (p_uvs) { + uv_offset = stride; + stride += 2; + } + + float buffer_data[(2 + 2 + 4) * 4]; + + for (int i = 0; i < p_points; i++) { + buffer_data[stride * i + 0] = p_vertices[i].x; + buffer_data[stride * i + 1] = p_vertices[i].y; + } + + if (p_colors) { + for (int i = 0; i < p_points; i++) { + buffer_data[stride * i + color_offset + 0] = p_colors[i].r; + buffer_data[stride * i + color_offset + 1] = p_colors[i].g; + buffer_data[stride * i + color_offset + 2] = p_colors[i].b; + buffer_data[stride * i + color_offset + 3] = p_colors[i].a; + } + } + + if (p_uvs) { + for (int i = 0; i < p_points; i++) { + buffer_data[stride * i + uv_offset + 0] = p_uvs[i].x; + buffer_data[stride * i + uv_offset + 1] = p_uvs[i].y; + } + } + + glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); + glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), buffer_data); + + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), NULL); + + if (p_colors) { + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), (uint8_t *)0 + color_offset * sizeof(float)); + glEnableVertexAttribArray(VS::ARRAY_COLOR); + } + + if (p_uvs) { + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), (uint8_t *)0 + uv_offset * sizeof(float)); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glDrawArrays(prim[p_points], 0, p_points); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip) { + + int command_count = p_item->commands.size(); + Item::Command **commands = p_item->commands.ptrw(); + + for (int i = 0; i < command_count; i++) { + + Item::Command *command = commands[i]; + + switch (command->type) { + + case Item::Command::TYPE_LINE: { + + Item::CommandLine *line = static_cast<Item::CommandLine *>(command); + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false); + state.canvas_shader.bind(); + + _set_uniforms(); + + _bind_canvas_texture(RID(), RID()); + + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4fv(VS::ARRAY_COLOR, line->color.components); + + state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); + + if (line->width <= 1) { + Vector2 verts[2] = { + Vector2(line->from.x, line->from.y), + Vector2(line->to.x, line->to.y) + }; + + _draw_gui_primitive(2, verts, NULL, NULL); + } else { + Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5; + + Vector2 verts[4] = { + line->from - t, + line->from + t, + line->to + t, + line->to - t + }; + + _draw_gui_primitive(4, verts, NULL, NULL); + } + + } break; + + case Item::Command::TYPE_RECT: { + + Item::CommandRect *r = static_cast<Item::CommandRect *>(command); + + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4fv(VS::ARRAY_COLOR, r->modulate.components); + + _bind_quad_buffer(); + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false); + if (state.canvas_shader.bind()) + _set_uniforms(); + + RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map); + + if (!tex) { + Rect2 dst_rect = Rect2(r->rect.position, r->rect.size); + + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(0, 0, 1, 1)); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } else { + + bool untile = false; + + if (r->flags & CANVAS_RECT_TILE && !(tex->flags & VS::TEXTURE_FLAG_REPEAT)) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + untile = true; + } + + Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height); + Rect2 src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1); + + Rect2 dst_rect = Rect2(r->rect.position, r->rect.size); + + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + if (r->flags & CANVAS_RECT_FLIP_H) { + src_rect.size.x *= -1; + } + + if (r->flags & CANVAS_RECT_FLIP_V) { + src_rect.size.y *= -1; + } + + if (r->flags & CANVAS_RECT_TRANSPOSE) { + dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform + } + + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + + state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y)); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + if (untile) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + } break; + + case Item::Command::TYPE_NINEPATCH: { + + Item::CommandNinePatch *np = static_cast<Item::CommandNinePatch *>(command); + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true); + if (state.canvas_shader.bind()) + _set_uniforms(); + + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4fv(VS::ARRAY_COLOR, np->color.components); + + RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(np->texture, np->normal_map); + + if (!tex) { + print_line("TODO: ninepatch without texture"); + continue; + } + + Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height); + + // state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + + // prepare vertex buffer + + float buffer[16 * 2 + 16 * 2]; + + { + + // first row + + buffer[(0 * 4 * 4) + 0] = np->rect.position.x; + buffer[(0 * 4 * 4) + 1] = np->rect.position.y; + + buffer[(0 * 4 * 4) + 2] = np->source.position.x * texpixel_size.x; + buffer[(0 * 4 * 4) + 3] = np->source.position.y * texpixel_size.y; + + buffer[(0 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT]; + buffer[(0 * 4 * 4) + 5] = np->rect.position.y; + + buffer[(0 * 4 * 4) + 6] = (np->source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x; + buffer[(0 * 4 * 4) + 7] = np->source.position.y * texpixel_size.y; + + buffer[(0 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT]; + buffer[(0 * 4 * 4) + 9] = np->rect.position.y; + + buffer[(0 * 4 * 4) + 10] = (np->source.position.x + np->source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x; + buffer[(0 * 4 * 4) + 11] = np->source.position.y * texpixel_size.y; + + buffer[(0 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x; + buffer[(0 * 4 * 4) + 13] = np->rect.position.y; + + buffer[(0 * 4 * 4) + 14] = (np->source.position.x + np->source.size.x) * texpixel_size.x; + buffer[(0 * 4 * 4) + 15] = np->source.position.y * texpixel_size.y; + + // second row + + buffer[(1 * 4 * 4) + 0] = np->rect.position.x; + buffer[(1 * 4 * 4) + 1] = np->rect.position.y + np->margin[MARGIN_TOP]; + + buffer[(1 * 4 * 4) + 2] = np->source.position.x * texpixel_size.x; + buffer[(1 * 4 * 4) + 3] = (np->source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y; + + buffer[(1 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT]; + buffer[(1 * 4 * 4) + 5] = np->rect.position.y + np->margin[MARGIN_TOP]; + + buffer[(1 * 4 * 4) + 6] = (np->source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x; + buffer[(1 * 4 * 4) + 7] = (np->source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y; + + buffer[(1 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT]; + buffer[(1 * 4 * 4) + 9] = np->rect.position.y + np->margin[MARGIN_TOP]; + + buffer[(1 * 4 * 4) + 10] = (np->source.position.x + np->source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x; + buffer[(1 * 4 * 4) + 11] = (np->source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y; + + buffer[(1 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x; + buffer[(1 * 4 * 4) + 13] = np->rect.position.y + np->margin[MARGIN_TOP]; + + buffer[(1 * 4 * 4) + 14] = (np->source.position.x + np->source.size.x) * texpixel_size.x; + buffer[(1 * 4 * 4) + 15] = (np->source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y; + + // thrid row + + buffer[(2 * 4 * 4) + 0] = np->rect.position.x; + buffer[(2 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM]; + + buffer[(2 * 4 * 4) + 2] = np->source.position.x * texpixel_size.x; + buffer[(2 * 4 * 4) + 3] = (np->source.position.y + np->source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y; + + buffer[(2 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT]; + buffer[(2 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM]; + + buffer[(2 * 4 * 4) + 6] = (np->source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x; + buffer[(2 * 4 * 4) + 7] = (np->source.position.y + np->source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y; + + buffer[(2 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT]; + buffer[(2 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM]; + + buffer[(2 * 4 * 4) + 10] = (np->source.position.x + np->source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x; + buffer[(2 * 4 * 4) + 11] = (np->source.position.y + np->source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y; + + buffer[(2 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x; + buffer[(2 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM]; + + buffer[(2 * 4 * 4) + 14] = (np->source.position.x + np->source.size.x) * texpixel_size.x; + buffer[(2 * 4 * 4) + 15] = (np->source.position.y + np->source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y; + + // fourth row + + buffer[(3 * 4 * 4) + 0] = np->rect.position.x; + buffer[(3 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y; + + buffer[(3 * 4 * 4) + 2] = np->source.position.x * texpixel_size.x; + buffer[(3 * 4 * 4) + 3] = (np->source.position.y + np->source.size.y) * texpixel_size.y; + + buffer[(3 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT]; + buffer[(3 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y; + + buffer[(3 * 4 * 4) + 6] = (np->source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x; + buffer[(3 * 4 * 4) + 7] = (np->source.position.y + np->source.size.y) * texpixel_size.y; + + buffer[(3 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT]; + buffer[(3 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y; + + buffer[(3 * 4 * 4) + 10] = (np->source.position.x + np->source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x; + buffer[(3 * 4 * 4) + 11] = (np->source.position.y + np->source.size.y) * texpixel_size.y; + + buffer[(3 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x; + buffer[(3 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y; + + buffer[(3 * 4 * 4) + 14] = (np->source.position.x + np->source.size.x) * texpixel_size.x; + buffer[(3 * 4 * 4) + 15] = (np->source.position.y + np->source.size.y) * texpixel_size.y; + + // print_line(String::num((np->source.position.y + np->source.size.y) * texpixel_size.y)); + } + + glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * (16 + 16) * 2, buffer); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements); + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), NULL); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (uint8_t *)0 + (sizeof(float) * 2)); + + glDrawElements(GL_TRIANGLES, 18 * 3 - (np->draw_center ? 0 : 6), GL_UNSIGNED_BYTE, NULL); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + } break; + + case Item::Command::TYPE_CIRCLE: { + + Item::CommandCircle *circle = static_cast<Item::CommandCircle *>(command); + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false); + + if (state.canvas_shader.bind()) + _set_uniforms(); + + static const int num_points = 32; + + Vector2 points[num_points + 1]; + points[num_points] = circle->pos; + + 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; + } + + _bind_canvas_texture(RID(), RID()); + + _draw_polygon(indices, num_points * 3, num_points + 1, points, NULL, &circle->color, true); + } break; + + case Item::Command::TYPE_POLYGON: { + + Item::CommandPolygon *polygon = static_cast<Item::CommandPolygon *>(command); + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true); + + if (state.canvas_shader.bind()) + _set_uniforms(); + + RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + } + + _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); + } break; + + case Item::Command::TYPE_POLYLINE: { + Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(command); + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false); + + if (state.canvas_shader.bind()) + _set_uniforms(); + + if (pline->triangles.size()) { + _draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1); + } else { + if (pline->multiline) { + int todo = pline->lines.size() / 2; + int max_per_call = data.polygon_buffer_size / (sizeof(real_t) * 4); + int offset = 0; + + while (todo) { + int to_draw = MIN(max_per_call, todo); + _draw_generic(GL_LINES, to_draw * 2, &pline->lines.ptr()[offset], NULL, pline->line_colors.size() == 1 ? pline->line_colors.ptr() : &pline->line_colors.ptr()[offset], pline->line_colors.size() == 1); + todo -= to_draw; + offset += to_draw * 2; + } + } else { + _draw_generic(GL_LINES, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); + } + } + } break; + + case Item::Command::TYPE_PRIMITIVE: { + + Item::CommandPrimitive *primitive = static_cast<Item::CommandPrimitive *>(command); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true); + + if (state.canvas_shader.bind()) + _set_uniforms(); + + ERR_CONTINUE(primitive->points.size() < 1); + + RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(primitive->texture, primitive->normal_map); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size); + } + + 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); + } else if (primitive->colors.empty()) { + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + } + + _draw_gui_primitive(primitive->points.size(), primitive->points.ptr(), primitive->colors.ptr(), primitive->uvs.ptr()); + } break; + + case Item::Command::TYPE_TRANSFORM: { + Item::CommandTransform *transform = static_cast<Item::CommandTransform *>(command); + state.uniforms.extra_matrix = transform->xform; + state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, state.uniforms.extra_matrix); + } break; + + case Item::Command::TYPE_PARTICLES: { + + } break; + + case Item::Command::TYPE_CLIP_IGNORE: { + + Item::CommandClipIgnore *ci = static_cast<Item::CommandClipIgnore *>(command); + if (current_clip) { + if (ci->ignore != reclip) { + if (ci->ignore) { + glDisable(GL_SCISSOR_TEST); + reclip = true; + } else { + glEnable(GL_SCISSOR_TEST); + + int x = current_clip->final_clip_rect.position.x; + int y = storage->frame.current_rt->height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.y); + int w = current_clip->final_clip_rect.size.x; + int h = current_clip->final_clip_rect.size.y; + + glScissor(x, y, w, h); + + reclip = false; + } + } + } + + } break; + + default: { + print_line("other"); + } break; + } + } +} + +void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { + + // This isn't really working yet, so disabling for now. + + /* + 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); + + if (p_rect != Rect2()) { + // only use section + + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true); + } + + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section); + + _bind_quad_buffer(); + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(VS::ARRAY_VERTEX); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); + + state.canvas_shader.bind(); + _bind_canvas_texture(state.current_tex, state.current_normal); + + 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) { + + Item *current_clip = NULL; + + RasterizerStorageGLES2::Shader *shader_cache = NULL; + + bool rebind_shader = true; + + Size2 rt_size = Size2(storage->frame.current_rt->width, storage->frame.current_rt->height); + + state.current_tex = RID(); + state.current_tex_ptr = NULL; + state.current_normal = RID(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); + + int last_blend_mode = -1; + + RID canvas_last_material = RID(); + + while (p_item_list) { + + Item *ci = p_item_list; + + if (current_clip != ci->final_clip_owner) { + + current_clip = ci->final_clip_owner; + + if (current_clip) { + glEnable(GL_SCISSOR_TEST); + glScissor(current_clip->final_clip_rect.position.x, (rt_size.height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.height)), current_clip->final_clip_rect.size.width, current_clip->final_clip_rect.size.height); + } else { + glDisable(GL_SCISSOR_TEST); + } + } + + // TODO: copy back buffer + + if (ci->copy_back_buffer) { + if (ci->copy_back_buffer->full) { + _copy_texscreen(Rect2()); + } else { + _copy_texscreen(ci->copy_back_buffer->rect); + } + } + + Item *material_owner = ci->material_owner ? ci->material_owner : ci; + + RID material = material_owner->material; + + if (material != canvas_last_material || rebind_shader) { + + RasterizerStorageGLES2::Material *material_ptr = storage->material_owner.getornull(material); + RasterizerStorageGLES2::Shader *shader_ptr = NULL; + + if (material_ptr) { + shader_ptr = material_ptr->shader; + + if (shader_ptr && shader_ptr->mode != VS::SHADER_CANVAS_ITEM) { + shader_ptr = NULL; // not a canvas item shader, don't use. + } + } + + if (shader_ptr) { + if (shader_ptr->canvas_item.uses_screen_texture) { + _copy_texscreen(Rect2()); + } + + if (shader_ptr != shader_cache) { + + if (shader_ptr->canvas_item.uses_time) { + VisualServerRaster::redraw_request(); + } + + state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); + state.canvas_shader.bind(); + } + + int tc = material_ptr->textures.size(); + RID *textures = material_ptr->textures.ptrw(); + + ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = shader_ptr->texture_hints.ptrw(); + + for (int i = 0; i < tc; i++) { + + glActiveTexture(GL_TEXTURE2 + i); + + RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i]); + + if (!t) { + + switch (texture_hints[i]) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: { + glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { + glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { + glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); + } break; + default: { + glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); + } break; + } + + continue; + } + + t = t->get_ptr(); + + glBindTexture(t->target, t->tex_id); + } + } else { + state.canvas_shader.set_custom_shader(0); + state.canvas_shader.bind(); + } + + shader_cache = shader_ptr; + + canvas_last_material = material; + + rebind_shader = false; + } + + int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX; + bool unshaded = true || (shader_cache && blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX); + bool reclip = false; + + if (last_blend_mode != blend_mode) { + + switch (blend_mode) { + + case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + } break; + case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_ADD: { + + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + } break; + case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_SUB: { + + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + } break; + case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_DST_COLOR, GL_ZERO); + } break; + case RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } break; + } + } + + state.uniforms.final_modulate = unshaded ? ci->final_modulate : Color(ci->final_modulate.r * p_modulate.r, ci->final_modulate.g * p_modulate.g, ci->final_modulate.b * p_modulate.b, ci->final_modulate.a * p_modulate.a); + + state.uniforms.modelview_matrix = ci->final_transform; + state.uniforms.extra_matrix = Transform2D(); + + _set_uniforms(); + + _canvas_item_render_commands(p_item_list, NULL, reclip); + + rebind_shader = true; // hacked in for now. + + if (reclip) { + glEnable(GL_SCISSOR_TEST); + glScissor(current_clip->final_clip_rect.position.x, (rt_size.height - (current_clip->final_clip_rect.position.y + current_clip->final_clip_rect.size.height)), current_clip->final_clip_rect.size.width, current_clip->final_clip_rect.size.height); + } + + p_item_list = p_item_list->next; + } + + if (current_clip) { + glDisable(GL_SCISSOR_TEST); + } +} + +void RasterizerCanvasGLES2::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) { +} + +void RasterizerCanvasGLES2::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) { +} + +void RasterizerCanvasGLES2::reset_canvas() { + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DITHER); + glEnable(GL_BLEND); + + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // bind the back buffer to a texture so shaders can use it. + // It should probably use texture unit -3 (as GLES3 does as well) but currently that's buggy. + // keeping this for now as there's nothing else that uses texture unit 2 + // TODO ^ + if (storage->frame.current_rt) { + glActiveTexture(GL_TEXTURE0 + 2); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void RasterizerCanvasGLES2::_bind_quad_buffer() { + glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices); + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, NULL); +} +void RasterizerCanvasGLES2::draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src) { + + state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y)); + state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(p_src.position.x, p_src.position.y, p_src.size.x, p_src.size.y)); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +void RasterizerCanvasGLES2::draw_window_margins(int *black_margin, RID *black_image) { +} + +void RasterizerCanvasGLES2::initialize() { + + // quad buffer + { + glGenBuffers(1, &data.canvas_quad_vertices); + glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices); + + const float qv[8] = { + 0, 0, + 0, 1, + 1, 1, + 1, 0 + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, qv, GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + // polygon buffer + { + uint32_t poly_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128); + poly_size *= 1024; + poly_size = MAX(poly_size, (2 + 2 + 4) * 4 * sizeof(float)); + glGenBuffers(1, &data.polygon_buffer); + glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); + glBufferData(GL_ARRAY_BUFFER, poly_size, NULL, GL_DYNAMIC_DRAW); + + data.polygon_buffer_size = poly_size; + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + uint32_t index_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_index_size_kb", 128); + index_size *= 1024; // kb + glGenBuffers(1, &data.polygon_index_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + // ninepatch buffers + { + // array buffer + glGenBuffers(1, &data.ninepatch_vertices); + glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices); + + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (16 + 16) * 2, NULL, GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // element buffer + glGenBuffers(1, &data.ninepatch_elements); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements); + +#define _EIDX(y, x) (y * 4 + x) + uint8_t elems[3 * 2 * 9] = { + + // first row + + _EIDX(0, 0), _EIDX(0, 1), _EIDX(1, 1), + _EIDX(1, 1), _EIDX(1, 0), _EIDX(0, 0), + + _EIDX(0, 1), _EIDX(0, 2), _EIDX(1, 2), + _EIDX(1, 2), _EIDX(1, 1), _EIDX(0, 1), + + _EIDX(0, 2), _EIDX(0, 3), _EIDX(1, 3), + _EIDX(1, 3), _EIDX(1, 2), _EIDX(0, 2), + + // second row + + _EIDX(1, 0), _EIDX(1, 1), _EIDX(2, 1), + _EIDX(2, 1), _EIDX(2, 0), _EIDX(1, 0), + + // the center one would be here, but we'll put it at the end + // so it's easier to disable the center and be able to use + // one draw call for both + + _EIDX(1, 2), _EIDX(1, 3), _EIDX(2, 3), + _EIDX(2, 3), _EIDX(2, 2), _EIDX(1, 2), + + // third row + + _EIDX(2, 0), _EIDX(2, 1), _EIDX(3, 1), + _EIDX(3, 1), _EIDX(3, 0), _EIDX(2, 0), + + _EIDX(2, 1), _EIDX(2, 2), _EIDX(3, 2), + _EIDX(3, 2), _EIDX(3, 1), _EIDX(2, 1), + + _EIDX(2, 2), _EIDX(2, 3), _EIDX(3, 3), + _EIDX(3, 3), _EIDX(3, 2), _EIDX(2, 2), + + // center field + + _EIDX(1, 1), _EIDX(1, 2), _EIDX(2, 2), + _EIDX(2, 2), _EIDX(2, 1), _EIDX(1, 1) + }; + ; +#undef _EIDX + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elems), elems, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + state.canvas_shader.init(); + + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true); + + state.canvas_shader.bind(); +} + +void RasterizerCanvasGLES2::finalize() { +} + +RasterizerCanvasGLES2::RasterizerCanvasGLES2() { +} diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h new file mode 100644 index 0000000000..4eab8c6038 --- /dev/null +++ b/drivers/gles2/rasterizer_canvas_gles2.h @@ -0,0 +1,129 @@ +/*************************************************************************/ +/* rasterizer_canvas_gles2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 RASTERIZERCANVASGLES2_H +#define RASTERIZERCANVASGLES2_H + +#include "rasterizer_storage_gles2.h" +#include "servers/visual/rasterizer.h" + +#include "shaders/canvas.glsl.gen.h" + +// #include "shaders/canvas_shadow.glsl.gen.h" + +class RasterizerSceneGLES2; + +class RasterizerCanvasGLES2 : public RasterizerCanvas { +public: + struct Uniforms { + Transform projection_matrix; + + Transform2D modelview_matrix; + Transform2D extra_matrix; + + Color final_modulate; + + float time; + }; + + struct Data { + + GLuint canvas_quad_vertices; + GLuint polygon_buffer; + GLuint polygon_index_buffer; + + uint32_t polygon_buffer_size; + + GLuint ninepatch_vertices; + GLuint ninepatch_elements; + + } data; + + struct State { + Uniforms uniforms; + bool canvas_texscreen_used; + CanvasShaderGLES2 canvas_shader; + // CanvasShadowShaderGLES3 canvas_shadow_shader; + + bool using_texture_rect; + bool using_ninepatch; + + RID current_tex; + RID current_normal; + RasterizerStorageGLES2::Texture *current_tex_ptr; + + Transform vp; + + } state; + + typedef void Texture; + + RasterizerSceneGLES2 *scene_render; + + RasterizerStorageGLES2 *storage; + + virtual RID light_internal_create(); + virtual void light_internal_update(RID p_rid, Light *p_light); + virtual void light_internal_free(RID p_rid); + + void _set_uniforms(); + + virtual void canvas_begin(); + virtual void canvas_end(); + + _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false); + + _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); + _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); + _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); + _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); + virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow); + + virtual void 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); + + virtual void reset_canvas(); + + RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map); + + void _bind_quad_buffer(); + void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src); + + void initialize(); + void finalize(); + + virtual void draw_window_margins(int *black_margin, RID *black_image); + + RasterizerCanvasGLES2(); +}; + +#endif // RASTERIZERCANVASGLES2_H diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp new file mode 100644 index 0000000000..9339167c8e --- /dev/null +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -0,0 +1,416 @@ +/*************************************************************************/ +/* rasterizer_gles2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "rasterizer_gles2.h" + +#include "gl_context/context_gl.h" +#include "os/os.h" +#include "project_settings.h" +#include <string.h> + +#define _EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 +#define _EXT_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 +#define _EXT_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 +#define _EXT_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 +#define _EXT_DEBUG_SOURCE_API_ARB 0x8246 +#define _EXT_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 +#define _EXT_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 +#define _EXT_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 +#define _EXT_DEBUG_SOURCE_APPLICATION_ARB 0x824A +#define _EXT_DEBUG_SOURCE_OTHER_ARB 0x824B +#define _EXT_DEBUG_TYPE_ERROR_ARB 0x824C +#define _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D +#define _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E +#define _EXT_DEBUG_TYPE_PORTABILITY_ARB 0x824F +#define _EXT_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 +#define _EXT_DEBUG_TYPE_OTHER_ARB 0x8251 +#define _EXT_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 +#define _EXT_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 +#define _EXT_DEBUG_LOGGED_MESSAGES_ARB 0x9145 +#define _EXT_DEBUG_SEVERITY_HIGH_ARB 0x9146 +#define _EXT_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 +#define _EXT_DEBUG_SEVERITY_LOW_ARB 0x9148 +#define _EXT_DEBUG_OUTPUT 0x92E0 + +#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED) +#define GLAPIENTRY APIENTRY +#else +#define GLAPIENTRY +#endif + +static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam) { + + if (type == _EXT_DEBUG_TYPE_OTHER_ARB) + return; + + if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB) + return; //these are ultimately annoying, so removing for now + + char debSource[256], debType[256], debSev[256]; + if (source == _EXT_DEBUG_SOURCE_API_ARB) + strcpy(debSource, "OpenGL"); + else if (source == _EXT_DEBUG_SOURCE_WINDOW_SYSTEM_ARB) + strcpy(debSource, "Windows"); + else if (source == _EXT_DEBUG_SOURCE_SHADER_COMPILER_ARB) + strcpy(debSource, "Shader Compiler"); + else if (source == _EXT_DEBUG_SOURCE_THIRD_PARTY_ARB) + strcpy(debSource, "Third Party"); + else if (source == _EXT_DEBUG_SOURCE_APPLICATION_ARB) + strcpy(debSource, "Application"); + else if (source == _EXT_DEBUG_SOURCE_OTHER_ARB) + strcpy(debSource, "Other"); + + if (type == _EXT_DEBUG_TYPE_ERROR_ARB) + strcpy(debType, "Error"); + else if (type == _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB) + strcpy(debType, "Deprecated behavior"); + else if (type == _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB) + strcpy(debType, "Undefined behavior"); + else if (type == _EXT_DEBUG_TYPE_PORTABILITY_ARB) + strcpy(debType, "Portability"); + else if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB) + strcpy(debType, "Performance"); + else if (type == _EXT_DEBUG_TYPE_OTHER_ARB) + strcpy(debType, "Other"); + + if (severity == _EXT_DEBUG_SEVERITY_HIGH_ARB) + strcpy(debSev, "High"); + else if (severity == _EXT_DEBUG_SEVERITY_MEDIUM_ARB) + strcpy(debSev, "Medium"); + else if (severity == _EXT_DEBUG_SEVERITY_LOW_ARB) + strcpy(debSev, "Low"); + + String output = String() + "GL ERROR: Source: " + debSource + "\tType: " + debType + "\tID: " + itos(id) + "\tSeverity: " + debSev + "\tMessage: " + message; + + ERR_PRINTS(output); +} + +typedef void (*DEBUGPROCARB)(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const char *message, + const void *userParam); + +typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userParam); + +RasterizerStorage *RasterizerGLES2::get_storage() { + + return storage; +} + +RasterizerCanvas *RasterizerGLES2::get_canvas() { + + return canvas; +} + +RasterizerScene *RasterizerGLES2::get_scene() { + + return scene; +} + +void RasterizerGLES2::initialize() { + + if (OS::get_singleton()->is_stdout_verbose()) { + print_line("Using GLES2 video driver"); + } + +#ifdef GLAD_ENABLED + if (!gladLoadGL()) { + ERR_PRINT("Error initializing GLAD"); + } + +// GLVersion seems to be used for both GL and GL ES, so we need different version checks for them +#ifdef OPENGL_ENABLED // OpenGL 2.1 Profile required + if (GLVersion.major < 2) { +#else // OpenGL ES 3.0 + if (GLVersion.major < 2) { +#endif + ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 2.1 / OpenGL ES 2.0, sorry :(\n" + "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot will now crash with a segmentation fault."); + OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 2.1 / OpenGL ES 2.0, sorry :(\n" + "Godot Engine will self-destruct as soon as you acknowledge this error message.", + "Fatal error: Insufficient OpenGL / GLES driver support"); + } + +#ifdef GLES_OVER_GL + //Test GL_ARB_framebuffer_object extension + if (!GLAD_GL_ARB_framebuffer_object) { + //Try older GL_EXT_framebuffer_object extension + if (GLAD_GL_EXT_framebuffer_object) { + glIsRenderbuffer = glIsRenderbufferEXT; + glBindRenderbuffer = glBindRenderbufferEXT; + glDeleteRenderbuffers = glDeleteRenderbuffersEXT; + glGenRenderbuffers = glGenRenderbuffersEXT; + glRenderbufferStorage = glRenderbufferStorageEXT; + glGetRenderbufferParameteriv = glGetRenderbufferParameterivEXT; + glIsFramebuffer = glIsFramebufferEXT; + glBindFramebuffer = glBindFramebufferEXT; + glDeleteFramebuffers = glDeleteFramebuffersEXT; + glGenFramebuffers = glGenFramebuffersEXT; + glCheckFramebufferStatus = glCheckFramebufferStatusEXT; + glFramebufferTexture1D = glFramebufferTexture1DEXT; + glFramebufferTexture2D = glFramebufferTexture2DEXT; + glFramebufferTexture3D = glFramebufferTexture3DEXT; + glFramebufferRenderbuffer = glFramebufferRenderbufferEXT; + glGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameterivEXT; + glGenerateMipmap = glGenerateMipmapEXT; + } else { + ERR_PRINT("Your system's graphic drivers seem not to support GL_ARB(EXT)_framebuffer_object OpenGL extension, sorry :(\n" + "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot will now crash with a segmentation fault."); + OS::get_singleton()->alert("Your system's graphic drivers seem not to support GL_ARB(EXT)_framebuffer_object OpenGL extension, sorry :(\n" + "Godot Engine will self-destruct as soon as you acknowledge this error message.", + "Fatal error: Insufficient OpenGL / GLES driver support"); + } + } +#endif + if (true || OS::get_singleton()->is_stdout_verbose()) { + if (GLAD_GL_ARB_debug_output) { + glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + glDebugMessageCallbackARB(_gl_debug_print, NULL); + glEnable(_EXT_DEBUG_OUTPUT); + } else { + print_line("OpenGL debugging not supported!"); + } + } + +#endif // GLAD_ENABLED + + // For debugging +#ifdef GLES_OVER_GL + if (GLAD_GL_ARB_debug_output) { + glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_ERROR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); + glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); + glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); + glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_PORTABILITY_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); + glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_PERFORMANCE_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); + glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_OTHER_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE); + /* glDebugMessageInsertARB( + GL_DEBUG_SOURCE_API_ARB, + GL_DEBUG_TYPE_OTHER_ARB, 1, + GL_DEBUG_SEVERITY_HIGH_ARB, 5, "hello"); + */ + } +#endif + + const GLubyte *renderer = glGetString(GL_RENDERER); + print_line("OpenGL ES 2.0 Renderer: " + String((const char *)renderer)); + storage->initialize(); + canvas->initialize(); + scene->initialize(); +} + +void RasterizerGLES2::begin_frame() { + uint64_t tick = OS::get_singleton()->get_ticks_usec(); + + double delta = double(tick - prev_ticks) / 1000000.0; + delta *= Engine::get_singleton()->get_time_scale(); + + time_total += delta; + + if (delta == 0) { + //to avoid hiccups + delta = 0.001; + } + + prev_ticks = tick; + + // double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs"); + // if (time_total > time_roll_over) + // time_total = 0; //roll over every day (should be customz + + storage->frame.time[0] = time_total; + storage->frame.time[1] = Math::fmod(time_total, 3600); + storage->frame.time[2] = Math::fmod(time_total, 900); + storage->frame.time[3] = Math::fmod(time_total, 60); + storage->frame.count++; + storage->frame.delta = delta; + + storage->frame.prev_tick = tick; + + storage->update_dirty_resources(); + + storage->info.render_final = storage->info.render; + storage->info.render.reset(); + + scene->iteration(); +} + +void RasterizerGLES2::set_current_render_target(RID p_render_target) { + + if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { + // pending clear request. Do that first. + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); + glClearColor(storage->frame.clear_request_color.r, + storage->frame.clear_request_color.g, + storage->frame.clear_request_color.b, + storage->frame.clear_request_color.a); + glClear(GL_COLOR_BUFFER_BIT); + } + + if (p_render_target.is_valid()) { + RasterizerStorageGLES2::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target); + storage->frame.current_rt = rt; + ERR_FAIL_COND(!rt); + storage->frame.clear_request = false; + + glViewport(0, 0, rt->width, rt->height); + } else { + storage->frame.current_rt = NULL; + storage->frame.clear_request = false; + glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); + } +} + +void RasterizerGLES2::restore_render_target() { + ERR_FAIL_COND(storage->frame.current_rt == NULL); + RasterizerStorageGLES2::RenderTarget *rt = storage->frame.current_rt; + glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); + glViewport(0, 0, rt->width, rt->height); +} + +void RasterizerGLES2::clear_render_target(const Color &p_color) { + ERR_FAIL_COND(!storage->frame.current_rt); + + storage->frame.clear_request = true; + storage->frame.clear_request_color = p_color; +} + +void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale) { + + if (p_image.is_null() || p_image->empty()) + return; + + int window_w = OS::get_singleton()->get_video_mode(0).width; + int window_h = OS::get_singleton()->get_video_mode(0).height; + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, window_w, window_h); + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glClearColor(p_color.r, p_color.g, p_color.b, p_color.a); + glClear(GL_COLOR_BUFFER_BIT); + + canvas->canvas_begin(); + + RID texture = storage->texture_create(); + storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), VS::TEXTURE_FLAG_FILTER); + storage->texture_set_data(texture, p_image); + + Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height()); + Rect2 screenrect; + + screenrect = imgrect; + screenrect.position += ((Size2(window_w, window_h) - screenrect.size) / 2.0).floor(); + + RasterizerStorageGLES2::Texture *t = storage->texture_owner.get(texture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, t->tex_id); + canvas->draw_generic_textured_rect(screenrect, Rect2(0, 0, 1, 1)); + glBindTexture(GL_TEXTURE_2D, 0); + canvas->canvas_end(); + + storage->free(texture); + + OS::get_singleton()->swap_buffers(); +} + +void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen) { + + ERR_FAIL_COND(storage->frame.current_rt); + + RasterizerStorageGLES2::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true); + canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false); + + canvas->state.canvas_shader.bind(); + + canvas->canvas_begin(); + canvas->state.canvas_shader.set_uniform(CanvasShaderGLES2::BLIT_PASS, true); + glDisable(GL_BLEND); + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rt->color); + + // TODO normals + + canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 0, 1, -1)); + + canvas->state.canvas_shader.set_uniform(CanvasShaderGLES2::BLIT_PASS, false); + + glBindTexture(GL_TEXTURE_2D, 0); + canvas->canvas_end(); +} + +void RasterizerGLES2::end_frame(bool p_swap_buffers) { + if (p_swap_buffers) + OS::get_singleton()->swap_buffers(); + else + glFinish(); +} + +void RasterizerGLES2::finalize() { +} + +Rasterizer *RasterizerGLES2::_create_current() { + + return memnew(RasterizerGLES2); +} + +void RasterizerGLES2::make_current() { + _create_func = _create_current; +} + +void RasterizerGLES2::register_config() { +} + +RasterizerGLES2::RasterizerGLES2() { + + storage = memnew(RasterizerStorageGLES2); + canvas = memnew(RasterizerCanvasGLES2); + scene = memnew(RasterizerSceneGLES2); + canvas->storage = storage; + canvas->scene_render = scene; + storage->canvas = canvas; + scene->storage = storage; + storage->scene = scene; + + prev_ticks = 0; + time_total = 0; +} + +RasterizerGLES2::~RasterizerGLES2() { + + memdelete(storage); + memdelete(canvas); +} diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h new file mode 100644 index 0000000000..8d57275449 --- /dev/null +++ b/drivers/gles2/rasterizer_gles2.h @@ -0,0 +1,72 @@ +/*************************************************************************/ +/* rasterizer_gles2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 RASTERIZERGLES2_H +#define RASTERIZERGLES2_H + +#include "rasterizer_canvas_gles2.h" +#include "rasterizer_scene_gles2.h" +#include "rasterizer_storage_gles2.h" +#include "servers/visual/rasterizer.h" + +class RasterizerGLES2 : public Rasterizer { + + static Rasterizer *_create_current(); + + RasterizerStorageGLES2 *storage; + RasterizerCanvasGLES2 *canvas; + RasterizerSceneGLES2 *scene; + + uint64_t prev_ticks; + double time_total; + +public: + virtual RasterizerStorage *get_storage(); + virtual RasterizerCanvas *get_canvas(); + virtual RasterizerScene *get_scene(); + + virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale); + + virtual void initialize(); + virtual void begin_frame(); + virtual void set_current_render_target(RID p_render_target); + virtual void restore_render_target(); + virtual void clear_render_target(const Color &p_color); + virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0); + virtual void end_frame(bool p_swap_buffers); + virtual void finalize(); + + static void make_current(); + + static void register_config(); + RasterizerGLES2(); + ~RasterizerGLES2(); +}; + +#endif // RASTERIZERGLES2_H diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp new file mode 100644 index 0000000000..bb39cbcbd5 --- /dev/null +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -0,0 +1,235 @@ +/*************************************************************************/ +/* rasterizer_scene_gles2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "rasterizer_scene_gles2.h" +#include "math_funcs.h" +#include "os/os.h" +#include "project_settings.h" +#include "rasterizer_canvas_gles2.h" +#include "servers/visual/visual_server_raster.h" + +#ifndef GLES_OVER_GL +#define glClearDepth glClearDepthf +#endif + +/* SHADOW ATLAS API */ + +RID RasterizerSceneGLES2::shadow_atlas_create() { + + return RID(); +} + +void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) { +} + +void RasterizerSceneGLES2::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { +} + +bool RasterizerSceneGLES2::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { + return false; +} + +void RasterizerSceneGLES2::set_directional_shadow_count(int p_count) { +} + +int RasterizerSceneGLES2::get_directional_light_shadow_size(RID p_light_intance) { + return 0; +} +////////////////////////////////////////////////////// + +RID RasterizerSceneGLES2::reflection_atlas_create() { + return RID(); +} + +void RasterizerSceneGLES2::reflection_atlas_set_size(RID p_ref_atlas, int p_size) { +} + +void RasterizerSceneGLES2::reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) { +} + +//////////////////////////////////////////////////// + +RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) { + return RID(); +} + +void RasterizerSceneGLES2::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) { +} + +void RasterizerSceneGLES2::reflection_probe_release_atlas_index(RID p_instance) { +} + +bool RasterizerSceneGLES2::reflection_probe_instance_needs_redraw(RID p_instance) { + return false; +} + +bool RasterizerSceneGLES2::reflection_probe_instance_has_reflection(RID p_instance) { + return false; +} + +bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { + return false; +} + +bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_instance) { + return false; +} + +/* ENVIRONMENT API */ + +RID RasterizerSceneGLES2::environment_create() { + + return RID(); +} + +void RasterizerSceneGLES2::environment_set_background(RID p_env, VS::EnvironmentBG p_bg) { +} + +void RasterizerSceneGLES2::environment_set_sky(RID p_env, RID p_sky) { +} + +void RasterizerSceneGLES2::environment_set_sky_custom_fov(RID p_env, float p_scale) { +} + +void RasterizerSceneGLES2::environment_set_bg_color(RID p_env, const Color &p_color) { +} + +void RasterizerSceneGLES2::environment_set_bg_energy(RID p_env, float p_energy) { +} + +void RasterizerSceneGLES2::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { +} + +void RasterizerSceneGLES2::environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy, float p_sky_contribution) { +} + +void RasterizerSceneGLES2::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { +} + +void RasterizerSceneGLES2::environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { +} + +void RasterizerSceneGLES2::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) { +} + +void RasterizerSceneGLES2::environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) { +} + +void RasterizerSceneGLES2::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) { +} + +void RasterizerSceneGLES2::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { +} + +void RasterizerSceneGLES2::environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { +} + +void RasterizerSceneGLES2::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) { +} + +void RasterizerSceneGLES2::environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) { +} + +void RasterizerSceneGLES2::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) { +} + +void RasterizerSceneGLES2::environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) { +} + +bool RasterizerSceneGLES2::is_environment(RID p_env) { + return false; +} + +VS::EnvironmentBG RasterizerSceneGLES2::environment_get_background(RID p_env) { + return VS::ENV_BG_CLEAR_COLOR; +} + +int RasterizerSceneGLES2::environment_get_canvas_max_layer(RID p_env) { + return 0; +} + +RID RasterizerSceneGLES2::light_instance_create(RID p_light) { + return RID(); +} + +void RasterizerSceneGLES2::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) { +} + +void RasterizerSceneGLES2::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) { +} + +void RasterizerSceneGLES2::light_instance_mark_visible(RID p_light_instance) { +} + +////////////////////// + +RID RasterizerSceneGLES2::gi_probe_instance_create() { + + return RID(); +} + +void RasterizerSceneGLES2::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) { +} +void RasterizerSceneGLES2::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) { +} + +void RasterizerSceneGLES2::gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) { +} + +//////////////////////////// +//////////////////////////// +//////////////////////////// + +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) { +} + +void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) { +} + +void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) { +} + +bool RasterizerSceneGLES2::free(RID p_rid) { + return true; +} + +void RasterizerSceneGLES2::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) { +} + +void RasterizerSceneGLES2::initialize() { +} + +void RasterizerSceneGLES2::iteration() { +} + +void RasterizerSceneGLES2::finalize() { +} + +RasterizerSceneGLES2::RasterizerSceneGLES2() { +} diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h new file mode 100644 index 0000000000..99f034afed --- /dev/null +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -0,0 +1,258 @@ +/*************************************************************************/ +/* rasterizer_scene_gles2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 RASTERIZERSCENEGLES2_H +#define RASTERIZERSCENEGLES2_H + +/* Must come before shaders or the Windows build fails... */ +#include "rasterizer_storage_gles2.h" + +#include "shaders/scene.glsl.gen.h" +/* + +#include "drivers/gles3/shaders/cube_to_dp.glsl.gen.h" +#include "drivers/gles3/shaders/effect_blur.glsl.gen.h" +#include "drivers/gles3/shaders/exposure.glsl.gen.h" +#include "drivers/gles3/shaders/resolve.glsl.gen.h" +#include "drivers/gles3/shaders/scene.glsl.gen.h" +#include "drivers/gles3/shaders/screen_space_reflection.glsl.gen.h" +#include "drivers/gles3/shaders/ssao.glsl.gen.h" +#include "drivers/gles3/shaders/ssao_blur.glsl.gen.h" +#include "drivers/gles3/shaders/ssao_minify.glsl.gen.h" +#include "drivers/gles3/shaders/subsurf_scattering.glsl.gen.h" +#include "drivers/gles3/shaders/tonemap.glsl.gen.h" + +*/ + +class RasterizerSceneGLES2 : public RasterizerScene { +public: + RasterizerStorageGLES2 *storage; + struct State { + + bool texscreen_copied; + int current_blend_mode; + float current_line_width; + int current_depth_draw; + bool current_depth_test; + GLuint current_main_tex; + + SceneShaderGLES2 scene_shader; + // CubeToDpShaderGLES3 cube_to_dp_shader; + // ResolveShaderGLES3 resolve_shader; + // ScreenSpaceReflectionShaderGLES3 ssr_shader; + // EffectBlurShaderGLES3 effect_blur_shader; + // SubsurfScatteringShaderGLES3 sss_shader; + // SsaoMinifyShaderGLES3 ssao_minify_shader; + // SsaoShaderGLES3 ssao_shader; + // SsaoBlurShaderGLES3 ssao_blur_shader; + // ExposureShaderGLES3 exposure_shader; + // TonemapShaderGLES3 tonemap_shader; + + /* + struct SceneDataUBO { + //this is a std140 compatible struct. Please read the OpenGL 3.3 Specificaiton spec before doing any changes + float projection_matrix[16]; + float inv_projection_matrix[16]; + float camera_inverse_matrix[16]; + float camera_matrix[16]; + float ambient_light_color[4]; + float bg_color[4]; + float fog_color_enabled[4]; + float fog_sun_color_amount[4]; + + float ambient_energy; + float bg_energy; + float z_offset; + float z_slope_scale; + float shadow_dual_paraboloid_render_zfar; + float shadow_dual_paraboloid_render_side; + float viewport_size[2]; + float screen_pixel_size[2]; + float shadow_atlas_pixel_size[2]; + float shadow_directional_pixel_size[2]; + + float time; + float z_far; + float reflection_multiplier; + float subsurface_scatter_width; + float ambient_occlusion_affect_light; + + uint32_t fog_depth_enabled; + float fog_depth_begin; + float fog_depth_curve; + uint32_t fog_transmit_enabled; + float fog_transmit_curve; + uint32_t fog_height_enabled; + float fog_height_min; + float fog_height_max; + float fog_height_curve; + // make sure this struct is padded to be a multiple of 16 bytes for webgl + + } ubo_data; + + GLuint scene_ubo; + + struct EnvironmentRadianceUBO { + + float transform[16]; + float ambient_contribution; + uint8_t padding[12]; + + } env_radiance_data; + + GLuint env_radiance_ubo; + + GLuint sky_verts; + GLuint sky_array; + + GLuint directional_ubo; + + GLuint spot_array_ubo; + GLuint omni_array_ubo; + GLuint reflection_array_ubo; + + GLuint immediate_buffer; + GLuint immediate_array; + + uint32_t ubo_light_size; + uint8_t *spot_array_tmp; + uint8_t *omni_array_tmp; + uint8_t *reflection_array_tmp; + + int max_ubo_lights; + int max_forward_lights_per_object; + int max_ubo_reflections; + int max_skeleton_bones; + + bool used_contact_shadows; + + int spot_light_count; + int omni_light_count; + int directional_light_count; + int reflection_probe_count; + + bool cull_front; + bool cull_disabled; + bool used_sss; + bool used_screen_texture; + bool using_contact_shadows; + + VS::ViewportDebugDraw debug_draw; + */ + } state; + + /* SHADOW ATLAS API */ + + RID shadow_atlas_create(); + void shadow_atlas_set_size(RID p_atlas, int p_size); + void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision); + bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version); + + virtual int get_directional_light_shadow_size(RID p_light_intance); + virtual void set_directional_shadow_count(int p_count); + + /* REFLECTION PROBE ATLAS API */ + + virtual RID reflection_atlas_create(); + virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size); + virtual void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv); + + /* REFLECTION CUBEMAPS */ + + /* REFLECTION PROBE INSTANCE */ + + virtual RID reflection_probe_instance_create(RID p_probe); + virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform); + virtual void reflection_probe_release_atlas_index(RID p_instance); + virtual bool reflection_probe_instance_needs_redraw(RID p_instance); + virtual bool reflection_probe_instance_has_reflection(RID p_instance); + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas); + virtual bool reflection_probe_instance_postprocess_step(RID p_instance); + + /* ENVIRONMENT API */ + virtual RID environment_create(); + + virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg); + virtual void environment_set_sky(RID p_env, RID p_sky); + virtual void environment_set_sky_custom_fov(RID p_env, float p_scale); + virtual void environment_set_bg_color(RID p_env, const Color &p_color); + virtual void environment_set_bg_energy(RID p_env, float p_energy); + virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); + + virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); + virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); + virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, bool p_bicubic_upscale); + virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture); + + virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness); + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); + + virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); + + virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp); + + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount); + virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve); + virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve); + + virtual bool is_environment(RID p_env); + + virtual VS::EnvironmentBG environment_get_background(RID p_env); + virtual int environment_get_canvas_max_layer(RID p_env); + + /* LIGHT INSTANCE */ + virtual RID light_instance_create(RID p_light); + virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform); + virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0); + virtual void light_instance_mark_visible(RID p_light_instance); + + /* REFLECTION INSTANCE */ + + virtual RID gi_probe_instance_create(); + virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data); + virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform); + virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds); + + /* RENDER LIST */ + + virtual void 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); + virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count); + virtual bool free(RID p_rid); + + virtual void set_scene_pass(uint64_t p_pass); + virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw); + + void iteration(); + void initialize(); + void finalize(); + RasterizerSceneGLES2(); +}; + +#endif // RASTERIZERSCENEGLES2_H diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp new file mode 100644 index 0000000000..5bca3ee548 --- /dev/null +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -0,0 +1,2061 @@ +/*************************************************************************/ +/* rasterizer_storage_gles2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "rasterizer_storage_gles2.h" +#include "project_settings.h" +#include "rasterizer_canvas_gles2.h" +#include "rasterizer_scene_gles2.h" + +GLuint RasterizerStorageGLES2::system_fbo = 0; + +/* TEXTURE API */ + +Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type) { + + r_gl_format = 0; + Ref<Image> image = p_image; + + bool need_decompress = false; + + switch (p_format) { + + case Image::FORMAT_L8: { + + r_gl_internal_format = GL_LUMINANCE; + r_gl_format = GL_LUMINANCE; + r_gl_type = GL_UNSIGNED_BYTE; + } break; + case Image::FORMAT_LA8: { + r_gl_internal_format = GL_LUMINANCE_ALPHA; + r_gl_format = GL_LUMINANCE_ALPHA; + r_gl_type = GL_UNSIGNED_BYTE; + } break; + case Image::FORMAT_R8: { + + r_gl_internal_format = GL_ALPHA; + r_gl_format = GL_ALPHA; + r_gl_type = GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RG8: { + + ERR_EXPLAIN("RG texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_RGB8: { + + r_gl_internal_format = GL_RGB; + r_gl_format = GL_RGB; + r_gl_type = GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RGBA8: { + + r_gl_format = GL_RGBA; + r_gl_internal_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + + } break; + case Image::FORMAT_RGBA4444: { + + r_gl_internal_format = GL_RGBA; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4; + + } break; + case Image::FORMAT_RGBA5551: { + + r_gl_internal_format = GL_RGB5_A1; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1; + + } break; + case Image::FORMAT_RF: { + ERR_EXPLAIN("R float texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_RGF: { + ERR_EXPLAIN("RG float texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_RGBF: { + + ERR_EXPLAIN("RGB float texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_RGBAF: { + + ERR_EXPLAIN("RGBA float texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_RH: { + ERR_EXPLAIN("R half float texture not supported"); + ERR_FAIL_V(image); + } break; + case Image::FORMAT_RGH: { + ERR_EXPLAIN("RG half float texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_RGBH: { + ERR_EXPLAIN("RGB half float texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_RGBAH: { + ERR_EXPLAIN("RGBA half float texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_RGBE9995: { + ERR_EXPLAIN("RGBA float texture not supported"); + ERR_FAIL_V(image); + + } break; + case Image::FORMAT_DXT1: { + + need_decompress = true; + + } break; + case Image::FORMAT_DXT3: { + + need_decompress = true; + + } break; + case Image::FORMAT_DXT5: { + + need_decompress = true; + + } break; + case Image::FORMAT_RGTC_R: { + + need_decompress = true; + + } break; + case Image::FORMAT_RGTC_RG: { + + need_decompress = true; + + } break; + case Image::FORMAT_BPTC_RGBA: { + + need_decompress = true; + } break; + case Image::FORMAT_BPTC_RGBF: { + + need_decompress = true; + } break; + case Image::FORMAT_BPTC_RGBFU: { + + need_decompress = true; + } break; + case Image::FORMAT_PVRTC2: { + + need_decompress = true; + } break; + case Image::FORMAT_PVRTC2A: { + + need_decompress = true; + } break; + case Image::FORMAT_PVRTC4: { + + need_decompress = true; + } break; + case Image::FORMAT_PVRTC4A: { + + need_decompress = true; + } break; + case Image::FORMAT_ETC: { + + need_decompress = true; + } break; + case Image::FORMAT_ETC2_R11: { + + need_decompress = true; + } break; + case Image::FORMAT_ETC2_R11S: { + + need_decompress = true; + } break; + case Image::FORMAT_ETC2_RG11: { + + need_decompress = true; + } break; + case Image::FORMAT_ETC2_RG11S: { + + need_decompress = true; + } break; + case Image::FORMAT_ETC2_RGB8: { + + need_decompress = true; + } break; + case Image::FORMAT_ETC2_RGBA8: { + + need_decompress = true; + } break; + case Image::FORMAT_ETC2_RGB8A1: { + + need_decompress = true; + } break; + default: { + + ERR_FAIL_V(Ref<Image>()); + } + } + + if (need_decompress) { + + if (!image.is_null()) { + image = image->duplicate(); + image->decompress(); + ERR_FAIL_COND_V(image->is_compressed(), image); + image->convert(Image::FORMAT_RGBA8); + } + + r_gl_format = GL_RGBA; + r_gl_internal_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + + return image; + } + + return p_image; +} + +static const GLenum _cube_side_enum[6] = { + + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + +}; + +RID RasterizerStorageGLES2::texture_create() { + + Texture *texture = memnew(Texture); + ERR_FAIL_COND_V(!texture, RID()); + glGenTextures(1, &texture->tex_id); + texture->active = false; + texture->total_data_size = 0; + + return texture_owner.make_rid(texture); +} + +void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags) { + GLenum format; + GLenum internal_format; + GLenum type; + + if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + p_flags &= ~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video + } + + Texture *texture = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!texture); + texture->width = p_width; + texture->height = p_height; + texture->format = p_format; + texture->flags = p_flags; + texture->stored_cube_sides = 0; + texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; + + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, format, internal_format, type); + + texture->alloc_width = texture->width; + texture->alloc_height = texture->height; + + texture->gl_format_cache = format; + texture->gl_type_cache = type; + texture->gl_internal_format_cache = internal_format; + texture->data_size = 0; + texture->mipmaps = 1; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + //prealloc if video + glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, type, NULL); + } + + texture->active = true; +} + +void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side) { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND(!texture); + ERR_FAIL_COND(!texture->active); + ERR_FAIL_COND(texture->render_target); + ERR_FAIL_COND(texture->format != p_image->get_format()); + ERR_FAIL_COND(p_image.is_null()); + + GLenum type; + GLenum format; + GLenum internal_format; + bool compressed = false; + bool srgb; + + if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { + texture->images[p_cube_side] = p_image; + } + + Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, format, internal_format, type); + + if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { + + texture->alloc_height = MAX(1, texture->alloc_height / 2); + texture->alloc_width = MAX(1, texture->alloc_width / 2); + + if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) { + + img->shrink_x2(); + } else if (img->get_format() <= Image::FORMAT_RGBA8) { + + img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); + } + }; + + GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_cube_side] : GL_TEXTURE_2D; + + texture->data_size = img->get_data().size(); + PoolVector<uint8_t>::Read read = img->get_data().read(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + texture->ignore_mipmaps = compressed && !img->has_mipmaps(); + + if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) + glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); + else { + if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + } + + if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering + + } else { + + glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering + } + + if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { + + if (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + } else { + + //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); + glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + +//set swizle for older format compatibility +#ifdef GLES_OVER_GL + switch (texture->format) { + + case Image::FORMAT_L8: { + + } break; + case Image::FORMAT_LA8: { + + } break; + default: { + + } break; + } +#endif + + int mipmaps = ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; + + int w = img->get_width(); + int h = img->get_height(); + + int tsize = 0; + + for (int i = 0; i < mipmaps; i++) { + + int size, ofs; + img->get_mipmap_offset_and_size(i, ofs, size); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]); + } else { + glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]); + } + + tsize += size; + + w = MAX(1, w >> 1); + h = MAX(1, h >> 1); + } + + info.texture_mem -= texture->total_data_size; + texture->total_data_size = tsize; + info.texture_mem += texture->total_data_size; + + // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem); + + texture->stored_cube_sides |= (1 << p_cube_side); + + if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (!(texture->flags & VS::TEXTURE_FLAG_CUBEMAP) || texture->stored_cube_sides == (1 << 6) - 1)) { + //generate mipmaps if they were requested and the image does not contain them + glGenerateMipmap(texture->target); + } + + texture->mipmaps = mipmaps; +} + +Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const { + + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND_V(!texture, Ref<Image>()); + ERR_FAIL_COND_V(!texture->active, Ref<Image>()); + ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>()); + + if (!texture->images[p_cube_side].is_null()) { + return texture->images[p_cube_side]; + } +#ifdef GLES_OVER_GL + + PoolVector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, texture->mipmaps > 1 ? -1 : 0); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + glActiveTexture(GL_TEXTURE0); + + glBindTexture(texture->target, texture->tex_id); + + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + //print_line("GET FORMAT: " + Image::get_format_name(texture->format) + " mipmaps: " + itos(texture->mipmaps)); + + for (int i = 0; i < texture->mipmaps; i++) { + + int ofs = 0; + if (i > 0) { + ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, i - 1); + } + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]); + } + + wb = PoolVector<uint8_t>::Write(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1 ? true : false, texture->format, data)); + + return Ref<Image>(img); +#else + + ERR_EXPLAIN("Sorry, It's not posible to obtain images back in OpenGL ES"); + return Ref<Image>(); +#endif +} + +void RasterizerStorageGLES2::texture_set_flags(RID p_texture, uint32_t p_flags) { + + Texture *texture = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!texture); + + bool had_mipmaps = texture->flags & VS::TEXTURE_FLAG_MIPMAPS; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; + texture->flags = p_flags | cube; // can't remove a cube from being a cube + + if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { + + if (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + } else { + //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); + glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { + if (!had_mipmaps && texture->mipmaps == 1) { + glGenerateMipmap(texture->target); + } + glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); + + } else { + if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + } + + if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering + + } else { + + glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering + } +} + +uint32_t RasterizerStorageGLES2::texture_get_flags(RID p_texture) const { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->flags; +} + +Image::Format RasterizerStorageGLES2::texture_get_format(RID p_texture) const { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND_V(!texture, Image::FORMAT_L8); + + return texture->format; +} + +uint32_t RasterizerStorageGLES2::texture_get_texid(RID p_texture) const { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->tex_id; +} + +uint32_t RasterizerStorageGLES2::texture_get_width(RID p_texture) const { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->width; +} + +uint32_t RasterizerStorageGLES2::texture_get_height(RID p_texture) const { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->height; +} + +void RasterizerStorageGLES2::texture_set_size_override(RID p_texture, int p_width, int p_height) { + Texture *texture = texture_owner.getornull(p_texture); + + ERR_FAIL_COND(!texture); + ERR_FAIL_COND(texture->render_target); + + ERR_FAIL_COND(p_width <= 0 || p_width > 16384); + ERR_FAIL_COND(p_height <= 0 || p_height > 16384); + //real texture size is in alloc width and height + texture->width = p_width; + texture->height = p_height; +} + +void RasterizerStorageGLES2::texture_set_path(RID p_texture, const String &p_path) { + Texture *texture = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!texture); + + texture->path = p_path; +} + +String RasterizerStorageGLES2::texture_get_path(RID p_texture) const { + Texture *texture = texture_owner.getornull(p_texture); + ERR_FAIL_COND_V(!texture, ""); + + return texture->path; +} + +void RasterizerStorageGLES2::texture_debug_usage(List<VS::TextureInfo> *r_info) { + List<RID> textures; + texture_owner.get_owned_list(&textures); + + for (List<RID>::Element *E = textures.front(); E; E = E->next()) { + + Texture *t = texture_owner.getornull(E->get()); + if (!t) + continue; + VS::TextureInfo tinfo; + tinfo.path = t->path; + tinfo.format = t->format; + tinfo.size.x = t->alloc_width; + tinfo.size.y = t->alloc_height; + tinfo.bytes = t->total_data_size; + r_info->push_back(tinfo); + } +} + +void RasterizerStorageGLES2::texture_set_shrink_all_x2_on_set_data(bool p_enable) { + config.shrink_textures_x2 = p_enable; +} + +void RasterizerStorageGLES2::textures_keep_original(bool p_enable) { + config.keep_original_textures = p_enable; +} + +void RasterizerStorageGLES2::texture_set_proxy(RID p_texture, RID p_proxy) { + Texture *texture = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!texture); + + if (texture->proxy) { + texture->proxy->proxy_owners.erase(texture); + texture->proxy = NULL; + } + + if (p_proxy.is_valid()) { + Texture *proxy = texture_owner.get(p_proxy); + ERR_FAIL_COND(!proxy); + ERR_FAIL_COND(proxy == texture); + proxy->proxy_owners.insert(texture); + texture->proxy = proxy; + } +} + +void RasterizerStorageGLES2::texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) { + // TODO +} + +void RasterizerStorageGLES2::texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) { + // TODO +} + +void RasterizerStorageGLES2::texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) { + // TODO +} + +RID RasterizerStorageGLES2::texture_create_radiance_cubemap(RID p_source, int p_resolution) const { + // TODO + return RID(); +} + +RID RasterizerStorageGLES2::sky_create() { + return RID(); +} + +void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size) { +} + +/* SHADER API */ + +RID RasterizerStorageGLES2::shader_create() { + + Shader *shader = memnew(Shader); + shader->mode = VS::SHADER_SPATIAL; + shader->shader = &scene->state.scene_shader; + RID rid = shader_owner.make_rid(shader); + _shader_make_dirty(shader); + shader->self = rid; + + return rid; +} + +void RasterizerStorageGLES2::_shader_make_dirty(Shader *p_shader) { + if (p_shader->dirty_list.in_list()) + return; + + _shader_dirty_list.add(&p_shader->dirty_list); +} + +void RasterizerStorageGLES2::shader_set_code(RID p_shader, const String &p_code) { + + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND(!shader); + + shader->code = p_code; + + String mode_string = ShaderLanguage::get_shader_type(p_code); + VS::ShaderMode mode; + + if (mode_string == "canvas_item") + mode = VS::SHADER_CANVAS_ITEM; + else if (mode_string == "particles") + mode = VS::SHADER_PARTICLES; + else + mode = VS::SHADER_SPATIAL; + + if (shader->custom_code_id && mode != shader->mode) { + shader->shader->free_custom_shader(shader->custom_code_id); + shader->custom_code_id = 0; + } + + shader->mode = mode; + + // TODO handle all shader types + if (mode == VS::SHADER_CANVAS_ITEM) { + shader->shader = &canvas->state.canvas_shader; + + } else { + return; + } + + if (shader->custom_code_id == 0) { + shader->custom_code_id = shader->shader->create_custom_shader(); + } + + _shader_make_dirty(shader); +} + +String RasterizerStorageGLES2::shader_get_code(RID p_shader) const { + + const Shader *shader = shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader, ""); + + return shader->code; +} + +void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { + + _shader_dirty_list.remove(&p_shader->dirty_list); + + p_shader->valid = false; + + p_shader->uniforms.clear(); + + ShaderCompilerGLES2::GeneratedCode gen_code; + ShaderCompilerGLES2::IdentifierActions *actions = NULL; + + switch (p_shader->mode) { + + // TODO + + case VS::SHADER_CANVAS_ITEM: { + + p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX; + + p_shader->canvas_item.uses_screen_texture = false; + p_shader->canvas_item.uses_screen_uv = false; + p_shader->canvas_item.uses_time = false; + + shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD); + shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX); + shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB); + shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL); + shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA); + + // shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED); + // shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); + + shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv; + shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv; + shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture; + shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time; + + actions = &shaders.actions_canvas; + actions->uniforms = &p_shader->uniforms; + } break; + + default: { + return; + } break; + } + + Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code); + + ERR_FAIL_COND(err != OK); + + p_shader->shader->set_custom_shader_code(p_shader->custom_code_id, gen_code.vertex, gen_code.vertex_global, gen_code.fragment, gen_code.light, gen_code.fragment_global, gen_code.uniforms, gen_code.texture_uniforms, gen_code.custom_defines); + + p_shader->texture_count = gen_code.texture_uniforms.size(); + p_shader->texture_hints = gen_code.texture_hints; + + p_shader->uses_vertex_time = gen_code.uses_vertex_time; + p_shader->uses_fragment_time = gen_code.uses_fragment_time; + + for (SelfList<Material> *E = p_shader->materials.first(); E; E = E->next()) { + _material_make_dirty(E->self()); + } + + p_shader->valid = true; + p_shader->version++; +} + +void RasterizerStorageGLES2::update_dirty_shaders() { + while (_shader_dirty_list.first()) { + _update_shader(_shader_dirty_list.first()->self()); + } +} + +void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { + + Shader *shader = shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + + if (shader->dirty_list.in_list()) { + _update_shader(shader); + } + + Map<int, StringName> order; + + for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { + + if (E->get().texture_order >= 0) { + order[E->get().texture_order + 100000] = E->key(); + } else { + order[E->get().order] = E->key(); + } + } + + for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) { + + PropertyInfo pi; + ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[E->get()]; + + pi.name = E->get(); + + switch (u.type) { + case ShaderLanguage::TYPE_VOID: { + pi.type = Variant::NIL; + } break; + + case ShaderLanguage::TYPE_BOOL: { + pi.type = Variant::BOOL; + } break; + + // bool vectors + case ShaderLanguage::TYPE_BVEC2: { + pi.type = Variant::INT; + pi.hint = PROPERTY_HINT_FLAGS; + pi.hint_string = "x,y"; + } break; + case ShaderLanguage::TYPE_BVEC3: { + pi.type = Variant::INT; + pi.hint = PROPERTY_HINT_FLAGS; + pi.hint_string = "x,y,z"; + } break; + case ShaderLanguage::TYPE_BVEC4: { + pi.type = Variant::INT; + pi.hint = PROPERTY_HINT_FLAGS; + pi.hint_string = "x,y,z,w"; + } break; + + // int stuff + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_INT: { + pi.type = Variant::INT; + + if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { + pi.hint = PROPERTY_HINT_RANGE; + pi.hint_string = rtos(u.hint_range[0]) + "," + rtos(u.hint_range[1]); + } + } break; + + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC4: { + pi.type = Variant::POOL_INT_ARRAY; + } break; + + case ShaderLanguage::TYPE_VEC2: { + pi.type = Variant::VECTOR2; + } break; + case ShaderLanguage::TYPE_VEC3: { + pi.type = Variant::VECTOR3; + } break; + + case ShaderLanguage::TYPE_VEC4: { + if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + pi.type = Variant::COLOR; + } else { + pi.type = Variant::PLANE; + } + } break; + + case ShaderLanguage::TYPE_MAT2: { + pi.type = Variant::TRANSFORM2D; + } break; + + case ShaderLanguage::TYPE_MAT3: { + pi.type = Variant::BASIS; + } break; + + case ShaderLanguage::TYPE_MAT4: { + pi.type = Variant::TRANSFORM; + } break; + + case ShaderLanguage::TYPE_SAMPLER2D: + case ShaderLanguage::TYPE_ISAMPLER2D: + case ShaderLanguage::TYPE_USAMPLER2D: { + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Texture"; + } break; + + case ShaderLanguage::TYPE_SAMPLERCUBE: { + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "CubeMap"; + } break; + } + + p_param_list->push_back(pi); + } +} + +void RasterizerStorageGLES2::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { + + Shader *shader = shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); + + if (p_texture.is_valid()) { + shader->default_textures[p_name] = p_texture; + } else { + shader->default_textures.erase(p_name); + } + + _shader_make_dirty(shader); +} + +RID RasterizerStorageGLES2::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { + + const Shader *shader = shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader, RID()); + + const Map<StringName, RID>::Element *E = shader->default_textures.find(p_name); + + if (!E) { + return RID(); + } + + return E->get(); +} + +/* COMMON MATERIAL API */ + +void RasterizerStorageGLES2::_material_make_dirty(Material *p_material) const { + + if (p_material->dirty_list.in_list()) + return; + + _material_dirty_list.add(&p_material->dirty_list); +} + +RID RasterizerStorageGLES2::material_create() { + + Material *material = memnew(Material); + + return material_owner.make_rid(material); +} + +void RasterizerStorageGLES2::material_set_shader(RID p_material, RID p_shader) { + + Material *material = material_owner.get(p_material); + ERR_FAIL_COND(!material); + + Shader *shader = shader_owner.getornull(p_shader); + + if (material->shader) { + // if a shader is present, remove the old shader + material->shader->materials.remove(&material->list); + } + + material->shader = shader; + + if (shader) { + shader->materials.add(&material->list); + } + + _material_make_dirty(material); +} + +RID RasterizerStorageGLES2::material_get_shader(RID p_material) const { + + const Material *material = material_owner.get(p_material); + ERR_FAIL_COND_V(!material, RID()); + + if (material->shader) { + return material->shader->self; + } + + return RID(); +} + +void RasterizerStorageGLES2::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { + + Material *material = material_owner.get(p_material); + ERR_FAIL_COND(!material); + + if (p_value.get_type() == Variant::NIL) { + material->params.erase(p_param); + } else { + material->params[p_param] = p_value; + } + + _material_make_dirty(material); +} + +Variant RasterizerStorageGLES2::material_get_param(RID p_material, const StringName &p_param) const { + + const Material *material = material_owner.get(p_material); + ERR_FAIL_COND_V(!material, RID()); + + if (material->params.has(p_param)) { + return material->params[p_param]; + } + + return Variant(); +} + +void RasterizerStorageGLES2::material_set_line_width(RID p_material, float p_width) { +} + +void RasterizerStorageGLES2::material_set_next_pass(RID p_material, RID p_next_material) { +} + +bool RasterizerStorageGLES2::material_is_animated(RID p_material) { + return false; +} + +bool RasterizerStorageGLES2::material_casts_shadows(RID p_material) { + return false; +} + +void RasterizerStorageGLES2::material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) { +} + +void RasterizerStorageGLES2::material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) { +} + +void RasterizerStorageGLES2::material_set_render_priority(RID p_material, int priority) { +} + +void RasterizerStorageGLES2::update_dirty_materials() { +} + +/* MESH API */ + +RID RasterizerStorageGLES2::mesh_create() { + return RID(); +} + +void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) { +} + +void RasterizerStorageGLES2::mesh_set_blend_shape_count(RID p_mesh, int p_amount) { +} + +int RasterizerStorageGLES2::mesh_get_blend_shape_count(RID p_mesh) const { + return 0; +} + +void RasterizerStorageGLES2::mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) { +} + +VS::BlendShapeMode RasterizerStorageGLES2::mesh_get_blend_shape_mode(RID p_mesh) const { + return VS::BLEND_SHAPE_MODE_NORMALIZED; +} + +void RasterizerStorageGLES2::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) { +} + +void RasterizerStorageGLES2::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { +} + +RID RasterizerStorageGLES2::mesh_surface_get_material(RID p_mesh, int p_surface) const { + return RID(); +} + +int RasterizerStorageGLES2::mesh_surface_get_array_len(RID p_mesh, int p_surface) const { + return 0; +} + +int RasterizerStorageGLES2::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const { + return 0; +} + +PoolVector<uint8_t> RasterizerStorageGLES2::mesh_surface_get_array(RID p_mesh, int p_surface) const { + return PoolVector<uint8_t>(); +} + +PoolVector<uint8_t> RasterizerStorageGLES2::mesh_surface_get_index_array(RID p_mesh, int p_surface) const { + return PoolVector<uint8_t>(); +} + +uint32_t RasterizerStorageGLES2::mesh_surface_get_format(RID p_mesh, int p_surface) const { + return 0; +} + +VS::PrimitiveType RasterizerStorageGLES2::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { + return VS::PRIMITIVE_TRIANGLES; +} + +AABB RasterizerStorageGLES2::mesh_surface_get_aabb(RID p_mesh, int p_surface) const { + return AABB(); +} + +Vector<PoolVector<uint8_t> > RasterizerStorageGLES2::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const { + return Vector<PoolVector<uint8_t> >(); +} +Vector<AABB> RasterizerStorageGLES2::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const { + return Vector<AABB>(); +} + +void RasterizerStorageGLES2::mesh_remove_surface(RID p_mesh, int p_surface) { +} + +int RasterizerStorageGLES2::mesh_get_surface_count(RID p_mesh) const { + return 0; +} + +void RasterizerStorageGLES2::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { +} + +AABB RasterizerStorageGLES2::mesh_get_custom_aabb(RID p_mesh) const { + return AABB(); +} + +AABB RasterizerStorageGLES2::mesh_get_aabb(RID p_mesh, RID p_skeleton) const { + return AABB(); +} +void RasterizerStorageGLES2::mesh_clear(RID p_mesh) { +} + +/* MULTIMESH API */ + +RID RasterizerStorageGLES2::multimesh_create() { + return RID(); +} + +void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format) { +} + +int RasterizerStorageGLES2::multimesh_get_instance_count(RID p_multimesh) const { + return 0; +} + +void RasterizerStorageGLES2::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { +} + +void RasterizerStorageGLES2::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) { +} + +void RasterizerStorageGLES2::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { +} + +void RasterizerStorageGLES2::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { +} + +RID RasterizerStorageGLES2::multimesh_get_mesh(RID p_multimesh) const { + return RID(); +} + +Transform RasterizerStorageGLES2::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { + return Transform(); +} + +Transform2D RasterizerStorageGLES2::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { + return Transform2D(); +} + +Color RasterizerStorageGLES2::multimesh_instance_get_color(RID p_multimesh, int p_index) const { + return Color(); +} + +void RasterizerStorageGLES2::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { +} + +int RasterizerStorageGLES2::multimesh_get_visible_instances(RID p_multimesh) const { + return 0; +} + +AABB RasterizerStorageGLES2::multimesh_get_aabb(RID p_multimesh) const { + + return AABB(); +} + +void RasterizerStorageGLES2::update_dirty_multimeshes() { +} + +/* IMMEDIATE API */ + +RID RasterizerStorageGLES2::immediate_create() { + return RID(); +} + +void RasterizerStorageGLES2::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture) { +} + +void RasterizerStorageGLES2::immediate_vertex(RID p_immediate, const Vector3 &p_vertex) { +} + +void RasterizerStorageGLES2::immediate_normal(RID p_immediate, const Vector3 &p_normal) { +} + +void RasterizerStorageGLES2::immediate_tangent(RID p_immediate, const Plane &p_tangent) { +} + +void RasterizerStorageGLES2::immediate_color(RID p_immediate, const Color &p_color) { +} + +void RasterizerStorageGLES2::immediate_uv(RID p_immediate, const Vector2 &tex_uv) { +} + +void RasterizerStorageGLES2::immediate_uv2(RID p_immediate, const Vector2 &tex_uv) { +} + +void RasterizerStorageGLES2::immediate_end(RID p_immediate) { +} + +void RasterizerStorageGLES2::immediate_clear(RID p_immediate) { +} + +AABB RasterizerStorageGLES2::immediate_get_aabb(RID p_immediate) const { + return AABB(); +} + +void RasterizerStorageGLES2::immediate_set_material(RID p_immediate, RID p_material) { +} + +RID RasterizerStorageGLES2::immediate_get_material(RID p_immediate) const { + return RID(); +} + +/* SKELETON API */ + +RID RasterizerStorageGLES2::skeleton_create() { + return RID(); +} + +void RasterizerStorageGLES2::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) { +} + +int RasterizerStorageGLES2::skeleton_get_bone_count(RID p_skeleton) const { + return 0; +} + +void RasterizerStorageGLES2::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) { +} + +Transform RasterizerStorageGLES2::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { + return Transform(); +} +void RasterizerStorageGLES2::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { +} + +Transform2D RasterizerStorageGLES2::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { + return Transform2D(); +} + +void RasterizerStorageGLES2::update_dirty_skeletons() { +} + +/* Light API */ + +RID RasterizerStorageGLES2::light_create(VS::LightType p_type) { + return RID(); +} + +void RasterizerStorageGLES2::light_set_color(RID p_light, const Color &p_color) { +} + +void RasterizerStorageGLES2::light_set_param(RID p_light, VS::LightParam p_param, float p_value) { +} + +void RasterizerStorageGLES2::light_set_shadow(RID p_light, bool p_enabled) { +} + +void RasterizerStorageGLES2::light_set_shadow_color(RID p_light, const Color &p_color) { +} + +void RasterizerStorageGLES2::light_set_projector(RID p_light, RID p_texture) { +} + +void RasterizerStorageGLES2::light_set_negative(RID p_light, bool p_enable) { +} + +void RasterizerStorageGLES2::light_set_cull_mask(RID p_light, uint32_t p_mask) { +} + +void RasterizerStorageGLES2::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { +} + +void RasterizerStorageGLES2::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) { +} + +VS::LightOmniShadowMode RasterizerStorageGLES2::light_omni_get_shadow_mode(RID p_light) { + return VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; +} + +void RasterizerStorageGLES2::light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) { +} + +void RasterizerStorageGLES2::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) { +} + +void RasterizerStorageGLES2::light_directional_set_blend_splits(RID p_light, bool p_enable) { +} + +bool RasterizerStorageGLES2::light_directional_get_blend_splits(RID p_light) const { + return false; +} + +VS::LightDirectionalShadowMode RasterizerStorageGLES2::light_directional_get_shadow_mode(RID p_light) { + return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; +} + +void RasterizerStorageGLES2::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) { +} + +VS::LightDirectionalShadowDepthRangeMode RasterizerStorageGLES2::light_directional_get_shadow_depth_range_mode(RID p_light) const { + return VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; +} + +VS::LightType RasterizerStorageGLES2::light_get_type(RID p_light) const { + return VS::LIGHT_DIRECTIONAL; +} + +float RasterizerStorageGLES2::light_get_param(RID p_light, VS::LightParam p_param) { + + return VS::LIGHT_DIRECTIONAL; +} + +Color RasterizerStorageGLES2::light_get_color(RID p_light) { + return Color(); +} + +bool RasterizerStorageGLES2::light_has_shadow(RID p_light) const { + + return VS::LIGHT_DIRECTIONAL; +} + +uint64_t RasterizerStorageGLES2::light_get_version(RID p_light) const { + return 0; +} + +AABB RasterizerStorageGLES2::light_get_aabb(RID p_light) const { + return AABB(); +} + +/* PROBE API */ + +RID RasterizerStorageGLES2::reflection_probe_create() { + return RID(); +} + +void RasterizerStorageGLES2::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) { +} + +void RasterizerStorageGLES2::reflection_probe_set_intensity(RID p_probe, float p_intensity) { +} + +void RasterizerStorageGLES2::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) { +} + +void RasterizerStorageGLES2::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) { +} + +void RasterizerStorageGLES2::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) { +} + +void RasterizerStorageGLES2::reflection_probe_set_max_distance(RID p_probe, float p_distance) { +} + +void RasterizerStorageGLES2::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { +} + +void RasterizerStorageGLES2::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { +} + +void RasterizerStorageGLES2::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { +} + +void RasterizerStorageGLES2::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { +} + +void RasterizerStorageGLES2::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) { +} + +void RasterizerStorageGLES2::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { +} + +AABB RasterizerStorageGLES2::reflection_probe_get_aabb(RID p_probe) const { + return AABB(); +} +VS::ReflectionProbeUpdateMode RasterizerStorageGLES2::reflection_probe_get_update_mode(RID p_probe) const { + return VS::REFLECTION_PROBE_UPDATE_ALWAYS; +} + +uint32_t RasterizerStorageGLES2::reflection_probe_get_cull_mask(RID p_probe) const { + return 0; +} + +Vector3 RasterizerStorageGLES2::reflection_probe_get_extents(RID p_probe) const { + return Vector3(); +} +Vector3 RasterizerStorageGLES2::reflection_probe_get_origin_offset(RID p_probe) const { + return Vector3(); +} + +bool RasterizerStorageGLES2::reflection_probe_renders_shadows(RID p_probe) const { + return false; +} + +float RasterizerStorageGLES2::reflection_probe_get_origin_max_distance(RID p_probe) const { + return 0; +} + +RID RasterizerStorageGLES2::gi_probe_create() { + return RID(); +} + +void RasterizerStorageGLES2::gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) { +} + +AABB RasterizerStorageGLES2::gi_probe_get_bounds(RID p_probe) const { + return AABB(); +} + +void RasterizerStorageGLES2::gi_probe_set_cell_size(RID p_probe, float p_size) { +} + +float RasterizerStorageGLES2::gi_probe_get_cell_size(RID p_probe) const { + return 0.0; +} + +void RasterizerStorageGLES2::gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) { +} + +Transform RasterizerStorageGLES2::gi_probe_get_to_cell_xform(RID p_probe) const { + return Transform(); +} + +void RasterizerStorageGLES2::gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data) { +} + +PoolVector<int> RasterizerStorageGLES2::gi_probe_get_dynamic_data(RID p_probe) const { + return PoolVector<int>(); +} + +void RasterizerStorageGLES2::gi_probe_set_dynamic_range(RID p_probe, int p_range) { +} + +int RasterizerStorageGLES2::gi_probe_get_dynamic_range(RID p_probe) const { + return 0; +} + +void RasterizerStorageGLES2::gi_probe_set_energy(RID p_probe, float p_range) { +} + +void RasterizerStorageGLES2::gi_probe_set_bias(RID p_probe, float p_range) { +} + +void RasterizerStorageGLES2::gi_probe_set_normal_bias(RID p_probe, float p_range) { +} + +void RasterizerStorageGLES2::gi_probe_set_propagation(RID p_probe, float p_range) { +} + +void RasterizerStorageGLES2::gi_probe_set_interior(RID p_probe, bool p_enable) { +} + +bool RasterizerStorageGLES2::gi_probe_is_interior(RID p_probe) const { + return false; +} + +void RasterizerStorageGLES2::gi_probe_set_compress(RID p_probe, bool p_enable) { +} + +bool RasterizerStorageGLES2::gi_probe_is_compressed(RID p_probe) const { + return false; +} +float RasterizerStorageGLES2::gi_probe_get_energy(RID p_probe) const { + return 0; +} + +float RasterizerStorageGLES2::gi_probe_get_bias(RID p_probe) const { + return 0; +} + +float RasterizerStorageGLES2::gi_probe_get_normal_bias(RID p_probe) const { + return 0; +} + +float RasterizerStorageGLES2::gi_probe_get_propagation(RID p_probe) const { + return 0; +} + +uint32_t RasterizerStorageGLES2::gi_probe_get_version(RID p_probe) { + return 0; +} + +RasterizerStorage::GIProbeCompression RasterizerStorageGLES2::gi_probe_get_dynamic_data_get_preferred_compression() const { + return GI_PROBE_UNCOMPRESSED; +} + +RID RasterizerStorageGLES2::gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) { + return RID(); +} + +void RasterizerStorageGLES2::gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) { +} + +/////// + +RID RasterizerStorageGLES2::lightmap_capture_create() { + return RID(); +} + +void RasterizerStorageGLES2::lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) { +} + +AABB RasterizerStorageGLES2::lightmap_capture_get_bounds(RID p_capture) const { + return AABB(); +} + +void RasterizerStorageGLES2::lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree) { +} + +PoolVector<uint8_t> RasterizerStorageGLES2::lightmap_capture_get_octree(RID p_capture) const { + return PoolVector<uint8_t>(); +} + +void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) { +} + +Transform RasterizerStorageGLES2::lightmap_capture_get_octree_cell_transform(RID p_capture) const { + return Transform(); +} + +void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) { +} + +int RasterizerStorageGLES2::lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { + return 0; +} + +void RasterizerStorageGLES2::lightmap_capture_set_energy(RID p_capture, float p_energy) { +} + +float RasterizerStorageGLES2::lightmap_capture_get_energy(RID p_capture) const { + return 0.0; +} + +const PoolVector<RasterizerStorage::LightmapCaptureOctree> *RasterizerStorageGLES2::lightmap_capture_get_octree_ptr(RID p_capture) const { + return NULL; +} + +/////// + +RID RasterizerStorageGLES2::particles_create() { + return RID(); +} + +void RasterizerStorageGLES2::particles_set_emitting(RID p_particles, bool p_emitting) { +} + +bool RasterizerStorageGLES2::particles_get_emitting(RID p_particles) { + return false; +} + +void RasterizerStorageGLES2::particles_set_amount(RID p_particles, int p_amount) { +} + +void RasterizerStorageGLES2::particles_set_lifetime(RID p_particles, float p_lifetime) { +} + +void RasterizerStorageGLES2::particles_set_one_shot(RID p_particles, bool p_one_shot) { +} + +void RasterizerStorageGLES2::particles_set_pre_process_time(RID p_particles, float p_time) { +} + +void RasterizerStorageGLES2::particles_set_explosiveness_ratio(RID p_particles, float p_ratio) { +} + +void RasterizerStorageGLES2::particles_set_randomness_ratio(RID p_particles, float p_ratio) { +} + +void RasterizerStorageGLES2::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { +} + +void RasterizerStorageGLES2::particles_set_speed_scale(RID p_particles, float p_scale) { +} + +void RasterizerStorageGLES2::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { +} + +void RasterizerStorageGLES2::particles_set_fixed_fps(RID p_particles, int p_fps) { +} + +void RasterizerStorageGLES2::particles_set_fractional_delta(RID p_particles, bool p_enable) { +} + +void RasterizerStorageGLES2::particles_set_process_material(RID p_particles, RID p_material) { +} + +void RasterizerStorageGLES2::particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) { +} + +void RasterizerStorageGLES2::particles_set_draw_passes(RID p_particles, int p_passes) { +} + +void RasterizerStorageGLES2::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { +} + +void RasterizerStorageGLES2::particles_restart(RID p_particles) { +} + +void RasterizerStorageGLES2::particles_request_process(RID p_particles) { +} + +AABB RasterizerStorageGLES2::particles_get_current_aabb(RID p_particles) { + return AABB(); +} + +AABB RasterizerStorageGLES2::particles_get_aabb(RID p_particles) const { + return AABB(); +} + +void RasterizerStorageGLES2::particles_set_emission_transform(RID p_particles, const Transform &p_transform) { +} + +int RasterizerStorageGLES2::particles_get_draw_passes(RID p_particles) const { + return 0; +} + +RID RasterizerStorageGLES2::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { + return RID(); +} + +void RasterizerStorageGLES2::update_particles() { +} + +//////// + +void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { +} + +void RasterizerStorageGLES2::instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { +} + +void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) { +} + +void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) { +} + +/* RENDER TARGET */ + +void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { + + if (rt->width <= 0 || rt->height <= 0) + return; + + Texture *texture = texture_owner.getornull(rt->texture); + ERR_FAIL_COND(!texture); + + // create fbo + + glGenFramebuffers(1, &rt->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); + + // color + + 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 (texture->flags & VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + + 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); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); + + // depth + + glGenRenderbuffers(1, &rt->depth); + glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, rt->width, rt->height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + + glDeleteRenderbuffers(1, &rt->fbo); + glDeleteTextures(1, &rt->depth); + glDeleteTextures(1, &rt->color); + rt->fbo = 0; + rt->width = 0; + rt->height = 0; + rt->color = 0; + rt->depth = 0; + texture->tex_id = 0; + texture->active = false; + WARN_PRINT("Could not create framebuffer!!"); + return; + } + + texture->format = Image::FORMAT_RGBA8; + texture->gl_format_cache = GL_RGBA; + texture->gl_type_cache = GL_UNSIGNED_BYTE; + texture->gl_internal_format_cache = GL_RGBA; + texture->tex_id = rt->color; + texture->width = rt->width; + texture->alloc_width = rt->width; + texture->height = rt->height; + texture->alloc_height = rt->height; + texture->active = true; + + texture_set_flags(rt->texture, texture->flags); + + // copy texscreen buffers + { + 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); + + glGenFramebuffers(1, &rt->copy_screen_effect.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); + } + } + + glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); +} + +void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) { + + if (rt->fbo) { + glDeleteFramebuffers(1, &rt->fbo); + glDeleteTextures(1, &rt->color); + rt->fbo = 0; + } + + if (rt->depth) { + glDeleteRenderbuffers(1, &rt->depth); + rt->depth = 0; + } + + Texture *tex = texture_owner.get(rt->texture); + tex->alloc_height = 0; + tex->alloc_width = 0; + tex->width = 0; + 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; + + glDeleteTextures(1, &rt->copy_screen_effect.color); + rt->copy_screen_effect.color = 0; + } +} + +RID RasterizerStorageGLES2::render_target_create() { + + RenderTarget *rt = memnew(RenderTarget); + + Texture *t = memnew(Texture); + + t->flags = 0; + t->width = 0; + t->height = 0; + t->alloc_height = 0; + t->alloc_width = 0; + t->format = Image::FORMAT_R8; + t->target = GL_TEXTURE_2D; + t->gl_format_cache = 0; + t->gl_internal_format_cache = 0; + t->gl_type_cache = 0; + t->data_size = 0; + t->total_data_size = 0; + t->ignore_mipmaps = false; + t->mipmaps = 1; + t->active = true; + t->tex_id = 0; + t->render_target = rt; + + rt->texture = texture_owner.make_rid(t); + + return render_target_owner.make_rid(rt); +} + +void RasterizerStorageGLES2::render_target_set_size(RID p_render_target, int p_width, int p_height) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + if (p_width == rt->width && p_height == rt->height) + return; + + _render_target_clear(rt); + + rt->width = p_width; + rt->height = p_height; + + _render_target_allocate(rt); +} + +RID RasterizerStorageGLES2::render_target_get_texture(RID p_render_target) const { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->texture; +} + +void RasterizerStorageGLES2::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + rt->flags[p_flag] = p_value; + + switch (p_flag) { + case RENDER_TARGET_HDR: + case RENDER_TARGET_NO_3D: + case RENDER_TARGET_NO_SAMPLING: + case RENDER_TARGET_NO_3D_EFFECTS: { + //must reset for these formats + _render_target_clear(rt); + _render_target_allocate(rt); + + } break; + default: {} + } +} + +bool RasterizerStorageGLES2::render_target_was_used(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, false); + + return rt->used_in_frame; +} + +void RasterizerStorageGLES2::render_target_clear_used(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + rt->used_in_frame = false; +} + +void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, VS::ViewportMSAA p_msaa) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + if (rt->msaa == p_msaa) + return; + + _render_target_clear(rt); + rt->msaa = p_msaa; + _render_target_allocate(rt); +} + +/* CANVAS SHADOW */ + +RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) { + return RID(); +} + +/* LIGHT SHADOW MAPPING */ + +RID RasterizerStorageGLES2::canvas_light_occluder_create() { + return RID(); +} + +void RasterizerStorageGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) { +} + +VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const { + return VS::INSTANCE_NONE; +} + +bool RasterizerStorageGLES2::free(RID p_rid) { + return false; +} + +bool RasterizerStorageGLES2::has_os_feature(const String &p_feature) const { + return false; +} + +//////////////////////////////////////////// + +void RasterizerStorageGLES2::set_debug_generate_wireframes(bool p_generate) { +} + +void RasterizerStorageGLES2::render_info_begin_capture() { +} + +void RasterizerStorageGLES2::render_info_end_capture() { +} + +int RasterizerStorageGLES2::get_captured_render_info(VS::RenderInfo p_info) { + + return get_render_info(p_info); +} + +int RasterizerStorageGLES2::get_render_info(VS::RenderInfo p_info) { + return 0; +} + +void RasterizerStorageGLES2::initialize() { + RasterizerStorageGLES2::system_fbo = 0; + + { + const char *gl_extensions = (const char *)glGetString(GL_EXTENSIONS); + Vector<String> strings = String(gl_extensions).split(" ", false); + for (int i = 0; i < strings.size(); i++) { + config.extensions.insert(strings[i]); + } + } + + frame.count = 0; + frame.prev_tick = 0; + frame.delta = 0; + frame.current_rt = NULL; + frame.clear_request = false; + // config.keep_original_textures = false; + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size); + + shaders.copy.init(); + + { + //default textures + + glGenTextures(1, &resources.white_tex); + unsigned char whitetexdata[8 * 8 * 3]; + for (int i = 0; i < 8 * 8 * 3; i++) { + whitetexdata[i] = 255; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, resources.white_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenTextures(1, &resources.black_tex); + unsigned char blacktexdata[8 * 8 * 3]; + for (int i = 0; i < 8 * 8 * 3; i++) { + blacktexdata[i] = 0; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, resources.black_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, blacktexdata); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenTextures(1, &resources.normal_tex); + unsigned char normaltexdata[8 * 8 * 3]; + for (int i = 0; i < 8 * 8 * 3; i += 3) { + normaltexdata[i + 0] = 128; + normaltexdata[i + 1] = 128; + normaltexdata[i + 2] = 255; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, resources.normal_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, normaltexdata); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenTextures(1, &resources.aniso_tex); + unsigned char anisotexdata[8 * 8 * 3]; + for (int i = 0; i < 8 * 8 * 3; i += 3) { + anisotexdata[i + 0] = 255; + anisotexdata[i + 1] = 128; + anisotexdata[i + 2] = 0; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, resources.aniso_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + } +} + +void RasterizerStorageGLES2::finalize() { +} + +void RasterizerStorageGLES2::update_dirty_resources() { + update_dirty_shaders(); + update_dirty_materials(); +} + +RasterizerStorageGLES2::RasterizerStorageGLES2() { + RasterizerStorageGLES2::system_fbo = 0; +} diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h new file mode 100644 index 0000000000..9f8d8d100b --- /dev/null +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -0,0 +1,838 @@ +/*************************************************************************/ +/* rasterizer_storage_gles2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 RASTERIZERSTORAGEGLES2_H +#define RASTERIZERSTORAGEGLES2_H + +#include "self_list.h" +#include "servers/visual/rasterizer.h" +#include "servers/visual/shader_language.h" +#include "shader_compiler_gles2.h" +#include "shader_gles2.h" + +#include "shaders/copy.glsl.gen.h" +/* +#include "shaders/blend_shape.glsl.gen.h" +#include "shaders/canvas.glsl.gen.h" +#include "shaders/copy.glsl.gen.h" +#include "shaders/cubemap_filter.glsl.gen.h" +#include "shaders/particles.glsl.gen.h" +*/ + +class RasterizerCanvasGLES2; +class RasterizerSceneGLES2; + +class RasterizerStorageGLES2 : public RasterizerStorage { +public: + RasterizerCanvasGLES2 *canvas; + RasterizerSceneGLES2 *scene; + + static GLuint system_fbo; + + struct Config { + + bool shrink_textures_x2; + bool use_fast_texture_filter; + // bool use_anisotropic_filter; + + bool hdr_supported; + + bool use_rgba_2d_shadows; + + // float anisotropic_level; + + int max_texture_image_units; + int max_texture_size; + + bool generate_wireframes; + + bool use_texture_array_environment; + + Set<String> extensions; + + bool keep_original_textures; + + bool no_depth_prepass; + bool force_vertex_shading; + } config; + + struct Resources { + + GLuint white_tex; + GLuint black_tex; + GLuint normal_tex; + GLuint aniso_tex; + + GLuint quadie; + GLuint quadie_array; + + } resources; + + mutable struct Shaders { + + ShaderCompilerGLES2 compiler; + + CopyShaderGLES2 copy; + + ShaderCompilerGLES2::IdentifierActions actions_canvas; + ShaderCompilerGLES2::IdentifierActions actions_scene; + ShaderCompilerGLES2::IdentifierActions actions_particles; + + } shaders; + + struct Info { + + uint64_t texture_mem; + uint64_t vertex_mem; + + struct Render { + uint32_t object_count; + uint32_t draw_call_count; + uint32_t material_switch_count; + uint32_t surface_switch_count; + uint32_t shader_rebind_count; + uint32_t vertices_count; + + void reset() { + object_count = 0; + draw_call_count = 0; + material_switch_count = 0; + surface_switch_count = 0; + shader_rebind_count = 0; + vertices_count = 0; + } + } render, render_final, snap; + + Info() { + + texture_mem = 0; + vertex_mem = 0; + render.reset(); + render_final.reset(); + } + + } info; + + ///////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////DATA/////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////API//////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////// + + /* TEXTURE API */ + + struct RenderTarget; + + struct Texture : RID_Data { + + Texture *proxy; + Set<Texture *> proxy_owners; + + String path; + uint32_t flags; + int width, height; + int alloc_width, alloc_height; + Image::Format format; + + GLenum target; + GLenum gl_format_cache; + GLenum gl_internal_format_cache; + GLenum gl_type_cache; + + int data_size; + int total_data_size; + bool ignore_mipmaps; + + int mipmaps; + + bool active; + GLenum tex_id; + + uint16_t stored_cube_sides; + + RenderTarget *render_target; + + Ref<Image> images[6]; + + Texture() { + flags = 0; + width = 0; + height = 0; + alloc_width = 0; + alloc_height = 0; + format = Image::FORMAT_L8; + + target = 0; + + data_size = 0; + total_data_size = 0; + ignore_mipmaps = false; + + active = false; + + tex_id = 0; + + stored_cube_sides = 0; + + proxy = NULL; + + render_target = NULL; + } + + _ALWAYS_INLINE_ Texture *get_ptr() { + if (proxy) { + return proxy; //->get_ptr(); only one level of indirection, else not inlining possible. + } else { + return this; + } + } + + ~Texture() { + if (tex_id != 0) { + glDeleteTextures(1, &tex_id); + } + + for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) { + E->get()->proxy = NULL; + } + + if (proxy) { + proxy->proxy_owners.erase(this); + } + } + }; + + mutable RID_Owner<Texture> texture_owner; + + Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type); + + virtual RID texture_create(); + virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT); + virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT); + virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const; + virtual void texture_set_flags(RID p_texture, uint32_t p_flags); + virtual uint32_t texture_get_flags(RID p_texture) const; + virtual Image::Format texture_get_format(RID p_texture) const; + virtual uint32_t texture_get_texid(RID p_texture) const; + virtual uint32_t texture_get_width(RID p_texture) const; + virtual uint32_t texture_get_height(RID p_texture) const; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); + + virtual void texture_set_path(RID p_texture, const String &p_path); + virtual String texture_get_path(RID p_texture) const; + + virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); + + virtual void texture_debug_usage(List<VS::TextureInfo> *r_info); + + virtual RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const; + + virtual void textures_keep_original(bool p_enable); + + virtual void texture_set_proxy(RID p_texture, RID p_proxy); + + virtual void texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); + + /* SKY API */ + + virtual RID sky_create(); + virtual void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size); + + /* SHADER API */ + + struct Material; + + struct Shader : public RID_Data { + + RID self; + + VS::ShaderMode mode; + ShaderGLES2 *shader; + String code; + SelfList<Material>::List materials; + + Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + + uint32_t texture_count; + + uint32_t custom_code_id; + uint32_t version; + + SelfList<Shader> dirty_list; + + Map<StringName, RID> default_textures; + + Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints; + + bool valid; + + String path; + + struct CanvasItem { + + enum BlendMode { + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + BLEND_MODE_PMALPHA, + }; + + int blend_mode; + + /* + enum LightMode { + LIGHT_MODE_NORMAL, + LIGHT_MODE_UNSHADED, + LIGHT_MODE_LIGHT_ONLY + }; + + int light_mode; + */ + bool uses_screen_texture; + bool uses_screen_uv; + bool uses_time; + + } canvas_item; + + /* + struct Spatial { + + enum BlendMode { + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + }; + + int blend_mode; + + enum DepthDrawMode { + DEPTH_DRAW_OPAQUE, + DEPTH_DRAW_ALWAYS, + DEPTH_DRAW_NEVER, + DEPTH_DRAW_ALPHA_PREPASS, + }; + + int depth_draw_mode; + + enum CullMode { + CULL_MODE_FRONT, + CULL_MODE_BACK, + CULL_MODE_DISABLED, + }; + + int cull_mode; + + bool uses_alpha; + bool uses_alpha_scissor; + bool unshaded; + bool no_depth_test; + bool uses_vertex; + bool uses_discard; + bool uses_sss; + bool uses_screen_texture; + bool uses_time; + bool writes_modelview_or_projection; + bool uses_vertex_lighting; + bool uses_world_coordinates; + + } spatial; + + struct Particles { + + } particles; + */ + + bool uses_vertex_time; + bool uses_fragment_time; + + Shader() : + dirty_list(this) { + + shader = NULL; + valid = false; + custom_code_id = 0; + version = 1; + } + }; + + mutable RID_Owner<Shader> shader_owner; + mutable SelfList<Shader>::List _shader_dirty_list; + + void _shader_make_dirty(Shader *p_shader); + + virtual RID shader_create(); + + virtual void shader_set_code(RID p_shader, const String &p_code); + virtual String shader_get_code(RID p_shader) const; + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture); + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const; + + void _update_shader(Shader *p_shader) const; + void update_dirty_shaders(); + + /* COMMON MATERIAL API */ + + struct Material : public RID_Data { + + Shader *shader; + Map<StringName, Variant> params; + SelfList<Material> list; + SelfList<Material> dirty_list; + Vector<RID> textures; + float line_width; + int render_priority; + + RID next_pass; + + uint32_t index; + uint64_t last_pass; + + Map<Geometry *, int> geometry_owners; + Map<RasterizerScene::InstanceBase *, int> instance_owners; + + bool can_cast_shadow_cache; + bool is_animated_cache; + + Material() : + list(this), + dirty_list(this) { + can_cast_shadow_cache = false; + is_animated_cache = false; + shader = NULL; + line_width = 1.0; + last_pass = 0; + render_priority = 0; + } + }; + + mutable SelfList<Material>::List _material_dirty_list; + void _material_make_dirty(Material *p_material) const; + + mutable RID_Owner<Material> material_owner; + + virtual RID material_create(); + + virtual void material_set_shader(RID p_material, RID p_shader); + virtual RID material_get_shader(RID p_material) const; + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value); + virtual Variant material_get_param(RID p_material, const StringName &p_param) const; + + virtual void material_set_line_width(RID p_material, float p_width); + virtual void material_set_next_pass(RID p_material, RID p_next_material); + + virtual bool material_is_animated(RID p_material); + virtual bool material_casts_shadows(RID p_material); + + virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance); + virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance); + + virtual void material_set_render_priority(RID p_material, int priority); + + void update_dirty_materials(); + + /* MESH API */ + virtual RID mesh_create(); + + virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()); + + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount); + virtual int mesh_get_blend_shape_count(RID p_mesh) const; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode); + virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; + + virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data); + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material); + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; + + virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const; + virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const; + + virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const; + virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const; + + virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; + virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; + + virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const; + virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const; + virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const; + + virtual void mesh_remove_surface(RID p_mesh, int p_surface); + virtual int mesh_get_surface_count(RID p_mesh) const; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb); + virtual AABB mesh_get_custom_aabb(RID p_mesh) const; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const; + virtual void mesh_clear(RID p_mesh); + + /* MULTIMESH API */ + + virtual RID multimesh_create(); + + virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format); + virtual int multimesh_get_instance_count(RID p_multimesh) const; + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh); + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform); + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform); + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color); + + virtual RID multimesh_get_mesh(RID p_multimesh) const; + + virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const; + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const; + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible); + virtual int multimesh_get_visible_instances(RID p_multimesh) const; + + virtual AABB multimesh_get_aabb(RID p_multimesh) const; + + void update_dirty_multimeshes(); + + /* IMMEDIATE API */ + + virtual RID immediate_create(); + virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture = RID()); + virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex); + virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal); + virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent); + virtual void immediate_color(RID p_immediate, const Color &p_color); + virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv); + virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv); + virtual void immediate_end(RID p_immediate); + virtual void immediate_clear(RID p_immediate); + virtual void immediate_set_material(RID p_immediate, RID p_material); + virtual RID immediate_get_material(RID p_immediate) const; + virtual AABB immediate_get_aabb(RID p_immediate) const; + + /* SKELETON API */ + + void update_dirty_skeletons(); + + virtual RID skeleton_create(); + virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false); + virtual int skeleton_get_bone_count(RID p_skeleton) const; + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform); + virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; + + /* Light API */ + + virtual RID light_create(VS::LightType p_type); + + virtual void light_set_color(RID p_light, const Color &p_color); + virtual void light_set_param(RID p_light, VS::LightParam p_param, float p_value); + virtual void light_set_shadow(RID p_light, bool p_enabled); + virtual void light_set_shadow_color(RID p_light, const Color &p_color); + virtual void light_set_projector(RID p_light, RID p_texture); + virtual void light_set_negative(RID p_light, bool p_enable); + virtual void light_set_cull_mask(RID p_light, uint32_t p_mask); + virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled); + + virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode); + virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail); + + virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode); + virtual void light_directional_set_blend_splits(RID p_light, bool p_enable); + virtual bool light_directional_get_blend_splits(RID p_light) const; + + virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); + virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); + + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode); + virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const; + + virtual bool light_has_shadow(RID p_light) const; + + virtual VS::LightType light_get_type(RID p_light) const; + virtual float light_get_param(RID p_light, VS::LightParam p_param); + virtual Color light_get_color(RID p_light); + + virtual AABB light_get_aabb(RID p_light) const; + virtual uint64_t light_get_version(RID p_light) const; + + /* PROBE API */ + virtual RID reflection_probe_create(); + + virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode); + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity); + virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient); + virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy); + virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib); + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance); + virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents); + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset); + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable); + virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable); + virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable); + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers); + + virtual AABB reflection_probe_get_aabb(RID p_probe) const; + virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; + virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const; + + virtual Vector3 reflection_probe_get_extents(RID p_probe) const; + virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const; + virtual float reflection_probe_get_origin_max_distance(RID p_probe) const; + virtual bool reflection_probe_renders_shadows(RID p_probe) const; + + /* GI PROBE API */ + virtual RID gi_probe_create(); + + virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds); + virtual AABB gi_probe_get_bounds(RID p_probe) const; + + virtual void gi_probe_set_cell_size(RID p_probe, float p_size); + virtual float gi_probe_get_cell_size(RID p_probe) const; + + virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform); + virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const; + + virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector<int> &p_data); + virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const; + + virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range); + virtual int gi_probe_get_dynamic_range(RID p_probe) const; + + virtual void gi_probe_set_energy(RID p_probe, float p_range); + virtual float gi_probe_get_energy(RID p_probe) const; + + virtual void gi_probe_set_bias(RID p_probe, float p_range); + virtual float gi_probe_get_bias(RID p_probe) const; + + virtual void gi_probe_set_normal_bias(RID p_probe, float p_range); + virtual float gi_probe_get_normal_bias(RID p_probe) const; + + virtual void gi_probe_set_propagation(RID p_probe, float p_range); + virtual float gi_probe_get_propagation(RID p_probe) const; + + virtual void gi_probe_set_interior(RID p_probe, bool p_enable); + virtual bool gi_probe_is_interior(RID p_probe) const; + + virtual void gi_probe_set_compress(RID p_probe, bool p_enable); + virtual bool gi_probe_is_compressed(RID p_probe) const; + + virtual uint32_t gi_probe_get_version(RID p_probe); + + virtual GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const; + virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression); + virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data); + + /* LIGHTMAP */ + + virtual RID lightmap_capture_create(); + virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds); + virtual AABB lightmap_capture_get_bounds(RID p_capture) const; + virtual void lightmap_capture_set_octree(RID p_capture, const PoolVector<uint8_t> &p_octree); + virtual PoolVector<uint8_t> lightmap_capture_get_octree(RID p_capture) const; + virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform); + virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const; + virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv); + virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const; + virtual void lightmap_capture_set_energy(RID p_capture, float p_energy); + virtual float lightmap_capture_get_energy(RID p_capture) const; + virtual const PoolVector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const; + + /* PARTICLES */ + void update_particles(); + + virtual RID particles_create(); + + virtual void particles_set_emitting(RID p_particles, bool p_emitting); + virtual bool particles_get_emitting(RID p_particles); + + virtual void particles_set_amount(RID p_particles, int p_amount); + virtual void particles_set_lifetime(RID p_particles, float p_lifetime); + virtual void particles_set_one_shot(RID p_particles, bool p_one_shot); + virtual void particles_set_pre_process_time(RID p_particles, float p_time); + virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio); + virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio); + virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb); + virtual void particles_set_speed_scale(RID p_particles, float p_scale); + virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); + virtual void particles_set_process_material(RID p_particles, RID p_material); + virtual void particles_set_fixed_fps(RID p_particles, int p_fps); + virtual void particles_set_fractional_delta(RID p_particles, bool p_enable); + virtual void particles_restart(RID p_particles); + + virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order); + + virtual void particles_set_draw_passes(RID p_particles, int p_passes); + virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh); + + virtual void particles_request_process(RID p_particles); + virtual AABB particles_get_current_aabb(RID p_particles); + virtual AABB particles_get_aabb(RID p_particles) const; + + virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform); + + virtual int particles_get_draw_passes(RID p_particles) const; + virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const; + + /* INSTANCE */ + + virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); + virtual void instance_remove_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); + + virtual void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance); + virtual void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance); + + /* RENDER TARGET */ + + struct RenderTarget : public RID_Data { + GLuint fbo; + + GLuint color; + GLuint depth; + + // TODO post processing effects? + + // TODO HDR? + + // TODO this is hardcoded for texscreen copies for now + + struct Effect { + GLuint fbo; + int width; + int height; + + GLuint color; + + Effect() { + fbo = 0; + width = 0; + height = 0; + color = 0; + } + }; + + Effect copy_screen_effect; + + int width, height; + + bool flags[RENDER_TARGET_FLAG_MAX]; + + bool used_in_frame; + VS::ViewportMSAA msaa; + + RID texture; + + RenderTarget() { + fbo = 0; + + color = 0; + depth = 0; + + width = 0; + height = 0; + + for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { + flags[i] = false; + } + + used_in_frame = false; + + msaa = VS::VIEWPORT_MSAA_DISABLED; + } + }; + + mutable RID_Owner<RenderTarget> render_target_owner; + + void _render_target_clear(RenderTarget *rt); + void _render_target_allocate(RenderTarget *rt); + + virtual RID render_target_create(); + virtual void render_target_set_size(RID p_render_target, int p_width, int p_height); + virtual RID render_target_get_texture(RID p_render_target) const; + + virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value); + virtual bool render_target_was_used(RID p_render_target); + virtual void render_target_clear_used(RID p_render_target); + virtual void render_target_set_msaa(RID p_render_target, VS::ViewportMSAA p_msaa); + + /* CANVAS SHADOW */ + + virtual RID canvas_light_shadow_buffer_create(int p_width); + + /* LIGHT SHADOW MAPPING */ + + virtual RID canvas_light_occluder_create(); + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines); + + virtual VS::InstanceType get_base_type(RID p_rid) const; + + virtual bool free(RID p_rid); + + struct Frame { + + RenderTarget *current_rt; + + bool clear_request; + Color clear_request_color; + int canvas_draw_commands; + float time[4]; + float delta; + uint64_t prev_tick; + uint64_t count; + + } frame; + + void initialize(); + void finalize(); + + virtual bool has_os_feature(const String &p_feature) const; + + virtual void update_dirty_resources(); + + virtual void set_debug_generate_wireframes(bool p_generate); + + virtual void render_info_begin_capture(); + virtual void render_info_end_capture(); + virtual int get_captured_render_info(VS::RenderInfo p_info); + + virtual int get_render_info(VS::RenderInfo p_info); + + RasterizerStorageGLES2(); +}; + +#endif // RASTERIZERSTORAGEGLES2_H diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp new file mode 100644 index 0000000000..f41bfe838b --- /dev/null +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -0,0 +1,891 @@ +/*************************************************************************/ +/* shader_compiler_gles3.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "shader_compiler_gles2.h" + +#include "os/os.h" +#include "string_buffer.h" +#include "string_builder.h" + +#define SL ShaderLanguage + +static String _mktab(int p_level) { + + String tb; + for (int i = 0; i < p_level; i++) { + tb += "\t"; + } + + return tb; +} + +static String _typestr(SL::DataType p_type) { + + return ShaderLanguage::get_datatype_name(p_type); +} + +static String _prestr(SL::DataPrecision p_pres) { + + switch (p_pres) { + case SL::PRECISION_LOWP: return "lowp "; + case SL::PRECISION_MEDIUMP: return "mediump "; + case SL::PRECISION_HIGHP: return "highp "; + case SL::PRECISION_DEFAULT: return ""; + } + return ""; +} + +static String _qualstr(SL::ArgumentQualifier p_qual) { + + switch (p_qual) { + case SL::ARGUMENT_QUALIFIER_IN: return "in "; + case SL::ARGUMENT_QUALIFIER_OUT: return "out "; + case SL::ARGUMENT_QUALIFIER_INOUT: return "inout "; + } + return ""; +} + +static String _opstr(SL::Operator p_op) { + + return SL::get_operator_text(p_op); +} + +static String _mkid(const String &p_id) { + + StringBuffer<> id; + id += "m_"; + id += p_id; + + return id.as_string(); +} + +static String f2sp0(float p_float) { + + if (int(p_float) == p_float) + return itos(p_float) + ".0"; + else + return rtoss(p_float); +} + +static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) { + + switch (p_type) { + case SL::TYPE_BOOL: return p_values[0].boolean ? "true" : "false"; + case SL::TYPE_BVEC2: + case SL::TYPE_BVEC3: + case SL::TYPE_BVEC4: { + + StringBuffer<> text; + + text += "bvec"; + text += itos(p_type - SL::TYPE_BOOL + 1); + text += "("; + + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += p_values[i].boolean ? "true" : "false"; + } + text += ")"; + return text.as_string(); + } + + // GLSL ES 2 doesn't support uints, so we just use signed ints instead... + case SL::TYPE_UINT: return itos(p_values[0].uint); + case SL::TYPE_UVEC2: + case SL::TYPE_UVEC3: + case SL::TYPE_UVEC4: { + + StringBuffer<> text; + + text += "ivec"; + text += itos(p_type - SL::TYPE_UINT + 1); + text += "("; + + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += itos(p_values[i].uint); + } + text += ")"; + return text.as_string(); + + } break; + + case SL::TYPE_INT: return itos(p_values[0].sint); + case SL::TYPE_IVEC2: + case SL::TYPE_IVEC3: + case SL::TYPE_IVEC4: { + + StringBuffer<> text; + + text += "ivec"; + text += itos(p_type - SL::TYPE_INT + 1); + text += "("; + + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += itos(p_values[i].sint); + } + text += ")"; + return text.as_string(); + + } break; + case SL::TYPE_FLOAT: return f2sp0(p_values[0].real) + "f"; + case SL::TYPE_VEC2: + case SL::TYPE_VEC3: + case SL::TYPE_VEC4: { + + StringBuffer<> text; + + text += "vec"; + text += itos(p_type - SL::TYPE_FLOAT + 1); + text += "("; + + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += f2sp0(p_values[i].real); + } + text += ")"; + return text.as_string(); + + } break; + case SL::TYPE_MAT2: + case SL::TYPE_MAT3: + case SL::TYPE_MAT4: { + + StringBuffer<> text; + + text += "mat"; + text += itos(p_type - SL::TYPE_MAT2 + 2); + text += "("; + + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += f2sp0(p_values[i].real); + } + text += ")"; + return text.as_string(); + + } break; + default: ERR_FAIL_V(String()); + } +} + +void ShaderCompilerGLES2::_dump_function_deps(SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added) { + int fidx = -1; + + for (int i = 0; i < p_node->functions.size(); i++) { + if (p_node->functions[i].name == p_for_func) { + fidx = i; + break; + } + } + + ERR_FAIL_COND(fidx == -1); + + for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { + + if (r_added.has(E->get())) { + continue; + } + + _dump_function_deps(p_node, E->get(), p_func_code, r_to_add, r_added); + + SL::FunctionNode *fnode = NULL; + + for (int i = 0; i < p_node->functions.size(); i++) { + if (p_node->functions[i].name == E->get()) { + fnode = p_node->functions[i].function; + break; + } + } + + ERR_FAIL_COND(!fnode); + + r_to_add += "\n"; + + StringBuffer<128> header; + + header += _typestr(fnode->return_type); + header += " "; + header += _mkid(fnode->name); + header += "("; + + for (int i = 0; i < fnode->arguments.size(); i++) { + if (i > 0) + header += ", "; + + header += _qualstr(fnode->arguments[i].qualifier); + header += _prestr(fnode->arguments[i].precision); + header += _typestr(fnode->arguments[i].type); + header += " "; + header += _mkid(fnode->arguments[i].name); + } + + header += ")\n"; + r_to_add += header.as_string(); + r_to_add += p_func_code[E->get()]; + + r_added.insert(E->get()); + } +} + +String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning) { + + StringBuilder code; + + switch (p_node->type) { + + case SL::Node::TYPE_SHADER: { + + SL::ShaderNode *snode = (SL::ShaderNode *)p_node; + + for (int i = 0; i < snode->render_modes.size(); i++) { + + if (p_default_actions.render_mode_defines.has(snode->render_modes[i]) && !used_rmode_defines.has(snode->render_modes[i])) { + + r_gen_code.custom_defines.push_back(p_default_actions.render_mode_defines[snode->render_modes[i]].utf8()); + used_rmode_defines.insert(snode->render_modes[i]); + } + + if (p_actions.render_mode_flags.has(snode->render_modes[i])) { + *p_actions.render_mode_flags[snode->render_modes[i]] = true; + } + + if (p_actions.render_mode_values.has(snode->render_modes[i])) { + Pair<int *, int> &p = p_actions.render_mode_values[snode->render_modes[i]]; + *p.first = p.second; + } + } + + int max_texture_uniforms = 0; + int max_uniforms = 0; + + for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) { + if (SL::is_sampler_type(E->get().type)) + max_texture_uniforms++; + else + max_uniforms++; + } + + r_gen_code.texture_uniforms.resize(max_texture_uniforms); + r_gen_code.texture_hints.resize(max_texture_uniforms); + + r_gen_code.uniforms.resize(max_uniforms + max_texture_uniforms); + + StringBuilder vertex_global; + StringBuilder fragment_global; + + // uniforms + + for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) { + StringBuffer<> uniform_code; + + uniform_code += "uniform "; + + uniform_code += _prestr(E->get().precission); + uniform_code += _typestr(E->get().type); + uniform_code += " "; + uniform_code += _mkid(E->key()); + uniform_code += ";\n"; + + if (SL::is_sampler_type(E->get().type)) { + r_gen_code.texture_uniforms[E->get().texture_order] = _mkid(E->key()); + r_gen_code.texture_hints[E->get().texture_order] = E->get().hint; + } else { + r_gen_code.uniforms[E->get().order] = E->key(); + } + + vertex_global += uniform_code.as_string(); + fragment_global += uniform_code.as_string(); + + p_actions.uniforms->insert(E->key(), E->get()); + } + + // varyings + + for (Map<StringName, SL::ShaderNode::Varying>::Element *E = snode->varyings.front(); E; E = E->next()) { + + StringBuffer<> varying_code; + + varying_code += "varying "; + varying_code += _prestr(E->get().precission); + varying_code += _typestr(E->get().type); + varying_code += " "; + varying_code += _mkid(E->key()); + varying_code += ";\n"; + + String final_code = varying_code.as_string(); + + vertex_global += final_code; + fragment_global += final_code; + } + + // functions + + Map<StringName, String> function_code; + + for (int i = 0; i < snode->functions.size(); i++) { + SL::FunctionNode *fnode = snode->functions[i].function; + function_code[fnode->name] = _dump_node_code(fnode->body, 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } + + Set<StringName> added_vertex; + Set<StringName> added_fragment; + + for (int i = 0; i < snode->functions.size(); i++) { + + SL::FunctionNode *fnode = snode->functions[i].function; + + current_func_name = fnode->name; + + if (fnode->name == vertex_name) { + _dump_function_deps(snode, fnode->name, function_code, vertex_global, added_vertex); + r_gen_code.vertex = function_code[vertex_name]; + + } else if (fnode->name == fragment_name) { + _dump_function_deps(snode, fnode->name, function_code, fragment_global, added_fragment); + r_gen_code.fragment = function_code[fragment_name]; + + } else if (fnode->name == light_name) { + _dump_function_deps(snode, fnode->name, function_code, fragment_global, added_fragment); + r_gen_code.light = function_code[light_name]; + } + } + + r_gen_code.vertex_global = vertex_global.as_string(); + r_gen_code.fragment_global = fragment_global.as_string(); + + } break; + + case SL::Node::TYPE_FUNCTION: { + + } break; + + case SL::Node::TYPE_BLOCK: { + + SL::BlockNode *bnode = (SL::BlockNode *)p_node; + + if (!bnode->single_statement) { + code += _mktab(p_level - 1); + code += "{\n"; + } + + for (int i = 0; i < bnode->statements.size(); i++) { + String statement_code = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + + if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) { + code += statement_code; + } else { + code += _mktab(p_level); + code += statement_code; + code += ";\n"; + } + } + + if (!bnode->single_statement) { + code += _mktab(p_level - 1); + code += "}\n"; + } + } break; + + case SL::Node::TYPE_VARIABLE_DECLARATION: { + SL::VariableDeclarationNode *var_dec_node = (SL::VariableDeclarationNode *)p_node; + + StringBuffer<> declaration; + + declaration += _prestr(var_dec_node->precision); + declaration += _typestr(var_dec_node->datatype); + + for (int i = 0; i < var_dec_node->declarations.size(); i++) { + + if (i > 0) { + declaration += ","; + } + + declaration += " "; + + declaration += _mkid(var_dec_node->declarations[i].name); + + if (var_dec_node->declarations[i].initializer) { + declaration += " = "; + declaration += _dump_node_code(var_dec_node->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } + } + + code += declaration.as_string(); + } break; + + case SL::Node::TYPE_VARIABLE: { + SL::VariableNode *var_node = (SL::VariableNode *)p_node; + + if (p_assigning && p_actions.write_flag_pointers.has(var_node->name)) { + *p_actions.write_flag_pointers[var_node->name] = true; + } + + if (p_default_actions.usage_defines.has(var_node->name) && !used_name_defines.has(var_node->name)) { + String define = p_default_actions.usage_defines[var_node->name]; + + if (define.begins_with("@")) { + define = p_default_actions.usage_defines[define.substr(1, define.length())]; + } + + r_gen_code.custom_defines.push_back(define.utf8()); + used_name_defines.insert(var_node->name); + } + + if (p_actions.usage_flag_pointers.has(var_node->name) && !used_flag_pointers.has(var_node->name)) { + *p_actions.usage_flag_pointers[var_node->name] = true; + used_flag_pointers.insert(var_node->name); + } + + if (p_default_actions.renames.has(var_node->name)) { + code += p_default_actions.renames[var_node->name]; + } else { + code += _mkid(var_node->name); + } + + if (var_node->name == time_name) { + if (current_func_name == vertex_name) { + r_gen_code.uses_vertex_time = true; + } + if (current_func_name == fragment_name || current_func_name == light_name) { + r_gen_code.uses_fragment_time = true; + } + } + } break; + + case SL::Node::TYPE_CONSTANT: { + SL::ConstantNode *const_node = (SL::ConstantNode *)p_node; + + return get_constant_text(const_node->datatype, const_node->values); + } break; + + case SL::Node::TYPE_OPERATOR: { + SL::OperatorNode *op_node = (SL::OperatorNode *)p_node; + + switch (op_node->op) { + case SL::OP_ASSIGN: + case SL::OP_ASSIGN_ADD: + case SL::OP_ASSIGN_SUB: + case SL::OP_ASSIGN_MUL: + case SL::OP_ASSIGN_DIV: + case SL::OP_ASSIGN_SHIFT_LEFT: + case SL::OP_ASSIGN_SHIFT_RIGHT: + case SL::OP_ASSIGN_MOD: + case SL::OP_ASSIGN_BIT_AND: + case SL::OP_ASSIGN_BIT_OR: + case SL::OP_ASSIGN_BIT_XOR: { + code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true); + code += " "; + code += _opstr(op_node->op); + code += " "; + code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } break; + + case SL::OP_BIT_INVERT: + case SL::OP_NEGATE: + case SL::OP_NOT: + case SL::OP_DECREMENT: + case SL::OP_INCREMENT: { + code += _opstr(op_node->op); + code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } break; + + case SL::OP_POST_DECREMENT: + case SL::OP_POST_INCREMENT: { + code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += _opstr(op_node->op); + } break; + + case SL::OP_CALL: + case SL::OP_CONSTRUCT: { + ERR_FAIL_COND_V(op_node->arguments[0]->type != SL::Node::TYPE_VARIABLE, String()); + + SL::VariableNode *var_node = (SL::VariableNode *)op_node->arguments[0]; + + if (op_node->op == SL::OP_CONSTRUCT) { + code += var_node->name; + } else { + + if (var_node->name == "texture") { + // emit texture call + + if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D) { + code += "texture2D"; + } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) { + code += "textureCube"; + } + + } else if (p_default_actions.renames.has(var_node->name)) { + code += p_default_actions.renames[var_node->name]; + } else if (internal_functions.has(var_node->name)) { + code += var_node->name; + } else { + code += _mkid(var_node->name); + } + } + + code += "("; + + for (int i = 1; i < op_node->arguments.size(); i++) { + if (i > 1) { + code += ", "; + } + + code += _dump_node_code(op_node->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } + + code += ")"; + + } break; + + case SL::OP_INDEX: { + code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "["; + code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "]"; + } break; + + case SL::OP_SELECT_IF: { + code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += " ? "; + code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += " : "; + code += _dump_node_code(op_node->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } break; + + default: { + code += "("; + code += _dump_node_code(op_node->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += " "; + code += _opstr(op_node->op); + code += " "; + code += _dump_node_code(op_node->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += ")"; + } break; + } + } break; + + case SL::Node::TYPE_CONTROL_FLOW: { + SL::ControlFlowNode *cf_node = (SL::ControlFlowNode *)p_node; + + if (cf_node->flow_op == SL::FLOW_OP_IF) { + + code += _mktab(p_level); + code += "if ("; + code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += ")\n"; + code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + + if (cf_node->blocks.size() == 2) { + code += _mktab(p_level); + code += "else\n"; + code += _dump_node_code(cf_node->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } + } else if (cf_node->flow_op == SL::FLOW_OP_WHILE) { + code += _mktab(p_level); + code += "while ("; + code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += ")\n"; + code += _dump_node_code(cf_node->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cf_node->flow_op == SL::FLOW_OP_FOR) { + + code += _mktab(p_level); + code += "for ("; + code += _dump_node_code(cf_node->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "; "; + code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "; "; + code += _dump_node_code(cf_node->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += ")\n"; + + code += _dump_node_code(cf_node->blocks[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + + } else if (cf_node->flow_op == SL::FLOW_OP_RETURN) { + code += _mktab(p_level); + code += "return"; + + if (cf_node->expressions.size()) { + code += " "; + code += _dump_node_code(cf_node->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } + code += ";\n"; + } else if (cf_node->flow_op == SL::FLOW_OP_DISCARD) { + code += "discard;"; + } else if (cf_node->flow_op == SL::FLOW_OP_CONTINUE) { + code += "continue;"; + } else if (cf_node->flow_op == SL::FLOW_OP_BREAK) { + code += "break;"; + } + } break; + + case SL::Node::TYPE_MEMBER: { + SL::MemberNode *member_node = (SL::MemberNode *)p_node; + code += _dump_node_code(member_node->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "."; + code += member_node->name; + } break; + } + + return code.as_string(); +} + +Error ShaderCompilerGLES2::compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { + + Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types()); + + if (err != OK) { + + Vector<String> shader = p_code.split("\n"); + for (int i = 0; i < shader.size(); i++) { + print_line(itos(i) + " " + shader[i]); + } + + _err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER); + return err; + } + + r_gen_code.custom_defines.clear(); + r_gen_code.uniforms.clear(); + r_gen_code.texture_uniforms.clear(); + r_gen_code.texture_hints.clear(); + r_gen_code.vertex = String(); + r_gen_code.vertex_global = String(); + r_gen_code.fragment = String(); + r_gen_code.fragment_global = String(); + r_gen_code.light = String(); + r_gen_code.uses_fragment_time = false; + r_gen_code.uses_vertex_time = false; + + used_name_defines.clear(); + used_rmode_defines.clear(); + used_flag_pointers.clear(); + + _dump_node_code(parser.get_shader(), 1, r_gen_code, *p_actions, actions[p_mode], false); + + return OK; +} + +ShaderCompilerGLES2::ShaderCompilerGLES2() { + + /** CANVAS ITEM SHADER **/ + + actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy"; + actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp"; + actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "gl_PointSize"; + + actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] == "extra_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["TIME"] = "time"; + actions[VS::SHADER_CANVAS_ITEM].renames["AT_LIGHT_PASS"] = "at_light_pass"; + actions[VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom"; + + actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth"; + actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp"; + actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color"; + actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture"; + actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture"; + actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv"; + actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture"; + actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size"; + actions[VS::SHADER_CANVAS_ITEM].renames["FRAGCOORD"] = "gl_FragCoord"; + actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"] = "gl_PointCoord"; + + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"] = "light_vec"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"] = "light_height"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"] = "light_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv"; + //actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_SHADOW_COLOR"]="light_shadow_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light"; + actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color"; + + actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_COLOR"] = "#define SHADOW_COLOR_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + + actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + + /** SPATIAL SHADER **/ + + actions[VS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; + actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; + actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; + actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; + actions[VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; + actions[VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; + + actions[VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; + actions[VS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; + actions[VS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; + actions[VS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; + actions[VS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; + actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; + actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; + actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize"; + //actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"]=ShaderLanguage::TYPE_INT; + + //builtins + + actions[VS::SHADER_SPATIAL].renames["TIME"] = "time"; + actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; + + actions[VS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; + actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; + actions[VS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap"; + actions[VS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth"; + actions[VS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; + actions[VS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; + actions[VS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; + actions[VS::SHADER_SPATIAL].renames["SPECULAR"] = "specular"; + actions[VS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness"; + actions[VS::SHADER_SPATIAL].renames["RIM"] = "rim"; + actions[VS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint"; + actions[VS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat"; + actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; + actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; + actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; + //actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"] = "sss_spread"; + actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; + actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; + actions[VS::SHADER_SPATIAL].renames["AO"] = "ao"; + actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; + actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; + //actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; + actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; + 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["SIDE"] = "side"; + actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; + + //for light + actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view"; + actions[VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; + actions[VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; + actions[VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; + actions[VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; + + actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; + actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; + actions[VS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; + actions[VS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM"; + actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; + actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; + actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; + actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; + actions[VS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n"; + actions[VS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; + actions[VS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; + actions[VS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; + actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; + actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; + actions[VS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; + actions[VS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; + actions[VS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; + + 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["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + + actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + + actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; + + actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; + + actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; + + actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; + + /* PARTICLES SHADER */ + + actions[VS::SHADER_PARTICLES].renames["COLOR"] = "out_color"; + actions[VS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz"; + actions[VS::SHADER_PARTICLES].renames["MASS"] = "mass"; + actions[VS::SHADER_PARTICLES].renames["ACTIVE"] = "active"; + actions[VS::SHADER_PARTICLES].renames["RESTART"] = "restart"; + actions[VS::SHADER_PARTICLES].renames["CUSTOM"] = "out_custom"; + actions[VS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform"; + actions[VS::SHADER_PARTICLES].renames["TIME"] = "time"; + actions[VS::SHADER_PARTICLES].renames["LIFETIME"] = "lifetime"; + actions[VS::SHADER_PARTICLES].renames["DELTA"] = "local_delta"; + actions[VS::SHADER_PARTICLES].renames["NUMBER"] = "particle_number"; + actions[VS::SHADER_PARTICLES].renames["INDEX"] = "index"; + actions[VS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity"; + actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; + actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; + + actions[VS::SHADER_SPATIAL].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; + + vertex_name = "vertex"; + fragment_name = "fragment"; + light_name = "light"; + time_name = "TIME"; + + List<String> func_list; + + ShaderLanguage::get_builtin_funcs(&func_list); + + for (List<String>::Element *E = func_list.front(); E; E = E->next()) { + internal_functions.insert(E->get()); + } +} diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h new file mode 100644 index 0000000000..804ead2172 --- /dev/null +++ b/drivers/gles2/shader_compiler_gles2.h @@ -0,0 +1,101 @@ +/*************************************************************************/ +/* shader_compiler_gles2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 SHADERCOMPILERGLES2_H +#define SHADERCOMPILERGLES2_H + +#include "pair.h" +#include "servers/visual/shader_language.h" +#include "servers/visual/shader_types.h" +#include "servers/visual_server.h" + +#include "string_builder.h" + +class ShaderCompilerGLES2 { +public: + struct IdentifierActions { + + Map<StringName, Pair<int *, int> > render_mode_values; + Map<StringName, bool *> render_mode_flags; + Map<StringName, bool *> usage_flag_pointers; + Map<StringName, bool *> write_flag_pointers; + + Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms; + }; + + struct GeneratedCode { + + Vector<CharString> custom_defines; + Vector<StringName> uniforms; + Vector<StringName> texture_uniforms; + Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints; + + String vertex_global; + String vertex; + String fragment_global; + String fragment; + String light; + + bool uses_fragment_time; + bool uses_vertex_time; + }; + +private: + ShaderLanguage parser; + + struct DefaultIdentifierActions { + + Map<StringName, String> renames; + Map<StringName, String> render_mode_defines; + Map<StringName, String> usage_defines; + }; + + void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added); + String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning); + + StringName current_func_name; + StringName vertex_name; + StringName fragment_name; + StringName light_name; + StringName time_name; + + Set<StringName> used_name_defines; + Set<StringName> used_flag_pointers; + Set<StringName> used_rmode_defines; + Set<StringName> internal_functions; + + DefaultIdentifierActions actions[VS::SHADER_MAX]; + +public: + Error compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code); + + ShaderCompilerGLES2(); +}; + +#endif // SHADERCOMPILERGLES3_H diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp new file mode 100644 index 0000000000..fa9562877d --- /dev/null +++ b/drivers/gles2/shader_gles2.cpp @@ -0,0 +1,689 @@ +/*************************************************************************/ +/* shader_gles2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "shader_gles2.h" + +#include "memory.h" +#include "print_string.h" +#include "string_builder.h" + +//#define DEBUG_OPENGL + +// #include "shaders/copy.glsl.gen.h" + +#ifdef DEBUG_OPENGL + +#define DEBUG_TEST_ERROR(m_section) \ + { \ + uint32_t err = glGetError(); \ + if (err) { \ + print_line("OpenGL Error #" + itos(err) + " at: " + m_section); \ + } \ + } +#else + +#define DEBUG_TEST_ERROR(m_section) + +#endif + +ShaderGLES2 *ShaderGLES2::active = NULL; + +//#define DEBUG_SHADER + +#ifdef DEBUG_SHADER + +#define DEBUG_PRINT(m_text) print_line(m_text); + +#else + +#define DEBUG_PRINT(m_text) + +#endif + +void ShaderGLES2::bind_uniforms() { + if (!uniforms_dirty) + return; + + // regular uniforms + + const Map<uint32_t, Variant>::Element *E = uniform_defaults.front(); + + while (E) { + int idx = E->key(); + int location = version->uniform_location[idx]; + + if (location < 0) { + E = E->next(); + continue; + } + + const Variant &v = E->value(); + _set_uniform_variant(location, v); + E = E->next(); + } + + // camera uniforms + + const Map<uint32_t, CameraMatrix>::Element *C = uniform_cameras.front(); + + while (C) { + int idx = E->key(); + int location = version->uniform_location[idx]; + + if (location < 0) { + C = C->next(); + continue; + } + + glUniformMatrix4fv(location, 1, GL_FALSE, &(C->get().matrix[0][0])); + C = C->next(); + } + + uniforms_dirty = false; +} + +GLint ShaderGLES2::get_uniform_location(int p_index) const { + + ERR_FAIL_COND_V(!version, -1); + + return version->uniform_location[p_index]; +} + +bool ShaderGLES2::bind() { + + if (active != this || !version || new_conditional_version.key != conditional_version.key) { + conditional_version = new_conditional_version; + version = get_current_version(); + } else { + return false; + } + + ERR_FAIL_COND_V(!version, false); + + glUseProgram(version->id); + + DEBUG_TEST_ERROR("use program"); + + active = this; + uniforms_dirty = true; + + return true; +} + +void ShaderGLES2::unbind() { + version = NULL; + glUseProgram(0); + uniforms_dirty = true; + active = NULL; +} + +static String _fix_error_code_line(const String &p_error, int p_code_start, int p_offset) { + + int last_find_pos = -1; + // NVIDIA + String error = p_error; + while ((last_find_pos = p_error.find("(", last_find_pos + 1)) != -1) { + + int end_pos = last_find_pos + 1; + + while (true) { + + if (p_error[end_pos] >= '0' && p_error[end_pos] <= '9') { + + end_pos++; + continue; + } else if (p_error[end_pos] == ')') { + break; + } else { + + end_pos = -1; + break; + } + } + + if (end_pos == -1) + continue; + + String numstr = error.substr(last_find_pos + 1, (end_pos - last_find_pos) - 1); + String begin = error.substr(0, last_find_pos + 1); + String end = error.substr(end_pos, error.length()); + int num = numstr.to_int() + p_code_start - p_offset; + error = begin + itos(num) + end; + } + + // ATI + last_find_pos = -1; + while ((last_find_pos = p_error.find("ERROR: ", last_find_pos + 1)) != -1) { + + last_find_pos += 6; + int end_pos = last_find_pos + 1; + + while (true) { + + if (p_error[end_pos] >= '0' && p_error[end_pos] <= '9') { + + end_pos++; + continue; + } else if (p_error[end_pos] == ':') { + break; + } else { + + end_pos = -1; + break; + } + } + continue; + if (end_pos == -1) + continue; + + String numstr = error.substr(last_find_pos + 1, (end_pos - last_find_pos) - 1); + print_line("numstr: " + numstr); + String begin = error.substr(0, last_find_pos + 1); + String end = error.substr(end_pos, error.length()); + int num = numstr.to_int() + p_code_start - p_offset; + error = begin + itos(num) + end; + } + return error; +} + +ShaderGLES2::Version *ShaderGLES2::get_current_version() { + + Version *_v = version_map.getptr(conditional_version); + + if (_v) { + if (conditional_version.code_version != 0) { + CustomCode *cc = custom_code_map.getptr(conditional_version.code_version); + ERR_FAIL_COND_V(!cc, _v); + if (cc->version == _v->code_version) + return _v; + } else { + return _v; + } + } + + if (!_v) + version_map[conditional_version]; + + Version &v = version_map[conditional_version]; + + if (!_v) { + v.uniform_location = memnew_arr(GLint, uniform_count); + } else { + if (v.ok) { + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + v.id = 0; + } + } + + v.ok = false; + + Vector<const char *> strings; + +#ifdef GLES_OVER_GL + strings.push_back("#version 120\n"); + strings.push_back("#define USE_GLES_OVER_GL\n"); +#else + strings.push_back("#version 100\n"); +#endif + + int define_line_ofs = 1; + + for (int j = 0; j < conditional_count; j++) { + bool enable = (conditional_version.version & (1 << j)) > 0; + + if (enable) { + strings.push_back(conditional_defines[j]); + define_line_ofs++; + DEBUG_PRINT(conditional_defines[j]); + } + } + + // keep them around during the functino + CharString code_string; + CharString code_string2; + CharString code_globals; + + CustomCode *cc = NULL; + + if (conditional_version.code_version > 0) { + cc = custom_code_map.getptr(conditional_version.code_version); + + ERR_FAIL_COND_V(!cc, NULL); + v.code_version = cc->version; + define_line_ofs += 2; + } + + // program + + v.id = glCreateProgram(); + ERR_FAIL_COND_V(v.id == 0, NULL); + + if (cc) { + for (int i = 0; i < cc->custom_defines.size(); i++) { + strings.push_back(cc->custom_defines[i]); + DEBUG_PRINT("CD #" + itos(i) + ": " + String(cc->custom_defines[i])); + } + } + + // vertex shader + + int string_base_size = strings.size(); + + strings.push_back(vertex_code0.get_data()); + + if (cc) { + code_globals = cc->vertex_globals.ascii(); + strings.push_back(code_globals.get_data()); + } + + strings.push_back(vertex_code1.get_data()); + + if (cc) { + code_string = cc->vertex.ascii(); + strings.push_back(code_string.get_data()); + } + + strings.push_back(vertex_code2.get_data()); + +#ifdef DEBUG_SHADER + + DEBUG_PRINT("\nVertex Code:\n\n" + String(code_string.get_data())); + +#endif + + v.vert_id = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(v.vert_id, strings.size(), &strings[0], NULL); + glCompileShader(v.vert_id); + + GLint status; + + glGetShaderiv(v.vert_id, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + GLsizei iloglen; + glGetShaderiv(v.vert_id, GL_INFO_LOG_LENGTH, &iloglen); + + if (iloglen < 0) { + glDeleteShader(v.vert_id); + glDeleteProgram(v.id); + v.id = 0; + + ERR_PRINT("No OpenGL vertex shader compiler log. What the frick?"); + } else { + if (iloglen == 0) { + iloglen = 4096; // buggy driver (Adreno 220+) + } + + char *ilogmem = (char *)Memory::alloc_static(iloglen + 1); + ilogmem[iloglen] = '\0'; + glGetShaderInfoLog(v.vert_id, iloglen, &iloglen, ilogmem); + + String err_string = get_shader_name() + ": Vertex shader compilation failed:\n"; + + err_string += ilogmem; + err_string = _fix_error_code_line(err_string, vertex_code_start, define_line_ofs); + + ERR_PRINTS(err_string); + + Memory::free_static(ilogmem); + glDeleteShader(v.vert_id); + glDeleteProgram(v.id); + v.id = 0; + } + + ERR_FAIL_V(NULL); + } + + strings.resize(string_base_size); + + // fragment shader + + strings.push_back(fragment_code0.get_data()); + + if (cc) { + code_globals = cc->fragment_globals.ascii(); + strings.push_back(code_globals.get_data()); + } + + strings.push_back(fragment_code1.get_data()); + + if (cc) { + code_string = cc->fragment.ascii(); + strings.push_back(code_string.get_data()); + } + + strings.push_back(fragment_code2.get_data()); + + if (cc) { + code_string2 = cc->light.ascii(); + strings.push_back(code_string2.get_data()); + } + + strings.push_back(fragment_code3.get_data()); + +#ifdef DEBUG_SHADER + DEBUG_PRINT("\nFragment Code:\n\n" + String(code_string.get_data())); +#endif + + v.frag_id = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(v.frag_id, strings.size(), &strings[0], NULL); + glCompileShader(v.frag_id); + + glGetShaderiv(v.frag_id, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + GLsizei iloglen; + glGetShaderiv(v.frag_id, GL_INFO_LOG_LENGTH, &iloglen); + + if (iloglen < 0) { + glDeleteShader(v.frag_id); + glDeleteShader(v.vert_id); + glDeleteProgram(v.id); + v.id = 0; + + ERR_PRINT("No OpenGL fragment shader compiler log. What the frick?"); + } else { + if (iloglen == 0) { + iloglen = 4096; // buggy driver (Adreno 220+) + } + + char *ilogmem = (char *)Memory::alloc_static(iloglen + 1); + ilogmem[iloglen] = '\0'; + glGetShaderInfoLog(v.frag_id, iloglen, &iloglen, ilogmem); + + String err_string = get_shader_name() + ": Fragment shader compilation failed:\n"; + + err_string += ilogmem; + err_string = _fix_error_code_line(err_string, fragment_code_start, define_line_ofs); + + ERR_PRINTS(err_string); + + Memory::free_static(ilogmem); + glDeleteShader(v.frag_id); + glDeleteShader(v.vert_id); + glDeleteProgram(v.id); + v.id = 0; + } + + ERR_FAIL_V(NULL); + } + + glAttachShader(v.id, v.frag_id); + glAttachShader(v.id, v.vert_id); + + // bind the attribute locations. This has to be done before linking so that the + // linker doesn't assign some random indices + + for (int i = 0; i < attribute_pair_count; i++) { + glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name); + } + + glLinkProgram(v.id); + + glGetProgramiv(v.id, GL_LINK_STATUS, &status); + if (status == GL_FALSE) { + GLsizei iloglen; + glGetProgramiv(v.id, GL_INFO_LOG_LENGTH, &iloglen); + + if (iloglen < 0) { + glDeleteShader(v.frag_id); + glDeleteShader(v.vert_id); + glDeleteProgram(v.id); + v.id = 0; + + ERR_PRINT("No OpenGL program link log. What the frick?"); + ERR_FAIL_V(NULL); + } + + if (iloglen == 0) { + iloglen = 4096; // buggy driver (Adreno 220+) + } + + char *ilogmem = (char *)Memory::alloc_static(iloglen + 1); + ilogmem[iloglen] = '\0'; + glGetProgramInfoLog(v.id, iloglen, &iloglen, ilogmem); + + String err_string = get_shader_name() + ": Program linking failed:\n"; + + err_string += ilogmem; + err_string = _fix_error_code_line(err_string, fragment_code_start, define_line_ofs); + + ERR_PRINTS(err_string); + + Memory::free_static(ilogmem); + glDeleteShader(v.frag_id); + glDeleteShader(v.vert_id); + glDeleteProgram(v.id); + v.id = 0; + + ERR_FAIL_V(NULL); + } + + // get uniform locations + + glUseProgram(v.id); + + for (int i = 0; i < uniform_count; i++) { + v.uniform_location[i] = glGetUniformLocation(v.id, uniform_names[i]); + } + + for (int i = 0; i < texunit_pair_count; i++) { + GLint loc = glGetUniformLocation(v.id, texunit_pairs[i].name); + if (loc >= 0) + glUniform1i(loc, texunit_pairs[i].index); + } + + if (cc) { + v.custom_uniform_locations.resize(cc->custom_uniforms.size()); + for (int i = 0; i < cc->custom_uniforms.size(); i++) { + v.custom_uniform_locations[i] = glGetUniformLocation(v.id, String(cc->custom_uniforms[i]).ascii().get_data()); + } + } + + glUseProgram(0); + v.ok = true; + + return &v; +} + +GLint ShaderGLES2::get_uniform_location(const String &p_name) const { + + ERR_FAIL_COND_V(!version, -1); + return glGetUniformLocation(version->id, p_name.ascii().get_data()); +} + +void ShaderGLES2::setup( + const char **p_conditional_defines, + int p_conditional_count, + const char **p_uniform_names, + int p_uniform_count, + const AttributePair *p_attribute_pairs, + int p_attribute_count, + const TexUnitPair *p_texunit_pairs, + int p_texunit_pair_count, + const char *p_vertex_code, + const char *p_fragment_code, + int p_vertex_code_start, + int p_fragment_code_start) { + + ERR_FAIL_COND(version); + + conditional_version.key = 0; + new_conditional_version.key = 0; + uniform_count = p_uniform_count; + conditional_count = p_conditional_count; + conditional_defines = p_conditional_defines; + uniform_names = p_uniform_names; + vertex_code = p_vertex_code; + fragment_code = p_fragment_code; + texunit_pairs = p_texunit_pairs; + texunit_pair_count = p_texunit_pair_count; + vertex_code_start = p_vertex_code_start; + fragment_code_start = p_fragment_code_start; + attribute_pairs = p_attribute_pairs; + attribute_pair_count = p_attribute_count; + + { + String globals_tag = "\nVERTEX_SHADER_GLOBALS"; + String code_tag = "\nVERTEX_SHADER_CODE"; + String code = vertex_code; + int cpos = code.find(globals_tag); + if (cpos == -1) { + vertex_code0 = code.ascii(); + } else { + vertex_code0 = code.substr(0, cpos).ascii(); + code = code.substr(cpos + globals_tag.length(), code.length()); + + cpos = code.find(code_tag); + + if (cpos == -1) { + vertex_code1 = code.ascii(); + } else { + vertex_code1 = code.substr(0, cpos).ascii(); + vertex_code2 = code.substr(cpos + code_tag.length(), code.length()).ascii(); + } + } + } + + { + String globals_tag = "\nFRAGMENT_SHADER_GLOBALS"; + String code_tag = "\nFRAGMENT_SHADER_CODE"; + String light_code_tag = "\nLIGHT_SHADER_CODE"; + String code = fragment_code; + int cpos = code.find(globals_tag); + if (cpos == -1) { + fragment_code0 = code.ascii(); + } else { + fragment_code0 = code.substr(0, cpos).ascii(); + code = code.substr(cpos + globals_tag.length(), code.length()); + + cpos = code.find(code_tag); + + if (cpos == -1) { + fragment_code1 = code.ascii(); + } else { + + fragment_code1 = code.substr(0, cpos).ascii(); + String code2 = code.substr(cpos + code_tag.length(), code.length()); + + cpos = code2.find(light_code_tag); + if (cpos == -1) { + fragment_code2 = code2.ascii(); + } else { + fragment_code2 = code2.substr(0, cpos).ascii(); + fragment_code3 = code2.substr(cpos + light_code_tag.length(), code2.length()).ascii(); + } + } + } + } +} + +void ShaderGLES2::finish() { + const VersionKey *V = NULL; + + while ((V = version_map.next(V))) { + Version &v = version_map[*V]; + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + } +} + +void ShaderGLES2::clear_caches() { + const VersionKey *V = NULL; + + while ((V = version_map.next(V))) { + Version &v = version_map[*V]; + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + } + + version_map.clear(); + + custom_code_map.clear(); + version = NULL; + last_custom_code = 1; + uniforms_dirty = true; +} + +uint32_t ShaderGLES2::create_custom_shader() { + custom_code_map[last_custom_code] = CustomCode(); + custom_code_map[last_custom_code].version = 1; + return last_custom_code++; +} + +void ShaderGLES2::set_custom_shader_code(uint32_t p_code_id, + const String &p_vertex, + const String &p_vertex_globals, + const String &p_fragment, + const String &p_light, + const String &p_fragment_globals, + const Vector<StringName> &p_uniforms, + const Vector<StringName> &p_texture_uniforms, + const Vector<CharString> &p_custom_defines) { + CustomCode *cc = custom_code_map.getptr(p_code_id); + ERR_FAIL_COND(!cc); + + cc->vertex = p_vertex; + cc->vertex_globals = p_vertex_globals; + cc->fragment = p_fragment; + cc->fragment_globals = p_fragment_globals; + cc->light = p_light; + cc->custom_uniforms = p_uniforms; + cc->custom_defines = p_custom_defines; + cc->version++; +} + +void ShaderGLES2::set_custom_shader(uint32_t p_code_id) { + new_conditional_version.code_version = p_code_id; +} + +void ShaderGLES2::free_custom_shader(uint32_t p_code_id) { + ERR_FAIL_COND(!custom_code_map.has(p_code_id)); + if (conditional_version.code_version == p_code_id) + conditional_version.code_version = 0; + + custom_code_map.erase(p_code_id); +} + +void ShaderGLES2::set_base_material_tex_index(int p_idx) { +} + +ShaderGLES2::ShaderGLES2() { + version = NULL; + last_custom_code = 1; + uniforms_dirty = true; +} + +ShaderGLES2::~ShaderGLES2() { + finish(); +} diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h new file mode 100644 index 0000000000..c3635bc201 --- /dev/null +++ b/drivers/gles2/shader_gles2.h @@ -0,0 +1,386 @@ +/*************************************************************************/ +/* shader_gles2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 SHADER_GLES2_H +#define SHADER_GLES2_H + +#include <stdio.h> + +#include "platform_config.h" +#ifndef GLES2_INCLUDE_H +#include <GLES2/gl2.h> +#else +#include GLES2_INCLUDE_H +#endif + +#include "camera_matrix.h" +#include "hash_map.h" +#include "map.h" +#include "variant.h" + +class ShaderGLES2 { +protected: + struct Enum { + + uint64_t mask; + uint64_t shift; + const char *defines[16]; + }; + + struct EnumValue { + + uint64_t set_mask; + uint64_t clear_mask; + }; + + struct AttributePair { + + const char *name; + int index; + }; + + struct UniformPair { + const char *name; + Variant::Type type_hint; + }; + + struct TexUnitPair { + + const char *name; + int index; + }; + + bool uniforms_dirty; + +private: + //@TODO Optimize to a fixed set of shader pools and use a LRU + int uniform_count; + int texunit_pair_count; + int conditional_count; + int vertex_code_start; + int fragment_code_start; + int attribute_pair_count; + + struct CustomCode { + + String vertex; + String vertex_globals; + String fragment; + String fragment_globals; + String light; + uint32_t version; + Vector<StringName> texture_uniforms; + Vector<StringName> custom_uniforms; + Vector<CharString> custom_defines; + }; + + struct Version { + + GLuint id; + GLuint vert_id; + GLuint frag_id; + GLint *uniform_location; + Vector<GLint> texture_uniform_locations; + Vector<GLint> custom_uniform_locations; + uint32_t code_version; + bool ok; + Version() { + code_version = 0; + ok = false; + uniform_location = NULL; + } + }; + + Version *version; + + union VersionKey { + + struct { + uint32_t version; + uint32_t code_version; + }; + uint64_t key; + bool operator==(const VersionKey &p_key) const { return key == p_key.key; } + bool operator<(const VersionKey &p_key) const { return key < p_key.key; } + }; + + struct VersionKeyHash { + + static _FORCE_INLINE_ uint32_t hash(const VersionKey &p_key) { return HashMapHasherDefault::hash(p_key.key); } + }; + + //this should use a way more cachefriendly version.. + HashMap<VersionKey, Version, VersionKeyHash> version_map; + + HashMap<uint32_t, CustomCode> custom_code_map; + uint32_t last_custom_code; + + VersionKey conditional_version; + VersionKey new_conditional_version; + + virtual String get_shader_name() const = 0; + + const char **conditional_defines; + const char **uniform_names; + const AttributePair *attribute_pairs; + const TexUnitPair *texunit_pairs; + const char *vertex_code; + const char *fragment_code; + CharString fragment_code0; + CharString fragment_code1; + CharString fragment_code2; + CharString fragment_code3; + + CharString vertex_code0; + CharString vertex_code1; + CharString vertex_code2; + + Vector<CharString> custom_defines; + + Version *get_current_version(); + + static ShaderGLES2 *active; + + int max_image_units; + + _FORCE_INLINE_ void _set_uniform_variant(GLint p_uniform, const Variant &p_value) { + + if (p_uniform < 0) + return; // do none + switch (p_value.get_type()) { + + case Variant::BOOL: + case Variant::INT: { + + int val = p_value; + glUniform1i(p_uniform, val); + } break; + case Variant::REAL: { + + real_t val = p_value; + glUniform1f(p_uniform, val); + } break; + case Variant::COLOR: { + + Color val = p_value; + glUniform4f(p_uniform, val.r, val.g, val.b, val.a); + } break; + case Variant::VECTOR2: { + + Vector2 val = p_value; + glUniform2f(p_uniform, val.x, val.y); + } break; + case Variant::VECTOR3: { + + Vector3 val = p_value; + glUniform3f(p_uniform, val.x, val.y, val.z); + } break; + case Variant::PLANE: { + + Plane val = p_value; + glUniform4f(p_uniform, val.normal.x, val.normal.y, val.normal.z, val.d); + } break; + case Variant::QUAT: { + + Quat val = p_value; + glUniform4f(p_uniform, val.x, val.y, val.z, val.w); + } break; + + case Variant::TRANSFORM2D: { + + Transform2D tr = p_value; + GLfloat matrix[16] = { /* build a 16x16 matrix */ + tr.elements[0][0], + tr.elements[0][1], + 0, + 0, + tr.elements[1][0], + tr.elements[1][1], + 0, + 0, + 0, + 0, + 1, + 0, + tr.elements[2][0], + tr.elements[2][1], + 0, + 1 + }; + + glUniformMatrix4fv(p_uniform, 1, false, matrix); + + } break; + case Variant::BASIS: + case Variant::TRANSFORM: { + + Transform tr = p_value; + GLfloat matrix[16] = { /* build a 16x16 matrix */ + tr.basis.elements[0][0], + tr.basis.elements[1][0], + tr.basis.elements[2][0], + 0, + tr.basis.elements[0][1], + tr.basis.elements[1][1], + tr.basis.elements[2][1], + 0, + tr.basis.elements[0][2], + tr.basis.elements[1][2], + tr.basis.elements[2][2], + 0, + tr.origin.x, + tr.origin.y, + tr.origin.z, + 1 + }; + + glUniformMatrix4fv(p_uniform, 1, false, matrix); + } break; + default: { ERR_FAIL(); } // do nothing + } + } + + Map<uint32_t, Variant> uniform_defaults; + Map<uint32_t, CameraMatrix> uniform_cameras; + +protected: + _FORCE_INLINE_ int _get_uniform(int p_which) const; + _FORCE_INLINE_ void _set_conditional(int p_which, bool p_value); + + void setup(const char **p_conditional_defines, + int p_conditional_count, + const char **p_uniform_names, + int p_uniform_count, + const AttributePair *p_attribute_pairs, + int p_attribute_count, + const TexUnitPair *p_texunit_pairs, + int p_texunit_pair_count, + const char *p_vertex_code, + const char *p_fragment_code, + int p_vertex_code_start, + int p_fragment_code_start); + + ShaderGLES2(); + +public: + enum { + CUSTOM_SHADER_DISABLED = 0 + }; + + GLint get_uniform_location(const String &p_name) const; + GLint get_uniform_location(int p_index) const; + + static _FORCE_INLINE_ ShaderGLES2 *get_active() { return active; } + bool bind(); + void unbind(); + void bind_uniforms(); + + inline GLuint get_program() const { return version ? version->id : 0; } + + void clear_caches(); + + uint32_t create_custom_shader(); + void set_custom_shader_code(uint32_t p_code_id, + const String &p_vertex, + const String &p_vertex_globals, + const String &p_fragment, + const String &p_light, + const String &p_fragment_globals, + const Vector<StringName> &p_uniforms, + const Vector<StringName> &p_texture_uniforms, + const Vector<CharString> &p_custom_defines); + + void set_custom_shader(uint32_t p_code_id); + void free_custom_shader(uint32_t p_code_id); + + void set_uniform_default(int p_idx, const Variant &p_value) { + + if (p_value.get_type() == Variant::NIL) { + + uniform_defaults.erase(p_idx); + } else { + + uniform_defaults[p_idx] = p_value; + } + uniforms_dirty = true; + } + + uint32_t get_version() const { return new_conditional_version.version; } + + void set_uniform_camera(int p_idx, const CameraMatrix &p_mat) { + + uniform_cameras[p_idx] = p_mat; + uniforms_dirty = true; + } + + _FORCE_INLINE_ void set_texture_uniform(int p_idx, const Variant &p_value) { + + ERR_FAIL_COND(!version); + ERR_FAIL_INDEX(p_idx, version->texture_uniform_locations.size()); + _set_uniform_variant(version->texture_uniform_locations[p_idx], p_value); + } + + _FORCE_INLINE_ GLint get_texture_uniform_location(int p_idx) { + + ERR_FAIL_COND_V(!version, -1); + ERR_FAIL_INDEX_V(p_idx, version->texture_uniform_locations.size(), -1); + return version->texture_uniform_locations[p_idx]; + } + + virtual void init() = 0; + void finish(); + + void set_base_material_tex_index(int p_idx); + + void add_custom_define(const String &p_define) { + custom_defines.push_back(p_define.utf8()); + } + + virtual ~ShaderGLES2(); +}; + +// called a lot, made inline + +int ShaderGLES2::_get_uniform(int p_which) const { + + ERR_FAIL_INDEX_V(p_which, uniform_count, -1); + ERR_FAIL_COND_V(!version, -1); + return version->uniform_location[p_which]; +} + +void ShaderGLES2::_set_conditional(int p_which, bool p_value) { + + ERR_FAIL_INDEX(p_which, conditional_count); + if (p_value) + new_conditional_version.version |= (1 << p_which); + else + new_conditional_version.version &= ~(1 << p_which); +} + +#endif diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub new file mode 100644 index 0000000000..5de3e1ac90 --- /dev/null +++ b/drivers/gles2/shaders/SCsub @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +Import('env') + +if 'GLES2_GLSL' in env['BUILDERS']: + env.GLES2_GLSL('copy.glsl'); +# env.GLES2_GLSL('resolve.glsl'); + env.GLES2_GLSL('canvas.glsl'); +# env.GLES2_GLSL('canvas_shadow.glsl'); + env.GLES2_GLSL('scene.glsl'); +# env.GLES2_GLSL('cubemap_filter.glsl'); +# env.GLES2_GLSL('cube_to_dp.glsl'); +# env.GLES2_GLSL('blend_shape.glsl'); +# env.GLES2_GLSL('screen_space_reflection.glsl'); +# env.GLES2_GLSL('effect_blur.glsl'); +# env.GLES2_GLSL('subsurf_scattering.glsl'); +# env.GLES2_GLSL('ssao.glsl'); +# env.GLES2_GLSL('ssao_minify.glsl'); +# env.GLES2_GLSL('ssao_blur.glsl'); +# env.GLES2_GLSL('exposure.glsl'); +# env.GLES2_GLSL('tonemap.glsl'); +# env.GLES2_GLSL('particles.glsl'); diff --git a/drivers/gles2/shaders/blend_shape.glsl b/drivers/gles2/shaders/blend_shape.glsl new file mode 100644 index 0000000000..4e0d066823 --- /dev/null +++ b/drivers/gles2/shaders/blend_shape.glsl @@ -0,0 +1,197 @@ +[vertex] + + +/* +from VisualServer: + +ARRAY_VERTEX=0, +ARRAY_NORMAL=1, +ARRAY_TANGENT=2, +ARRAY_COLOR=3, +ARRAY_TEX_UV=4, +ARRAY_TEX_UV2=5, +ARRAY_BONES=6, +ARRAY_WEIGHTS=7, +ARRAY_INDEX=8, +*/ + +#ifdef USE_2D_VERTEX +#define VFORMAT vec2 +#else +#define VFORMAT vec3 +#endif + +/* INPUT ATTRIBS */ + +layout(location=0) in highp VFORMAT vertex_attrib; +layout(location=1) in vec3 normal_attrib; + +#ifdef ENABLE_TANGENT +layout(location=2) in vec4 tangent_attrib; +#endif + +#ifdef ENABLE_COLOR +layout(location=3) in vec4 color_attrib; +#endif + +#ifdef ENABLE_UV +layout(location=4) in vec2 uv_attrib; +#endif + +#ifdef ENABLE_UV2 +layout(location=5) in vec2 uv2_attrib; +#endif + +#ifdef ENABLE_SKELETON +layout(location=6) in ivec4 bone_attrib; +layout(location=7) in vec4 weight_attrib; +#endif + +/* BLEND ATTRIBS */ + +#ifdef ENABLE_BLEND + +layout(location=8) in highp VFORMAT vertex_attrib_blend; +layout(location=9) in vec3 normal_attrib_blend; + +#ifdef ENABLE_TANGENT +layout(location=10) in vec4 tangent_attrib_blend; +#endif + +#ifdef ENABLE_COLOR +layout(location=11) in vec4 color_attrib_blend; +#endif + +#ifdef ENABLE_UV +layout(location=12) in vec2 uv_attrib_blend; +#endif + +#ifdef ENABLE_UV2 +layout(location=13) in vec2 uv2_attrib_blend; +#endif + +#ifdef ENABLE_SKELETON +layout(location=14) in ivec4 bone_attrib_blend; +layout(location=15) in vec4 weight_attrib_blend; +#endif + +#endif + +/* OUTPUTS */ + +out VFORMAT vertex_out; //tfb: + +#ifdef ENABLE_NORMAL +out vec3 normal_out; //tfb:ENABLE_NORMAL +#endif + +#ifdef ENABLE_TANGENT +out vec4 tangent_out; //tfb:ENABLE_TANGENT +#endif + +#ifdef ENABLE_COLOR +out vec4 color_out; //tfb:ENABLE_COLOR +#endif + +#ifdef ENABLE_UV +out vec2 uv_out; //tfb:ENABLE_UV +#endif + +#ifdef ENABLE_UV2 +out vec2 uv2_out; //tfb:ENABLE_UV2 +#endif + +#ifdef ENABLE_SKELETON +out ivec4 bone_out; //tfb:ENABLE_SKELETON +out vec4 weight_out; //tfb:ENABLE_SKELETON +#endif + +uniform float blend_amount; + +void main() { + + +#ifdef ENABLE_BLEND + + vertex_out = vertex_attrib_blend + vertex_attrib * blend_amount; + +#ifdef ENABLE_NORMAL + normal_out = normal_attrib_blend + normal_attrib * blend_amount; +#endif + +#ifdef ENABLE_TANGENT + + tangent_out.xyz = tangent_attrib_blend.xyz + tangent_attrib.xyz * blend_amount; + tangent_out.w = tangent_attrib_blend.w; //just copy, no point in blending his +#endif + +#ifdef ENABLE_COLOR + + color_out = color_attrib_blend + color_attrib * blend_amount; +#endif + +#ifdef ENABLE_UV + + uv_out = uv_attrib_blend + uv_attrib * blend_amount; +#endif + +#ifdef ENABLE_UV2 + + uv2_out = uv2_attrib_blend + uv2_attrib * blend_amount; +#endif + + +#ifdef ENABLE_SKELETON + + bone_out = bone_attrib_blend; + weight_out = weight_attrib_blend + weight_attrib * blend_amount; +#endif + +#else //ENABLE_BLEND + + + vertex_out = vertex_attrib * blend_amount; + +#ifdef ENABLE_NORMAL + normal_out = normal_attrib * blend_amount; +#endif + +#ifdef ENABLE_TANGENT + + tangent_out.xyz = tangent_attrib.xyz * blend_amount; + tangent_out.w = tangent_attrib.w; //just copy, no point in blending his +#endif + +#ifdef ENABLE_COLOR + + color_out = color_attrib * blend_amount; +#endif + +#ifdef ENABLE_UV + + uv_out = uv_attrib * blend_amount; +#endif + +#ifdef ENABLE_UV2 + + uv2_out = uv2_attrib * blend_amount; +#endif + + +#ifdef ENABLE_SKELETON + + bone_out = bone_attrib; + weight_out = weight_attrib * blend_amount; +#endif + +#endif + gl_Position = vec4(0.0); +} + +[fragment] + + +void main() { + +} + diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl new file mode 100644 index 0000000000..11c6ab9b76 --- /dev/null +++ b/drivers/gles2/shaders/canvas.glsl @@ -0,0 +1,141 @@ +[vertex] + +#ifdef USE_GLES_OVER_GL +#define mediump +#define highp +#else +precision mediump float; +precision mediump int; +#endif + +uniform highp mat4 projection_matrix; +uniform highp mat4 modelview_matrix; +uniform highp mat4 extra_matrix; +attribute highp vec2 vertex; // attrib:0 +attribute vec4 color_attrib; // attrib:3 +attribute vec2 uv_attrib; // attrib:4 + +varying vec2 uv_interp; +varying vec4 color_interp; + +uniform highp vec2 color_texpixel_size; + +#ifdef USE_TEXTURE_RECT + +uniform vec4 dst_rect; +uniform vec4 src_rect; + +#endif + +uniform bool blit_pass; + +VERTEX_SHADER_GLOBALS + +vec2 select(vec2 a, vec2 b, bvec2 c) { + vec2 ret; + + ret.x = c.x ? b.x : a.x; + ret.y = c.y ? b.y : a.y; + + return ret; +} + +void main() { + + vec4 color = color_attrib; + +#ifdef USE_TEXTURE_RECT + + if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z + uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx; + } else { + uv_interp = src_rect.xy + abs(src_rect.zw) * vertex; + } + + vec4 outvec = vec4(0.0, 0.0, 0.0, 1.0); + + // This is what is done in the GLES 3 bindings and should + // take care of flipped rects. + // + // But it doesn't. + // I don't know why, will need to investigate further. + + outvec.xy = dst_rect.xy + abs(dst_rect.zw) * select(vertex, vec2(1.0, 1.0) - vertex, lessThan(src_rect.zw, vec2(0.0, 0.0))); + + // outvec.xy = dst_rect.xy + abs(dst_rect.zw) * vertex; +#else + vec4 outvec = vec4(vertex.xy, 0.0, 1.0); + +#ifdef USE_UV_ATTRIBUTE + uv_interp = uv_attrib; +#else + uv_interp = vertex.xy; +#endif + +#endif + +{ + vec2 src_vtx=outvec.xy; +VERTEX_SHADER_CODE + +} + + color_interp = color; + + gl_Position = projection_matrix * modelview_matrix * outvec; + +} + +[fragment] + +#ifdef USE_GLES_OVER_GL +#define mediump +#define highp +#else +precision mediump float; +precision mediump int; +#endif + +uniform sampler2D color_texture; // texunit:0 +uniform highp vec2 color_texpixel_size; +uniform mediump sampler2D normal_texture; // texunit:1 + +varying mediump vec2 uv_interp; +varying mediump vec4 color_interp; + +uniform bool blit_pass; + +uniform vec4 final_modulate; + +#ifdef SCREEN_TEXTURE_USED + +uniform sampler2D screen_texture; // texunit:2 + +#endif + +#ifdef SCREEN_UV_USED + +uniform vec2 screen_pixel_size; + +#endif + +FRAGMENT_SHADER_GLOBALS + + +void main() { + + vec4 color = color_interp; + + color *= texture2D(color_texture, uv_interp); +{ + +FRAGMENT_SHADER_CODE + + +} + + color *= final_modulate; + + gl_FragColor = color; + +} diff --git a/drivers/gles2/shaders/canvas_shadow.glsl b/drivers/gles2/shaders/canvas_shadow.glsl new file mode 100644 index 0000000000..c757990de0 --- /dev/null +++ b/drivers/gles2/shaders/canvas_shadow.glsl @@ -0,0 +1,49 @@ +[vertex] + + + +uniform highp mat4 projection_matrix; +uniform highp mat4 light_matrix; +uniform highp mat4 world_matrix; +uniform highp float distance_norm; + +layout(location=0) in highp vec3 vertex; + +out highp vec4 position_interp; + +void main() { + + gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0))); + position_interp=gl_Position; +} + +[fragment] + +in highp vec4 position_interp; + +#ifdef USE_RGBA_SHADOWS + +layout(location=0) out lowp vec4 distance_buf; + +#else + +layout(location=0) out highp float distance_buf; + +#endif + +void main() { + + highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias; + +#ifdef USE_RGBA_SHADOWS + + highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); + comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); + distance_buf=comp; +#else + + distance_buf=depth; + +#endif +} + diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl new file mode 100644 index 0000000000..a21da68525 --- /dev/null +++ b/drivers/gles2/shaders/copy.glsl @@ -0,0 +1,72 @@ +[vertex] + +#ifdef USE_GLES_OVER_GL +#define mediump +#define highp +#else +precision mediump float; +precision mediump int; +#endif + +attribute highp vec4 vertex_attrib; // attrib:0 +attribute vec2 uv_in; // attrib:4 +attribute vec2 uv2_in; // attrib:5 + +varying vec2 uv_interp; + +varying vec2 uv2_interp; + +#ifdef USE_COPY_SECTION +uniform vec4 copy_section; +#endif + +void main() { + + uv_interp = uv_in; + uv2_interp = uv2_in; + gl_Position = vertex_attrib; + +#ifdef USE_COPY_SECTION + uv_interp = copy_section.xy + uv_interp * copy_section.zw; + gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; +#endif +} + +[fragment] + +#ifdef USE_GLES_OVER_GL +#define mediump +#define highp +#else +precision mediump float; +precision mediump int; +#endif + + +varying vec2 uv_interp; +uniform sampler2D source; // texunit:0 + +varying vec2 uv2_interp; + +#ifdef USE_CUSTOM_ALPHA +uniform float custom_alpha; +#endif + + +void main() { + + //vec4 color = color_interp; + vec4 color = texture2D( source, uv_interp ); + + +#ifdef USE_NO_ALPHA + color.a=1.0; +#endif + +#ifdef USE_CUSTOM_ALPHA + color.a=custom_alpha; +#endif + + + gl_FragColor = color; +} diff --git a/drivers/gles2/shaders/cube_to_dp.glsl b/drivers/gles2/shaders/cube_to_dp.glsl new file mode 100644 index 0000000000..5ffc78c0b9 --- /dev/null +++ b/drivers/gles2/shaders/cube_to_dp.glsl @@ -0,0 +1,79 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +} + +[fragment] + + +uniform highp samplerCube source_cube; //texunit:0 +in vec2 uv_interp; + +uniform bool z_flip; +uniform highp float z_far; +uniform highp float z_near; +uniform highp float bias; + +void main() { + + highp vec3 normal = vec3( uv_interp * 2.0 - 1.0, 0.0 ); +/* + if(z_flip) { + normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + } else { + normal.z = -0.5 + 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + } +*/ + + //normal.z = sqrt(1.0-dot(normal.xy,normal.xy)); + //normal.xy*=1.0+normal.z; + + normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + normal = normalize(normal); + +/* + normal.z=0.5; + normal=normalize(normal); +*/ + if (!z_flip) { + normal.z=-normal.z; + } + + //normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 )); + float depth = texture(source_cube,normal).r; + + // absolute values for direction cosines, bigger value equals closer to basis axis + vec3 unorm = abs(normal); + + if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) { + // x code + unorm = normal.x > 0.0 ? vec3( 1.0, 0.0, 0.0 ) : vec3( -1.0, 0.0, 0.0 ) ; + } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) { + // y code + unorm = normal.y > 0.0 ? vec3( 0.0, 1.0, 0.0 ) : vec3( 0.0, -1.0, 0.0 ) ; + } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) { + // z code + unorm = normal.z > 0.0 ? vec3( 0.0, 0.0, 1.0 ) : vec3( 0.0, 0.0, -1.0 ) ; + } else { + // oh-no we messed up code + // has to be + unorm = vec3( 1.0, 0.0, 0.0 ); + } + + float depth_fix = 1.0 / dot(normal,unorm); + + + depth = 2.0 * depth - 1.0; + float linear_depth = 2.0 * z_near * z_far / (z_far + z_near - depth * (z_far - z_near)); + gl_FragDepth = (linear_depth*depth_fix+bias) / z_far; +} + diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl new file mode 100644 index 0000000000..485fbb6ee0 --- /dev/null +++ b/drivers/gles2/shaders/cubemap_filter.glsl @@ -0,0 +1,294 @@ +[vertex] + + +layout(location=0) in highp vec2 vertex; + +layout(location=4) in highp vec2 uv; + +out highp vec2 uv_interp; + +void main() { + + uv_interp=uv; + gl_Position=vec4(vertex,0,1); +} + +[fragment] + + +precision highp float; +precision highp int; + +#ifdef USE_SOURCE_PANORAMA +uniform sampler2D source_panorama; //texunit:0 +#endif + +#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY +uniform sampler2DArray source_dual_paraboloid_array; //texunit:0 +uniform int source_array_index; +#endif + +#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) +uniform samplerCube source_cube; //texunit:0 +#endif + +uniform int face_id; +uniform float roughness; +in highp vec2 uv_interp; + + +layout(location = 0) out vec4 frag_color; + + +#define M_PI 3.14159265359 + + +vec3 texelCoordToVec(vec2 uv, int faceID) +{ + mat3 faceUvVectors[6]; +/* + // -x + faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face + + // +x + faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z + faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face + + // -y + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z + faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face + + // +y + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face + + // -z + faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x + faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face + + // +z + faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face +*/ + + // -x + faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face + + // +x + faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z + faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face + + // -y + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z + faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face + + // +y + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face + + // -z + faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x + faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face + + // +z + faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face + + // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. + vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; + return normalize(result); +} + +vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) +{ + float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] + + // Compute distribution direction + float Phi = 2.0 * M_PI * Xi.x; + float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float SinTheta = sqrt(1.0 - CosTheta * CosTheta); + + // Convert to spherical direction + vec3 H; + H.x = SinTheta * cos(Phi); + H.y = SinTheta * sin(Phi); + H.z = CosTheta; + + vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 TangentX = normalize(cross(UpVector, N)); + vec3 TangentY = cross(N, TangentX); + + // Tangent to world space + return TangentX * H.x + TangentY * H.y + N * H.z; +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float GGX(float NdotV, float a) +{ + float k = a / 2.0; + return NdotV / (NdotV * (1.0 - k) + k); +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float G_Smith(float a, float nDotV, float nDotL) +{ + return GGX(nDotL, a * a) * GGX(nDotV, a * a); +} + +float radicalInverse_VdC(uint bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +vec2 Hammersley(uint i, uint N) { + return vec2(float(i)/float(N), radicalInverse_VdC(i)); +} + + + +#ifdef LOW_QUALITY + +#define SAMPLE_COUNT 64u + +#else + +#define SAMPLE_COUNT 512u + +#endif + +uniform bool z_flip; + +#ifdef USE_SOURCE_PANORAMA + +vec4 texturePanorama(vec3 normal,sampler2D pano ) { + + vec2 st = vec2( + atan(normal.x, normal.z), + acos(normal.y) + ); + + if(st.x < 0.0) + st.x += M_PI*2.0; + + st/=vec2(M_PI*2.0,M_PI); + + return textureLod(pano,st,0.0); + +} + +#endif + +#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY + + +vec4 textureDualParaboloidArray(vec3 normal) { + + vec3 norm = normalize(normal); + norm.xy/=1.0+abs(norm.z); + norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25); + if (norm.z<0.0) { + norm.y=0.5-norm.y+0.5; + } + return textureLod(source_dual_paraboloid_array, vec3(norm.xy, float(source_array_index) ), 0.0); + +} + +#endif + +void main() { + +#ifdef USE_DUAL_PARABOLOID + + vec3 N = vec3( uv_interp * 2.0 - 1.0, 0.0 ); + N.z = 0.5 - 0.5*((N.x * N.x) + (N.y * N.y)); + N = normalize(N); + + if (z_flip) { + N.y=-N.y; //y is flipped to improve blending between both sides + N.z=-N.z; + } + + +#else + vec2 uv = (uv_interp * 2.0) - 1.0; + vec3 N = texelCoordToVec(uv, face_id); +#endif + //vec4 color = color_interp; + +#ifdef USE_DIRECT_WRITE + +#ifdef USE_SOURCE_PANORAMA + + frag_color=vec4(texturePanorama(N,source_panorama).rgb,1.0); +#endif + +#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY + + frag_color=vec4(textureDualParaboloidArray(N).rgb,1.0); +#endif + +#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) + + N.y=-N.y; + frag_color=vec4(texture(N,source_cube).rgb,1.0); +#endif + + + + +#else + + vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); + + for(uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) { + vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT); + + vec3 H = ImportanceSampleGGX( xi, roughness, N ); + vec3 V = N; + vec3 L = normalize(2.0 * dot( V, H ) * H - V); + + float ndotl = clamp(dot(N, L),0.0,1.0); + + if (ndotl>0.0) { +#ifdef USE_SOURCE_PANORAMA + sum.rgb += texturePanorama(H,source_panorama).rgb *ndotl; +#endif + +#ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY + + sum.rgb += textureDualParaboloidArray(H).rgb *ndotl; +#endif + +#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) + H.y=-H.y; + sum.rgb += textureLod(source_cube, H, 0.0).rgb *ndotl; +#endif + sum.a += ndotl; + } + } + sum /= sum.a; + + frag_color = vec4(sum.rgb, 1.0); + +#endif + +} + diff --git a/drivers/gles2/shaders/effect_blur.glsl b/drivers/gles2/shaders/effect_blur.glsl new file mode 100644 index 0000000000..b5f98a1244 --- /dev/null +++ b/drivers/gles2/shaders/effect_blur.glsl @@ -0,0 +1,301 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + +#ifdef USE_BLUR_SECTION + +uniform vec4 blur_section; + +#endif + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +#ifdef USE_BLUR_SECTION + + uv_interp = blur_section.xy + uv_interp * blur_section.zw; + gl_Position.xy = (blur_section.xy + (gl_Position.xy * 0.5 + 0.5) * blur_section.zw) * 2.0 - 1.0; +#endif +} + +[fragment] + +#if !defined(GLES_OVER_GL) +precision mediump float; +#endif + +in vec2 uv_interp; +uniform sampler2D source_color; //texunit:0 + +#ifdef SSAO_MERGE +uniform sampler2D source_ssao; //texunit:1 +#endif + +uniform float lod; +uniform vec2 pixel_size; + + +layout(location = 0) out vec4 frag_color; + +#ifdef SSAO_MERGE + +uniform vec4 ssao_color; + +#endif + +#if defined (GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL) + +uniform float glow_strength; + +#endif + +#if defined(DOF_FAR_BLUR) || defined (DOF_NEAR_BLUR) + +#ifdef DOF_QUALITY_LOW +const int dof_kernel_size=5; +const int dof_kernel_from=2; +const float dof_kernel[5] = float[] (0.153388,0.221461,0.250301,0.221461,0.153388); +#endif + +#ifdef DOF_QUALITY_MEDIUM +const int dof_kernel_size=11; +const int dof_kernel_from=5; +const float dof_kernel[11] = float[] (0.055037,0.072806,0.090506,0.105726,0.116061,0.119726,0.116061,0.105726,0.090506,0.072806,0.055037); + +#endif + +#ifdef DOF_QUALITY_HIGH +const int dof_kernel_size=21; +const int dof_kernel_from=10; +const float dof_kernel[21] = float[] (0.028174,0.032676,0.037311,0.041944,0.046421,0.050582,0.054261,0.057307,0.059587,0.060998,0.061476,0.060998,0.059587,0.057307,0.054261,0.050582,0.046421,0.041944,0.037311,0.032676,0.028174); +#endif + +uniform sampler2D dof_source_depth; //texunit:1 +uniform float dof_begin; +uniform float dof_end; +uniform vec2 dof_dir; +uniform float dof_radius; + +#ifdef DOF_NEAR_BLUR_MERGE + +uniform sampler2D source_dof_original; //texunit:2 +#endif + +#endif + + +#ifdef GLOW_FIRST_PASS + +uniform float exposure; +uniform float white; + +#ifdef GLOW_USE_AUTO_EXPOSURE + +uniform highp sampler2D source_auto_exposure; //texunit:1 +uniform highp float auto_exposure_grey; + +#endif + +uniform float glow_bloom; +uniform float glow_hdr_threshold; +uniform float glow_hdr_scale; + +#endif + +uniform float camera_z_far; +uniform float camera_z_near; + +void main() { + + + +#ifdef GAUSSIAN_HORIZONTAL + vec2 pix_size = pixel_size; + pix_size*=0.5; //reading from larger buffer, so use more samples + vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.214607; + color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.189879; + color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.157305; + color+=textureLod( source_color, uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.071303; + color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.189879; + color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.157305; + color+=textureLod( source_color, uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.071303; + frag_color = color; +#endif + +#ifdef GAUSSIAN_VERTICAL + vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.38774; + color+=textureLod( source_color, uv_interp+vec2( 0.0, 1.0)*pixel_size,lod )*0.24477; + color+=textureLod( source_color, uv_interp+vec2( 0.0, 2.0)*pixel_size,lod )*0.06136; + color+=textureLod( source_color, uv_interp+vec2( 0.0,-1.0)*pixel_size,lod )*0.24477; + color+=textureLod( source_color, uv_interp+vec2( 0.0,-2.0)*pixel_size,lod )*0.06136; + frag_color = color; +#endif + +//glow uses larger sigma for a more rounded blur effect + +#ifdef GLOW_GAUSSIAN_HORIZONTAL + vec2 pix_size = pixel_size; + pix_size*=0.5; //reading from larger buffer, so use more samples + vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.174938; + color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.165569; + color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.140367; + color+=textureLod( source_color, uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.106595; + color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.165569; + color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.140367; + color+=textureLod( source_color, uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.106595; + color*=glow_strength; + frag_color = color; +#endif + +#ifdef GLOW_GAUSSIAN_VERTICAL + vec4 color =textureLod( source_color, uv_interp+vec2(0.0, 0.0)*pixel_size,lod )*0.288713; + color+=textureLod( source_color, uv_interp+vec2(0.0, 1.0)*pixel_size,lod )*0.233062; + color+=textureLod( source_color, uv_interp+vec2(0.0, 2.0)*pixel_size,lod )*0.122581; + color+=textureLod( source_color, uv_interp+vec2(0.0,-1.0)*pixel_size,lod )*0.233062; + color+=textureLod( source_color, uv_interp+vec2(0.0,-2.0)*pixel_size,lod )*0.122581; + color*=glow_strength; + frag_color = color; +#endif + +#ifdef DOF_FAR_BLUR + + vec4 color_accum = vec4(0.0); + + float depth = textureLod( dof_source_depth, uv_interp, 0.0).r; + depth = depth * 2.0 - 1.0; +#ifdef USE_ORTHOGONAL_PROJECTION + depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#else + depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); +#endif + + float amount = smoothstep(dof_begin,dof_end,depth); + float k_accum=0.0; + + for(int i=0;i<dof_kernel_size;i++) { + + int int_ofs = i-dof_kernel_from; + vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius; + + float tap_k = dof_kernel[i]; + + float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r; + tap_depth = tap_depth * 2.0 - 1.0; +#ifdef USE_ORTHOGONAL_PROJECTION + tap_depth = ((tap_depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#else + tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near)); +#endif + float tap_amount = mix(smoothstep(dof_begin,dof_end,tap_depth),1.0,int_ofs==0); + tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect + + vec4 tap_color = textureLod( source_color, tap_uv, 0.0) * tap_k; + + k_accum+=tap_k*tap_amount; + color_accum+=tap_color*tap_amount; + + + } + + if (k_accum>0.0) { + color_accum/=k_accum; + } + + frag_color = color_accum;///k_accum; + +#endif + +#ifdef DOF_NEAR_BLUR + + vec4 color_accum = vec4(0.0); + + float max_accum=0; + + for(int i=0;i<dof_kernel_size;i++) { + + int int_ofs = i-dof_kernel_from; + vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius; + float ofs_influence = max(0.0,1.0-float(abs(int_ofs))/float(dof_kernel_from)); + + float tap_k = dof_kernel[i]; + + vec4 tap_color = textureLod( source_color, tap_uv, 0.0); + + float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r; + tap_depth = tap_depth * 2.0 - 1.0; +#ifdef USE_ORTHOGONAL_PROJECTION + tap_depth = ((tap_depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#else + tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near)); +#endif + float tap_amount = 1.0-smoothstep(dof_end,dof_begin,tap_depth); + tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect + +#ifdef DOF_NEAR_FIRST_TAP + + tap_color.a= 1.0-smoothstep(dof_end,dof_begin,tap_depth); + +#endif + + max_accum=max(max_accum,tap_amount*ofs_influence); + + color_accum+=tap_color*tap_k; + + } + + color_accum.a=max(color_accum.a,sqrt(max_accum)); + + +#ifdef DOF_NEAR_BLUR_MERGE + + vec4 original = textureLod( source_dof_original, uv_interp, 0.0); + color_accum = mix(original,color_accum,color_accum.a); + +#endif + +#ifndef DOF_NEAR_FIRST_TAP + //color_accum=vec4(vec3(color_accum.a),1.0); +#endif + frag_color = color_accum; + +#endif + + + +#ifdef GLOW_FIRST_PASS + +#ifdef GLOW_USE_AUTO_EXPOSURE + + frag_color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey; +#endif + frag_color*=exposure; + + float luminance = max(frag_color.r,max(frag_color.g,frag_color.b)); + float feedback = max( smoothstep(glow_hdr_threshold,glow_hdr_threshold+glow_hdr_scale,luminance), glow_bloom ); + + frag_color *= feedback; + +#endif + + +#ifdef SIMPLE_COPY + vec4 color =textureLod( source_color, uv_interp,0.0); + frag_color = color; +#endif + +#ifdef SSAO_MERGE + + vec4 color =textureLod( source_color, uv_interp,0.0); + float ssao =textureLod( source_ssao, uv_interp,0.0).r; + + frag_color = vec4( mix(color.rgb,color.rgb*mix(ssao_color.rgb,vec3(1.0),ssao),color.a), 1.0 ); + +#endif + + +} diff --git a/drivers/gles2/shaders/exposure.glsl b/drivers/gles2/shaders/exposure.glsl new file mode 100644 index 0000000000..001b90a0f1 --- /dev/null +++ b/drivers/gles2/shaders/exposure.glsl @@ -0,0 +1,98 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + + +void main() { + + gl_Position = vertex_attrib; + +} + +[fragment] + + +uniform highp sampler2D source_exposure; //texunit:0 + +#ifdef EXPOSURE_BEGIN + +uniform highp ivec2 source_render_size; +uniform highp ivec2 target_size; + +#endif + +#ifdef EXPOSURE_END + +uniform highp sampler2D prev_exposure; //texunit:1 +uniform highp float exposure_adjust; +uniform highp float min_luminance; +uniform highp float max_luminance; + +#endif + +layout(location = 0) out highp float exposure; + + + +void main() { + + + +#ifdef EXPOSURE_BEGIN + + + ivec2 src_pos = ivec2(gl_FragCoord.xy)*source_render_size/target_size; + +#if 1 + //more precise and expensive, but less jittery + ivec2 next_pos = ivec2(gl_FragCoord.xy+ivec2(1))*source_render_size/target_size; + next_pos = max(next_pos,src_pos+ivec2(1)); //so it at least reads one pixel + highp vec3 source_color=vec3(0.0); + for(int i=src_pos.x;i<next_pos.x;i++) { + for(int j=src_pos.y;j<next_pos.y;j++) { + source_color += texelFetch(source_exposure,ivec2(i,j),0).rgb; + } + } + + source_color/=float( (next_pos.x-src_pos.x)*(next_pos.y-src_pos.y) ); +#else + highp vec3 source_color = texelFetch(source_exposure,src_pos,0).rgb; + +#endif + + exposure = max(source_color.r,max(source_color.g,source_color.b)); + +#else + + ivec2 coord = ivec2(gl_FragCoord.xy); + exposure = texelFetch(source_exposure,coord*3+ivec2(0,0),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(1,0),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(2,0),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(0,1),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(1,1),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(2,1),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(0,2),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(1,2),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(2,2),0).r; + exposure *= (1.0/9.0); + +#ifdef EXPOSURE_END + +#ifdef EXPOSURE_FORCE_SET + //will stay as is +#else + highp float prev_lum = texelFetch(prev_exposure,ivec2(0,0),0).r; //1 pixel previous exposure + exposure = clamp( prev_lum + (exposure-prev_lum)*exposure_adjust,min_luminance,max_luminance); + +#endif //EXPOSURE_FORCE_SET + + +#endif //EXPOSURE_END + +#endif //EXPOSURE_BEGIN + + +} + + diff --git a/drivers/gles2/shaders/particles.glsl b/drivers/gles2/shaders/particles.glsl new file mode 100644 index 0000000000..a62c124dfe --- /dev/null +++ b/drivers/gles2/shaders/particles.glsl @@ -0,0 +1,260 @@ +[vertex] + + + +layout(location=0) in highp vec4 color; +layout(location=1) in highp vec4 velocity_active; +layout(location=2) in highp vec4 custom; +layout(location=3) in highp vec4 xform_1; +layout(location=4) in highp vec4 xform_2; +layout(location=5) in highp vec4 xform_3; + + +struct Attractor { + + vec3 pos; + vec3 dir; + float radius; + float eat_radius; + float strength; + float attenuation; +}; + +#define MAX_ATTRACTORS 64 + +uniform bool emitting; +uniform float system_phase; +uniform float prev_system_phase; +uniform int total_particles; +uniform float explosiveness; +uniform float randomness; +uniform float time; +uniform float delta; + +uniform int attractor_count; +uniform Attractor attractors[MAX_ATTRACTORS]; +uniform bool clear; +uniform uint cycle; +uniform float lifetime; +uniform mat4 emission_transform; +uniform uint random_seed; + + +out highp vec4 out_color; //tfb: +out highp vec4 out_velocity_active; //tfb: +out highp vec4 out_custom; //tfb: +out highp vec4 out_xform_1; //tfb: +out highp vec4 out_xform_2; //tfb: +out highp vec4 out_xform_3; //tfb: + + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { //ubo:0 + +MATERIAL_UNIFORMS + +}; + +#endif + + +VERTEX_SHADER_GLOBALS + +uint hash(uint x) { + + x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); + x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); + x = (x >> uint(16)) ^ x; + return x; +} + + +void main() { + +#ifdef PARTICLES_COPY + + out_color=color; + out_velocity_active=velocity_active; + out_custom = custom; + out_xform_1 = xform_1; + out_xform_2 = xform_2; + out_xform_3 = xform_3; + +#else + + bool apply_forces=true; + bool apply_velocity=true; + float local_delta=delta; + + float mass = 1.0; + + float restart_phase = float(gl_VertexID)/float(total_particles); + + if (randomness>0.0) { + uint seed = cycle; + if (restart_phase >= system_phase) { + seed-=uint(1); + } + seed*=uint(total_particles); + seed+=uint(gl_VertexID); + float random = float(hash(seed) % uint(65536)) / 65536.0; + restart_phase+=randomness * random * 1.0 / float(total_particles); + } + + restart_phase*= (1.0-explosiveness); + bool restart=false; + bool shader_active = velocity_active.a > 0.5; + + if (system_phase > prev_system_phase) { + // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed + + if (restart_phase >= prev_system_phase && restart_phase < system_phase ) { + restart=true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (system_phase - restart_phase) * lifetime; +#endif + } + + } else { + if (restart_phase >= prev_system_phase) { + restart=true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (1.0 - restart_phase + system_phase) * lifetime; +#endif + } else if (restart_phase < system_phase ) { + restart=true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (system_phase - restart_phase) * lifetime; +#endif + } + } + + uint current_cycle = cycle; + + if (system_phase < restart_phase) { + current_cycle-=uint(1); + } + + uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID); + int index = int(gl_VertexID); + + if (restart) { + shader_active=emitting; + } + + mat4 xform; + +#if defined(ENABLE_KEEP_DATA) + if (clear) { +#else + if (clear || restart) { +#endif + out_color=vec4(1.0); + out_velocity_active=vec4(0.0); + out_custom=vec4(0.0); + if (!restart) + shader_active=false; + + xform = mat4( + vec4(1.0,0.0,0.0,0.0), + vec4(0.0,1.0,0.0,0.0), + vec4(0.0,0.0,1.0,0.0), + vec4(0.0,0.0,0.0,1.0) + ); + } else { + out_color=color; + out_velocity_active=velocity_active; + out_custom=custom; + xform = transpose(mat4(xform_1,xform_2,xform_3,vec4(vec3(0.0),1.0))); + } + + if (shader_active) { + //execute shader + + { +VERTEX_SHADER_CODE + } + +#if !defined(DISABLE_FORCE) + + if (false) { + + vec3 force = vec3(0.0); + for(int i=0;i<attractor_count;i++) { + + vec3 rel_vec = xform[3].xyz - attractors[i].pos; + float dist = length(rel_vec); + if (attractors[i].radius < dist) + continue; + if (attractors[i].eat_radius>0.0 && attractors[i].eat_radius > dist) { + out_velocity_active.a=0.0; + } + + rel_vec = normalize(rel_vec); + + float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation); + + if (attractors[i].dir==vec3(0.0)) { + //towards center + force+=attractors[i].strength * rel_vec * attenuation * mass; + } else { + force+=attractors[i].strength * attractors[i].dir * attenuation *mass; + + } + } + + out_velocity_active.xyz += force * local_delta; + } +#endif + +#if !defined(DISABLE_VELOCITY) + + if (true) { + + xform[3].xyz += out_velocity_active.xyz * local_delta; + } +#endif + } else { + xform=mat4(0.0); + } + + xform = transpose(xform); + + out_velocity_active.a = mix(0.0,1.0,shader_active); + + out_xform_1 = xform[0]; + out_xform_2 = xform[1]; + out_xform_3 = xform[2]; + +#endif //PARTICLES_COPY + +} + +[fragment] + +//any code here is never executed, stuff is filled just so it works + + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { + +MATERIAL_UNIFORMS + +}; + +#endif + +FRAGMENT_SHADER_GLOBALS + +void main() { + + { +LIGHT_SHADER_CODE + } + + { +FRAGMENT_SHADER_CODE + } +} diff --git a/drivers/gles2/shaders/resolve.glsl b/drivers/gles2/shaders/resolve.glsl new file mode 100644 index 0000000000..0b50a9c57b --- /dev/null +++ b/drivers/gles2/shaders/resolve.glsl @@ -0,0 +1,44 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +} + +[fragment] + +#if !defined(GLES_OVER_GL) +precision mediump float; +#endif + +in vec2 uv_interp; +uniform sampler2D source_specular; //texunit:0 +uniform sampler2D source_ssr; //texunit:1 + +uniform vec2 pixel_size; + +in vec2 uv2_interp; + +layout(location = 0) out vec4 frag_color; + +void main() { + + vec4 specular = texture( source_specular, uv_interp ); + +#ifdef USE_SSR + + vec4 ssr = textureLod(source_ssr,uv_interp,0.0); + specular.rgb = mix(specular.rgb,ssr.rgb*specular.a,ssr.a); +#endif + + frag_color = vec4(specular.rgb,1.0); +} + diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl new file mode 100644 index 0000000000..79b989be4a --- /dev/null +++ b/drivers/gles2/shaders/scene.glsl @@ -0,0 +1,2113 @@ +[vertex] + +#define M_PI 3.14159265359 + +/* +from VisualServer: + +ARRAY_VERTEX=0, +ARRAY_NORMAL=1, +ARRAY_TANGENT=2, +ARRAY_COLOR=3, +ARRAY_TEX_UV=4, +ARRAY_TEX_UV2=5, +ARRAY_BONES=6, +ARRAY_WEIGHTS=7, +ARRAY_INDEX=8, +*/ + +//hack to use uv if no uv present so it works with lightmap + + +/* INPUT ATTRIBS */ + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=1) in vec3 normal_attrib; +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) +layout(location=2) in vec4 tangent_attrib; +#endif + +#if defined(ENABLE_COLOR_INTERP) +layout(location=3) in vec4 color_attrib; +#endif + +#if defined(ENABLE_UV_INTERP) +layout(location=4) in vec2 uv_attrib; +#endif + +#if defined(ENABLE_UV2_INTERP) +layout(location=5) in vec2 uv2_attrib; +#endif + +uniform float normal_mult; + +#ifdef USE_SKELETON +layout(location=6) in ivec4 bone_indices; // attrib:6 +layout(location=7) in vec4 bone_weights; // attrib:7 +#endif + +#ifdef USE_INSTANCING + +layout(location=8) in highp vec4 instance_xform0; +layout(location=9) in highp vec4 instance_xform1; +layout(location=10) in highp vec4 instance_xform2; +layout(location=11) in lowp vec4 instance_color; + +#if defined(ENABLE_INSTANCE_CUSTOM) +layout(location=12) in highp vec4 instance_custom_data; +#endif + +#endif + +layout(std140) uniform SceneData { //ubo:0 + + highp mat4 projection_matrix; + highp mat4 inv_projection_matrix; + highp mat4 camera_inverse_matrix; + highp mat4 camera_matrix; + + mediump vec4 ambient_light_color; + mediump vec4 bg_color; + + mediump vec4 fog_color_enabled; + mediump vec4 fog_sun_color_amount; + + mediump float ambient_energy; + mediump float bg_energy; + + mediump float z_offset; + mediump float z_slope_scale; + highp float shadow_dual_paraboloid_render_zfar; + highp float shadow_dual_paraboloid_render_side; + + highp vec2 viewport_size; + highp vec2 screen_pixel_size; + highp vec2 shadow_atlas_pixel_size; + highp vec2 directional_shadow_pixel_size; + + highp float time; + highp float z_far; + mediump float reflection_multiplier; + mediump float subsurface_scatter_width; + mediump float ambient_occlusion_affect_light; + + bool fog_depth_enabled; + highp float fog_depth_begin; + highp float fog_depth_curve; + bool fog_transmit_enabled; + highp float fog_transmit_curve; + bool fog_height_enabled; + highp float fog_height_min; + highp float fog_height_max; + highp float fog_height_curve; + +}; + +uniform highp mat4 world_transform; + + +#ifdef USE_LIGHT_DIRECTIONAL + +layout(std140) uniform DirectionalLightData { //ubo:3 + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, + mediump vec4 light_clamp; + mediump vec4 shadow_color_contact; + highp mat4 shadow_matrix1; + highp mat4 shadow_matrix2; + highp mat4 shadow_matrix3; + highp mat4 shadow_matrix4; + mediump vec4 shadow_split_offsets; +}; + +#endif + +#ifdef USE_VERTEX_LIGHTING +//omni and spot + +struct LightData { + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, + mediump vec4 light_clamp; + mediump vec4 shadow_color_contact; + highp mat4 shadow_matrix; + +}; + + +layout(std140) uniform OmniLightData { //ubo:4 + + LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + +layout(std140) uniform SpotLightData { //ubo:5 + + LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + +#ifdef USE_FORWARD_LIGHTING + + +uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; +uniform int omni_light_count; + +uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; +uniform int spot_light_count; + +#endif + +out vec4 diffuse_light_interp; +out vec4 specular_light_interp; + +void light_compute(vec3 N, vec3 L,vec3 V, vec3 light_color, float roughness, inout vec3 diffuse, inout vec3 specular) { + + float dotNL = max(dot(N,L), 0.0 ); + diffuse += dotNL * light_color / M_PI; + + if (roughness > 0.0) { + + vec3 H = normalize(V + L); + float dotNH = max(dot(N,H), 0.0 ); + float intensity = pow( dotNH, (1.0-roughness) * 256.0); + specular += light_color * intensity; + + } +} + +void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal, float roughness,inout vec3 diffuse, inout vec3 specular) { + + vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; + float light_length = length( light_rel_vec ); + float normalized_distance = light_length*omni_lights[idx].light_pos_inv_radius.w; + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w )); + + light_compute(normal,normalize(light_rel_vec),eye_vec,omni_lights[idx].light_color_energy.rgb * light_attenuation,roughness,diffuse,specular); + +} + +void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness, inout vec3 diffuse, inout vec3 specular) { + + vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex; + float light_length = length( light_rel_vec ); + float normalized_distance = light_length*spot_lights[idx].light_pos_inv_radius.w; + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.001), spot_lights[idx].light_direction_attenuation.w )); + vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz; + float spot_cutoff=spot_lights[idx].light_params.y; + float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff); + float spot_rim = (1.0 - scos) / (1.0 - spot_cutoff); + light_attenuation *= 1.0 - pow( max(spot_rim,0.001), spot_lights[idx].light_params.x); + + + light_compute(normal,normalize(light_rel_vec),eye_vec,spot_lights[idx].light_color_energy.rgb*light_attenuation,roughness,diffuse,specular); +} + + +#endif + +/* Varyings */ + +out highp vec3 vertex_interp; +out vec3 normal_interp; + +#if defined(ENABLE_COLOR_INTERP) +out vec4 color_interp; +#endif + +#if defined(ENABLE_UV_INTERP) +out vec2 uv_interp; +#endif + +#if defined(ENABLE_UV2_INTERP) +out vec2 uv2_interp; +#endif + + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) +out vec3 tangent_interp; +out vec3 binormal_interp; +#endif + + + + + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { //ubo:1 + +MATERIAL_UNIFORMS + +}; + +#endif + +VERTEX_SHADER_GLOBALS + +#ifdef RENDER_DEPTH_DUAL_PARABOLOID + +out highp float dp_clip; + +#endif + +#define SKELETON_TEXTURE_WIDTH 256 + +#ifdef USE_SKELETON +uniform highp sampler2D skeleton_texture; //texunit:-1 +#endif + +out highp vec4 position_interp; + +// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now. +// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316 +//invariant gl_Position; + +void main() { + + highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); + + mat4 world_matrix = world_transform; + + +#ifdef USE_INSTANCING + + { + highp mat4 m=mat4(instance_xform0,instance_xform1,instance_xform2,vec4(0.0,0.0,0.0,1.0)); + world_matrix = world_matrix * transpose(m); + } +#endif + + vec3 normal = normal_attrib * normal_mult; + + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + vec3 tangent = tangent_attrib.xyz; + tangent*=normal_mult; + float binormalf = tangent_attrib.a; +#endif + +#if defined(ENABLE_COLOR_INTERP) + color_interp = color_attrib; +#if defined(USE_INSTANCING) + color_interp *= instance_color; +#endif + +#endif + +#ifdef USE_SKELETON + { + //skeleton transform + ivec2 tex_ofs = ivec2( bone_indices.x%256, (bone_indices.x/256)*3 ); + highp mat3x4 m = mat3x4( + texelFetch(skeleton_texture,tex_ofs,0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,2),0) + ) * bone_weights.x; + + tex_ofs = ivec2( bone_indices.y%256, (bone_indices.y/256)*3 ); + + m+= mat3x4( + texelFetch(skeleton_texture,tex_ofs,0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,2),0) + ) * bone_weights.y; + + tex_ofs = ivec2( bone_indices.z%256, (bone_indices.z/256)*3 ); + + m+= mat3x4( + texelFetch(skeleton_texture,tex_ofs,0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,2),0) + ) * bone_weights.z; + + + tex_ofs = ivec2( bone_indices.w%256, (bone_indices.w/256)*3 ); + + m+= mat3x4( + texelFetch(skeleton_texture,tex_ofs,0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,2),0) + ) * bone_weights.w; + + + vertex.xyz = vertex * m; + + normal = vec4(normal,0.0) * m; +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + tangent.xyz = vec4(tangent.xyz,0.0) * m; +#endif + } +#endif + + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + + vec3 binormal = normalize( cross(normal,tangent) * binormalf ); +#endif + +#if defined(ENABLE_UV_INTERP) + uv_interp = uv_attrib; +#endif + +#if defined(ENABLE_UV2_INTERP) + uv2_interp = uv2_attrib; +#endif + +#if defined(USE_INSTANCING) && defined(ENABLE_INSTANCE_CUSTOM) + vec4 instance_custom = instance_custom_data; +#else + vec4 instance_custom = vec4(0.0); +#endif + + highp mat4 modelview = camera_inverse_matrix * world_matrix; + highp mat4 local_projection = projection_matrix; + +//using world coordinates +#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) + + vertex = world_matrix * vertex; + normal = normalize((world_matrix * vec4(normal,0.0)).xyz); + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + + tangent = normalize((world_matrix * vec4(tangent,0.0)).xyz); + binormal = normalize((world_matrix * vec4(binormal,0.0)).xyz); +#endif +#endif + + float roughness=0.0; + +//defines that make writing custom shaders easier +#define projection_matrix local_projection +#define world_transform world_matrix +{ + +VERTEX_SHADER_CODE + +} + + + +//using local coordinates (default) +#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) + + vertex = modelview * vertex; + normal = normalize((modelview * vec4(normal,0.0)).xyz); + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + + tangent = normalize((modelview * vec4(tangent,0.0)).xyz); + binormal = normalize((modelview * vec4(binormal,0.0)).xyz); +#endif +#endif + +//using world coordinates +#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) + + vertex = camera_inverse_matrix * vertex; + normal = normalize((camera_inverse_matrix * vec4(normal,0.0)).xyz); + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + + tangent = normalize((camera_inverse_matrix * vec4(tangent,0.0)).xyz); + binormal = normalize((camera_inverse_matrix * vec4(binormal,0.0)).xyz); +#endif +#endif + + vertex_interp = vertex.xyz; + normal_interp = normal; + + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + tangent_interp = tangent; + binormal_interp = binormal; +#endif + + +#ifdef RENDER_DEPTH + + +#ifdef RENDER_DEPTH_DUAL_PARABOLOID + + vertex_interp.z*= shadow_dual_paraboloid_render_side; + normal_interp.z*= shadow_dual_paraboloid_render_side; + + dp_clip=vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias + + //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges + + highp vec3 vtx = vertex_interp+normalize(vertex_interp)*z_offset; + highp float distance = length(vtx); + vtx = normalize(vtx); + vtx.xy/=1.0-vtx.z; + vtx.z=(distance/shadow_dual_paraboloid_render_zfar); + vtx.z=vtx.z * 2.0 - 1.0; + + vertex.xyz=vtx; + vertex.w=1.0; + + +#else + + float z_ofs = z_offset; + z_ofs += (1.0-abs(normal_interp.z))*z_slope_scale; + vertex_interp.z-=z_ofs; + +#endif //RENDER_DEPTH_DUAL_PARABOLOID + +#endif //RENDER_DEPTH + + gl_Position = projection_matrix * vec4(vertex_interp,1.0); + + position_interp=gl_Position; + +#ifdef USE_VERTEX_LIGHTING + + diffuse_light_interp=vec4(0.0); + specular_light_interp=vec4(0.0); + +#ifdef USE_FORWARD_LIGHTING + + for(int i=0;i<omni_light_count;i++) { + light_process_omni(omni_light_indices[i],vertex_interp,-normalize( vertex_interp ),normal_interp,roughness,diffuse_light_interp.rgb,specular_light_interp.rgb); + } + + for(int i=0;i<spot_light_count;i++) { + light_process_spot(spot_light_indices[i],vertex_interp,-normalize( vertex_interp ),normal_interp,roughness,diffuse_light_interp.rgb,specular_light_interp.rgb); + } +#endif + +#ifdef USE_LIGHT_DIRECTIONAL + + vec3 directional_diffuse = vec3(0.0); + vec3 directional_specular = vec3(0.0); + light_compute(normal_interp,-light_direction_attenuation.xyz,-normalize( vertex_interp ),light_color_energy.rgb,roughness,directional_diffuse,directional_specular); + + float diff_avg = dot(diffuse_light_interp.rgb,vec3(0.33333)); + float diff_dir_avg = dot(directional_diffuse,vec3(0.33333)); + if (diff_avg>0.0) { + diffuse_light_interp.a=diff_dir_avg/(diff_avg+diff_dir_avg); + } else { + diffuse_light_interp.a=1.0; + } + + diffuse_light_interp.rgb+=directional_diffuse; + + float spec_avg = dot(specular_light_interp.rgb,vec3(0.33333)); + float spec_dir_avg = dot(directional_specular,vec3(0.33333)); + if (spec_avg>0.0) { + specular_light_interp.a=spec_dir_avg/(spec_avg+spec_dir_avg); + } else { + specular_light_interp.a=1.0; + } + + specular_light_interp.rgb+=directional_specular; + +#endif //USE_LIGHT_DIRECTIONAL + + +#endif // USE_VERTEX_LIGHTING + +} + + +[fragment] + +/* texture unit usage, N is max_texture_unity-N + +1-skeleton +2-radiance +3-reflection_atlas +4-directional_shadow +5-shadow_atlas +6-decal_atlas +7-screen +8-depth +9-probe1 +10-probe2 + +*/ + +uniform highp mat4 world_transform; + +#define M_PI 3.14159265359 + +/* Varyings */ + +#if defined(ENABLE_COLOR_INTERP) +in vec4 color_interp; +#endif + +#if defined(ENABLE_UV_INTERP) +in vec2 uv_interp; +#endif + +#if defined(ENABLE_UV2_INTERP) +in vec2 uv2_interp; +#endif + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) +in vec3 tangent_interp; +in vec3 binormal_interp; +#endif + +in highp vec3 vertex_interp; +in vec3 normal_interp; + + +/* PBR CHANNELS */ + +//used on forward mainly +uniform bool no_ambient_light; + + + +#ifdef USE_RADIANCE_MAP + + + +layout(std140) uniform Radiance { //ubo:2 + + mat4 radiance_inverse_xform; + float radiance_ambient_contribution; + +}; + +#define RADIANCE_MAX_LOD 5.0 + +#ifdef USE_RADIANCE_MAP_ARRAY + +uniform sampler2DArray radiance_map; //texunit:-2 + +vec3 textureDualParaboloid(sampler2DArray p_tex, vec3 p_vec,float p_roughness) { + + vec3 norm = normalize(p_vec); + norm.xy/=1.0+abs(norm.z); + norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25); + + // we need to lie the derivatives (normg) and assume that DP side is always the same + // to get proper texture filtering + vec2 normg=norm.xy; + if (norm.z>0.0) { + norm.y=0.5-norm.y+0.5; + } + + // thanks to OpenGL spec using floor(layer + 0.5) for texture arrays, + // it's easy to have precision errors using fract() to interpolate layers + // as such, using fixed point to ensure it works. + + float index = p_roughness * RADIANCE_MAX_LOD; + int indexi = int(index * 256.0); + vec3 base = textureGrad(p_tex, vec3(norm.xy, float(indexi/256)),dFdx(normg),dFdy(normg)).xyz; + vec3 next = textureGrad(p_tex, vec3(norm.xy, float(indexi/256+1)),dFdx(normg),dFdy(normg)).xyz; + return mix(base,next,float(indexi%256)/256.0); +} + +#else + +uniform sampler2D radiance_map; //texunit:-2 + +vec3 textureDualParaboloid(sampler2D p_tex, vec3 p_vec,float p_roughness) { + + vec3 norm = normalize(p_vec); + norm.xy/=1.0+abs(norm.z); + norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25); + if (norm.z>0.0) { + norm.y=0.5-norm.y+0.5; + } + return textureLod(p_tex, norm.xy, p_roughness * RADIANCE_MAX_LOD).xyz; +} + +#endif + +#endif + +/* Material Uniforms */ + + + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { + +MATERIAL_UNIFORMS + +}; + +#endif + +FRAGMENT_SHADER_GLOBALS + +layout(std140) uniform SceneData { + + highp mat4 projection_matrix; + highp mat4 inv_projection_matrix; + highp mat4 camera_inverse_matrix; + highp mat4 camera_matrix; + + mediump vec4 ambient_light_color; + mediump vec4 bg_color; + + mediump vec4 fog_color_enabled; + mediump vec4 fog_sun_color_amount; + + mediump float ambient_energy; + mediump float bg_energy; + + mediump float z_offset; + mediump float z_slope_scale; + highp float shadow_dual_paraboloid_render_zfar; + highp float shadow_dual_paraboloid_render_side; + + highp vec2 viewport_size; + highp vec2 screen_pixel_size; + highp vec2 shadow_atlas_pixel_size; + highp vec2 directional_shadow_pixel_size; + + highp float time; + highp float z_far; + mediump float reflection_multiplier; + mediump float subsurface_scatter_width; + mediump float ambient_occlusion_affect_light; + + bool fog_depth_enabled; + highp float fog_depth_begin; + highp float fog_depth_curve; + bool fog_transmit_enabled; + highp float fog_transmit_curve; + bool fog_height_enabled; + highp float fog_height_min; + highp float fog_height_max; + highp float fog_height_curve; +}; + +//directional light data + +#ifdef USE_LIGHT_DIRECTIONAL + +layout(std140) uniform DirectionalLightData { + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, + mediump vec4 light_clamp; + mediump vec4 shadow_color_contact; + highp mat4 shadow_matrix1; + highp mat4 shadow_matrix2; + highp mat4 shadow_matrix3; + highp mat4 shadow_matrix4; + mediump vec4 shadow_split_offsets; +}; + + +uniform highp sampler2DShadow directional_shadow; //texunit:-4 + +#endif + +#ifdef USE_VERTEX_LIGHTING +in vec4 diffuse_light_interp; +in vec4 specular_light_interp; +#endif +//omni and spot + +struct LightData { + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, + mediump vec4 light_clamp; + mediump vec4 shadow_color_contact; + highp mat4 shadow_matrix; + +}; + + +layout(std140) uniform OmniLightData { //ubo:4 + + LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + +layout(std140) uniform SpotLightData { //ubo:5 + + LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + + +uniform highp sampler2DShadow shadow_atlas; //texunit:-5 + + +struct ReflectionData { + + mediump vec4 box_extents; + mediump vec4 box_offset; + mediump vec4 params; // intensity, 0, interior , boxproject + mediump vec4 ambient; //ambient color, energy + mediump vec4 atlas_clamp; + highp mat4 local_matrix; //up to here for spot and omni, rest is for directional + //notes: for ambientblend, use distance to edge to blend between already existing global environment +}; + +layout(std140) uniform ReflectionProbeData { //ubo:6 + + ReflectionData reflections[MAX_REFLECTION_DATA_STRUCTS]; +}; +uniform mediump sampler2D reflection_atlas; //texunit:-3 + + +#ifdef USE_FORWARD_LIGHTING + +uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; +uniform int omni_light_count; + +uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; +uniform int spot_light_count; + +uniform int reflection_indices[MAX_FORWARD_LIGHTS]; +uniform int reflection_count; + +#endif + + +#if defined(SCREEN_TEXTURE_USED) + +uniform highp sampler2D screen_texture; //texunit:-7 + +#endif + +#ifdef USE_MULTIPLE_RENDER_TARGETS + +layout(location=0) out vec4 diffuse_buffer; +layout(location=1) out vec4 specular_buffer; +layout(location=2) out vec4 normal_mr_buffer; +#if defined(ENABLE_SSS) +layout(location=3) out float sss_buffer; +#endif + +#else + +layout(location=0) out vec4 frag_color; + +#endif + +in highp vec4 position_interp; +uniform highp sampler2D depth_buffer; //texunit:-8 + +#ifdef USE_CONTACT_SHADOWS + +float contact_shadow_compute(vec3 pos, vec3 dir, float max_distance) { + + if (abs(dir.z)>0.99) + return 1.0; + + vec3 endpoint = pos+dir*max_distance; + vec4 source = position_interp; + vec4 dest = projection_matrix * vec4(endpoint, 1.0); + + vec2 from_screen = (source.xy / source.w) * 0.5 + 0.5; + vec2 to_screen = (dest.xy / dest.w) * 0.5 + 0.5; + + vec2 screen_rel = to_screen - from_screen; + + if (length(screen_rel)<0.00001) + return 1.0; //too small, don't do anything + + /*float pixel_size; //approximate pixel size + + if (screen_rel.x > screen_rel.y) { + + pixel_size = abs((pos.x-endpoint.x)/(screen_rel.x/screen_pixel_size.x)); + } else { + pixel_size = abs((pos.y-endpoint.y)/(screen_rel.y/screen_pixel_size.y)); + + }*/ + vec4 bias = projection_matrix * vec4(pos+vec3(0.0,0.0,0.04), 1.0); //todo un-harcode the 0.04 + + + + vec2 pixel_incr = normalize(screen_rel)*screen_pixel_size; + + + float steps = length(screen_rel) / length(pixel_incr); + steps = min(2000.0,steps); //put a limit to avoid freezing in some strange situation + //steps=10.0; + + vec4 incr = (dest - source)/steps; + float ratio=0.0; + float ratio_incr = 1.0/steps; + + while(steps>0.0) { + source += incr*2.0; + bias+=incr*2.0; + + vec3 uv_depth = (source.xyz / source.w) * 0.5 + 0.5; + float depth = texture(depth_buffer,uv_depth.xy).r; + + if (depth < uv_depth.z) { + if (depth > (bias.z/bias.w) * 0.5 + 0.5) { + return min(pow(ratio,4.0),1.0); + } else { + return 1.0; + } + } + + + ratio+=ratio_incr; + steps-=1.0; + } + + return 1.0; +} + +#endif + + +// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. +// We're dividing this factor off because the overall term we'll end up looks like +// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): +// +// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) +// +// We're basically regouping this as +// +// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] +// +// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. +// +// The contents of the D and G (G1) functions (GGX) are taken from +// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). +// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). + +float G_GGX_2cos(float cos_theta_m, float alpha) { + // Schlick's approximation + // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) + // Eq. (19), although see Heitz (2014) the about the problems with his derivation. + // It nevertheless approximates GGX well with k = alpha/2. + float k = 0.5*alpha; + return 0.5 / (cos_theta_m * (1.0 - k) + k); + + // float cos2 = cos_theta_m*cos_theta_m; + // float sin2 = (1.0-cos2); + // return 1.0 /( cos_theta_m + sqrt(cos2 + alpha*alpha*sin2) ); +} + +float D_GGX(float cos_theta_m, float alpha) { + float alpha2 = alpha*alpha; + float d = 1.0 + (alpha2-1.0)*cos_theta_m*cos_theta_m; + return alpha2/(M_PI * d * d); +} + +float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { + float cos2 = cos_theta_m * cos_theta_m; + float sin2 = (1.0-cos2); + float s_x = alpha_x * cos_phi; + float s_y = alpha_y * sin_phi; + return 1.0 / (cos_theta_m + sqrt(cos2 + (s_x*s_x + s_y*s_y)*sin2 )); +} + +float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { + float cos2 = cos_theta_m * cos_theta_m; + float sin2 = (1.0-cos2); + float r_x = cos_phi/alpha_x; + float r_y = sin_phi/alpha_y; + float d = cos2 + sin2*(r_x * r_x + r_y * r_y); + return 1.0 / (M_PI * alpha_x * alpha_y * d * d ); +} + + +float SchlickFresnel(float u) +{ + float m = 1.0-u; + float m2 = m*m; + return m2*m2*m; // pow(m,5) +} + +float GTR1(float NdotH, float a) +{ + if (a >= 1.0) return 1.0/M_PI; + float a2 = a*a; + float t = 1.0 + (a2-1.0)*NdotH*NdotH; + return (a2-1.0) / (M_PI*log(a2)*t); +} + +vec3 metallic_to_specular_color(float metallic, float specular, vec3 albedo) { + float dielectric = (0.034 * 2.0) * specular; + // energy conservation + return mix(vec3(dielectric), albedo, metallic); // TODO: reference? +} + +void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) { + +#if defined(USE_LIGHT_SHADER_CODE) +//light is written by the light shader + + vec3 normal = N; + vec3 albedo = diffuse_color; + vec3 light = L; + vec3 view = V; + +LIGHT_SHADER_CODE + + +#else + float NdotL = dot(N,L); + float cNdotL = max(NdotL, 0.0); // clamped NdotL + float NdotV = dot(N, V); + float cNdotV = max(NdotV, 0.0); + + if (metallic < 1.0) { +#if defined(DIFFUSE_OREN_NAYAR) + vec3 diffuse_brdf_NL; +#else + float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance +#endif + + +#if defined(DIFFUSE_LAMBERT_WRAP) + //energy conserving lambert wrap shader + diffuse_brdf_NL = max(0.0,(NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + +#elif defined(DIFFUSE_OREN_NAYAR) + + { + // see http://mimosa-pudica.net/improved-oren-nayar.html + float LdotV = dot(L, V); + + + float s = LdotV - NdotL * NdotV; + float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); + + float sigma2 = roughness * roughness; // TODO: this needs checking + vec3 A = 1.0 + sigma2 * (- 0.5 / (sigma2 + 0.33) + 0.17*diffuse_color / (sigma2 + 0.13) ); + float B = 0.45 * sigma2 / (sigma2 + 0.09); + + diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); + } + +#elif defined(DIFFUSE_TOON) + + diffuse_brdf_NL = smoothstep(-roughness,max(roughness,0.01),NdotL); + +#elif defined(DIFFUSE_BURLEY) + + { + + + vec3 H = normalize(V + L); + float cLdotH = max(0.0,dot(L, H)); + + float FD90 = 0.5 + 2.0 * cLdotH * cLdotH * roughness; + float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotV); + float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotL); + diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; + /* + float energyBias = mix(roughness, 0.0, 0.5); + float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); + float fd90 = energyBias + 2.0 * VoH * VoH * roughness; + float f0 = 1.0; + float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0); + float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0); + + diffuse_brdf_NL = lightScatter * viewScatter * energyFactor;*/ + } +#else + //lambert + diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#endif + +#if defined(TRANSMISSION_USED) + diffuse_light += light_color * diffuse_color * mix(vec3(diffuse_brdf_NL), vec3(M_PI), transmission) * attenuation; +#else + diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation; +#endif + + + +#if defined(LIGHT_USE_RIM) + float rim_light = pow(1.0-cNdotV, (1.0-roughness)*16.0); + diffuse_light += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color; +#endif + } + + + if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely + + + // D + +#if defined(SPECULAR_BLINN) + + vec3 H = normalize(V + L); + float cNdotH = max(dot(N,H), 0.0 ); + float intensity = pow( cNdotH, (1.0-roughness) * 256.0); + specular_light += light_color * intensity * specular_blob_intensity * attenuation; + +#elif defined(SPECULAR_PHONG) + + vec3 R = normalize(-reflect(L,N)); + float cRdotV = max(0.0,dot(R,V)); + float intensity = pow( cRdotV, (1.0-roughness) * 256.0); + specular_light += light_color * intensity * specular_blob_intensity * attenuation; + +#elif defined(SPECULAR_TOON) + + vec3 R = normalize(-reflect(L,N)); + float RdotV = dot(R,V); + float mid = 1.0-roughness; + mid*=mid; + float intensity = smoothstep(mid-roughness*0.5, mid+roughness*0.5, RdotV) * mid; + diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection + +#elif defined(SPECULAR_DISABLED) + //none.. + +#elif defined(SPECULAR_SCHLICK_GGX) + // shlick+ggx as default + + vec3 H = normalize(V + L); + + float cNdotH = max(dot(N,H), 0.0); + float cLdotH = max(dot(L,H), 0.0); + +# if defined(LIGHT_USE_ANISOTROPY) + + float aspect = sqrt(1.0-anisotropy*0.9); + float rx = roughness/aspect; + float ry = roughness*aspect; + float ax = rx*rx; + float ay = ry*ry; + float XdotH = dot( T, H ); + float YdotH = dot( B, H ); + float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH); + float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); + +# else + float alpha = roughness * roughness; + float D = D_GGX(cNdotH, alpha); + float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha); +# endif + // F + float F0 = 1.0; // FIXME + float cLdotH5 = SchlickFresnel(cLdotH); + float F = mix(cLdotH5, 1.0, F0); + + float specular_brdf_NL = cNdotL * D * F * G; + + specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; +#endif + +#if defined(LIGHT_USE_CLEARCOAT) + if (clearcoat_gloss > 0.0) { +# if !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) + vec3 H = normalize(V + L); +# endif +# if !defined(SPECULAR_SCHLICK_GGX) + float cNdotH = max(dot(N,H), 0.0); + float cLdotH = max(dot(L,H), 0.0); + float cLdotH5 = SchlickFresnel(cLdotH); +#endif + float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Fr = mix(.04, 1.0, cLdotH5); + float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); + + + float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + + specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; + } +#endif + } + + +#endif //defined(USE_LIGHT_SHADER_CODE) +} + + +float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) { + +#ifdef SHADOW_MODE_PCF_13 + + float avg=textureProj(shadow,vec4(pos,depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x*2.0,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x*2.0,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y*2.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y*2.0),depth,1.0)); + return avg*(1.0/13.0); + +#elif defined(SHADOW_MODE_PCF_5) + + float avg=textureProj(shadow,vec4(pos,depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); + return avg*(1.0/5.0); + +#else + + return textureProj(shadow,vec4(pos,depth,1.0)); + +#endif + +} + +#ifdef RENDER_DEPTH_DUAL_PARABOLOID + +in highp float dp_clip; + +#endif + + + +#if 0 +//need to save texture depth for this + +vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 pos, float distance) { + + float scale = 8.25 * (1.0 - translucency) / subsurface_scatter_width; + float d = scale * distance; + + /** + * Armed with the thickness, we can now calculate the color by means of the + * precalculated transmittance profile. + * (It can be precomputed into a texture, for maximum performance): + */ + float dd = -d * d; + vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) + + vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) + + vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) + + vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) + + vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) + + vec3(0.078, 0.0, 0.0) * exp(dd / 7.41); + + /** + * Using the profile, we finally approximate the transmitted lighting from + * the back of the object: + */ + return profile * clamp(0.3 + dot(light_vec, normal),0.0,1.0); +} +#endif + +void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) { + + vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; + float light_length = length( light_rel_vec ); + float normalized_distance = light_length*omni_lights[idx].light_pos_inv_radius.w; + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w )); + + if (omni_lights[idx].light_params.w>0.5) { + //there is a shadowmap + + highp vec3 splane=(omni_lights[idx].shadow_matrix * vec4(vertex,1.0)).xyz; + float shadow_len=length(splane); + splane=normalize(splane); + vec4 clamp_rect=omni_lights[idx].light_clamp; + + if (splane.z>=0.0) { + + splane.z+=1.0; + + clamp_rect.y+=clamp_rect.w; + + } else { + + splane.z=1.0 - splane.z; + + /* + if (clamp_rect.z<clamp_rect.w) { + clamp_rect.x+=clamp_rect.z; + } else { + clamp_rect.y+=clamp_rect.w; + } + */ + + } + + splane.xy/=splane.z; + splane.xy=splane.xy * 0.5 + 0.5; + splane.z = shadow_len * omni_lights[idx].light_pos_inv_radius.w; + + splane.xy = clamp_rect.xy+splane.xy*clamp_rect.zw; + float shadow = sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect); + +#ifdef USE_CONTACT_SHADOWS + + if (shadow>0.01 && omni_lights[idx].shadow_color_contact.a>0.0) { + + float contact_shadow = contact_shadow_compute(vertex,normalize(light_rel_vec),min(light_length,omni_lights[idx].shadow_color_contact.a)); + shadow=min(shadow,contact_shadow); + + } +#endif + light_attenuation*=mix(omni_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow); + } + + light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,omni_lights[idx].light_params.z*p_blob_intensity,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light); + +} + +void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent,vec3 albedo, vec3 transmission,float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) { + + vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex; + float light_length = length( light_rel_vec ); + float normalized_distance = light_length*spot_lights[idx].light_pos_inv_radius.w; + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.001), spot_lights[idx].light_direction_attenuation.w )); + vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz; + float spot_cutoff=spot_lights[idx].light_params.y; + float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff); + float spot_rim = (1.0 - scos) / (1.0 - spot_cutoff); + light_attenuation *= 1.0 - pow( max(spot_rim,0.001), spot_lights[idx].light_params.x); + + if (spot_lights[idx].light_params.w>0.5) { + //there is a shadowmap + highp vec4 splane=(spot_lights[idx].shadow_matrix * vec4(vertex,1.0)); + splane.xyz/=splane.w; + + float shadow = sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp); + +#ifdef USE_CONTACT_SHADOWS + if (shadow>0.01 && spot_lights[idx].shadow_color_contact.a>0.0) { + + float contact_shadow = contact_shadow_compute(vertex,normalize(light_rel_vec),min(light_length,spot_lights[idx].shadow_color_contact.a)); + shadow=min(shadow,contact_shadow); + + } +#endif + light_attenuation*=mix(spot_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow); + } + + light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,spot_lights[idx].light_params.z*p_blob_intensity,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light); + +} + +void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 tangent,float roughness,float anisotropy,vec3 ambient,vec3 skybox, inout highp vec4 reflection_accum,inout highp vec4 ambient_accum) { + + vec3 ref_vec = normalize(reflect(vertex,normal)); + vec3 local_pos = (reflections[idx].local_matrix * vec4(vertex,1.0)).xyz; + vec3 box_extents = reflections[idx].box_extents.xyz; + + if (any(greaterThan(abs(local_pos),box_extents))) { //out of the reflection box + return; + } + + vec3 inner_pos = abs(local_pos / box_extents); + float blend = max(inner_pos.x,max(inner_pos.y,inner_pos.z)); + //make blend more rounded + blend=mix(length(inner_pos),blend,blend); + blend*=blend; + blend=1.001-blend; + + if (reflections[idx].params.x>0.0){// compute reflection + + vec3 local_ref_vec = (reflections[idx].local_matrix * vec4(ref_vec,0.0)).xyz; + + if (reflections[idx].params.w > 0.5) { //box project + + vec3 nrdir = normalize(local_ref_vec); + vec3 rbmax = (box_extents - local_pos)/nrdir; + vec3 rbmin = (-box_extents - local_pos)/nrdir; + + + vec3 rbminmax = mix(rbmin,rbmax,greaterThan(nrdir,vec3(0.0,0.0,0.0))); + + float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); + vec3 posonbox = local_pos + nrdir * fa; + local_ref_vec = posonbox - reflections[idx].box_offset.xyz; + } + + + vec4 clamp_rect=reflections[idx].atlas_clamp; + vec3 norm = normalize(local_ref_vec); + norm.xy/=1.0+abs(norm.z); + norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25); + if (norm.z>0.0) { + norm.y=0.5-norm.y+0.5; + } + + vec2 atlas_uv = norm.xy * clamp_rect.zw + clamp_rect.xy; + atlas_uv = clamp(atlas_uv,clamp_rect.xy,clamp_rect.xy+clamp_rect.zw); + + highp vec4 reflection; + reflection.rgb = textureLod(reflection_atlas,atlas_uv,roughness*5.0).rgb; + + if (reflections[idx].params.z < 0.5) { + reflection.rgb = mix(skybox,reflection.rgb,blend); + } + reflection.rgb*=reflections[idx].params.x; + reflection.a = blend; + reflection.rgb*=reflection.a; + + reflection_accum+=reflection; + } + + if (reflections[idx].ambient.a>0.0) { //compute ambient using skybox + + + vec3 local_amb_vec = (reflections[idx].local_matrix * vec4(normal,0.0)).xyz; + + vec3 splane=normalize(local_amb_vec); + vec4 clamp_rect=reflections[idx].atlas_clamp; + + splane.z*=-1.0; + if (splane.z>=0.0) { + splane.z+=1.0; + clamp_rect.y+=clamp_rect.w; + } else { + splane.z=1.0 - splane.z; + splane.y=-splane.y; + } + + splane.xy/=splane.z; + splane.xy=splane.xy * 0.5 + 0.5; + + splane.xy = splane.xy * clamp_rect.zw + clamp_rect.xy; + splane.xy = clamp(splane.xy,clamp_rect.xy,clamp_rect.xy+clamp_rect.zw); + + highp vec4 ambient_out; + ambient_out.a=blend; + ambient_out.rgb = textureLod(reflection_atlas,splane.xy,5.0).rgb; + ambient_out.rgb=mix(reflections[idx].ambient.rgb,ambient_out.rgb,reflections[idx].ambient.a); + if (reflections[idx].params.z < 0.5) { + ambient_out.rgb = mix(ambient,ambient_out.rgb,blend); + } + + ambient_out.rgb *= ambient_out.a; + ambient_accum+=ambient_out; + } else { + + highp vec4 ambient_out; + ambient_out.a=blend; + ambient_out.rgb=reflections[idx].ambient.rgb; + if (reflections[idx].params.z < 0.5) { + ambient_out.rgb = mix(ambient,ambient_out.rgb,blend); + } + ambient_out.rgb *= ambient_out.a; + ambient_accum+=ambient_out; + + } +} + +#ifdef USE_GI_PROBES + +uniform mediump sampler3D gi_probe1; //texunit:-9 +uniform highp mat4 gi_probe_xform1; +uniform highp vec3 gi_probe_bounds1; +uniform highp vec3 gi_probe_cell_size1; +uniform highp float gi_probe_multiplier1; +uniform highp float gi_probe_bias1; +uniform highp float gi_probe_normal_bias1; +uniform bool gi_probe_blend_ambient1; + +uniform mediump sampler3D gi_probe2; //texunit:-10 +uniform highp mat4 gi_probe_xform2; +uniform highp vec3 gi_probe_bounds2; +uniform highp vec3 gi_probe_cell_size2; +uniform highp float gi_probe_multiplier2; +uniform highp float gi_probe_bias2; +uniform highp float gi_probe_normal_bias2; +uniform bool gi_probe2_enabled; +uniform bool gi_probe_blend_ambient2; + +vec3 voxel_cone_trace(mediump sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, bool blend_ambient, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { + + float dist = p_bias;//1.0; //dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0; + float alpha=0.0; + vec3 color = vec3(0.0); + + while(dist < max_distance && alpha < 0.95) { + float diameter = max(1.0, 2.0 * tan_half_angle * dist); + vec4 scolor = textureLod(probe, (pos + dist * direction) * cell_size, log2(diameter) ); + float a = (1.0 - alpha); + color += scolor.rgb * a; + alpha += a * scolor.a; + dist += diameter * 0.5; + } + + if (blend_ambient) { + color.rgb = mix(ambient,color.rgb,min(1.0,alpha/0.95)); + } + + return color; +} + +void gi_probe_compute(mediump sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient,float multiplier, mat3 normal_mtx,vec3 ref_vec, float roughness,float p_bias,float p_normal_bias, inout vec4 out_spec, inout vec4 out_diff) { + + + + vec3 probe_pos = (probe_xform * vec4(pos,1.0)).xyz; + vec3 ref_pos = (probe_xform * vec4(pos+ref_vec,1.0)).xyz; + ref_vec = normalize(ref_pos - probe_pos); + + probe_pos+=(probe_xform * vec4(normal_mtx[2],0.0)).xyz*p_normal_bias; + +/* out_diff.rgb = voxel_cone_trace(probe,cell_size,probe_pos,normalize((probe_xform * vec4(ref_vec,0.0)).xyz),0.0 ,100.0); + out_diff.a = 1.0; + return;*/ + //out_diff = vec4(textureLod(probe,probe_pos*cell_size,3.0).rgb,1.0); + //return; + + //this causes corrupted pixels, i have no idea why.. + if (any(bvec2(any(lessThan(probe_pos,vec3(0.0))),any(greaterThan(probe_pos,bounds))))) { + return; + } + + //vec3 blendv = probe_pos/bounds * 2.0 - 1.0; + //float blend = 1.001-max(blendv.x,max(blendv.y,blendv.z)); + float blend=1.0; + + float max_distance = length(bounds); + + //radiance +#ifdef VCT_QUALITY_HIGH + +#define MAX_CONE_DIRS 6 + vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] ( + vec3(0, 0, 1), + vec3(0.866025, 0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5) + ); + + float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); + float cone_angle_tan = 0.577; + float min_ref_tan = 0.0; +#else + +#define MAX_CONE_DIRS 4 + + vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] ( + vec3(0.707107, 0, 0.707107), + vec3(0, 0.707107, 0.707107), + vec3(-0.707107, 0, 0.707107), + vec3(0, -0.707107, 0.707107) + ); + + float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25); + float cone_angle_tan = 0.98269; + max_distance*=0.5; + float min_ref_tan = 0.2; + +#endif + vec3 light=vec3(0.0); + for(int i=0;i<MAX_CONE_DIRS;i++) { + + vec3 dir = normalize( (probe_xform * vec4(pos + normal_mtx * cone_dirs[i],1.0)).xyz - probe_pos); + light+=cone_weights[i] * voxel_cone_trace(probe,cell_size,probe_pos,ambient,blend_ambient,dir,cone_angle_tan,max_distance,p_bias); + + } + + light*=multiplier; + + out_diff += vec4(light*blend,blend); + + //irradiance + + vec3 irr_light = voxel_cone_trace(probe,cell_size,probe_pos,environment,blend_ambient,ref_vec,max(min_ref_tan,tan(roughness * 0.5 * M_PI)) ,max_distance,p_bias); + + irr_light *= multiplier; + //irr_light=vec3(0.0); + + out_spec += vec4(irr_light*blend,blend); + +} + + +void gi_probes_compute(vec3 pos, vec3 normal, float roughness, inout vec3 out_specular, inout vec3 out_ambient) { + + roughness = roughness * roughness; + + vec3 ref_vec = normalize(reflect(normalize(pos),normal)); + + //find arbitrary tangent and bitangent, then build a matrix + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0, 0, 1) : vec3(0, 1, 0); + vec3 tangent = normalize(cross(v0, normal)); + vec3 bitangent = normalize(cross(tangent, normal)); + mat3 normal_mat = mat3(tangent,bitangent,normal); + + vec4 diff_accum = vec4(0.0); + vec4 spec_accum = vec4(0.0); + + vec3 ambient = out_ambient; + out_ambient = vec3(0.0); + + vec3 environment = out_specular; + + out_specular = vec3(0.0); + + gi_probe_compute(gi_probe1,gi_probe_xform1,gi_probe_bounds1,gi_probe_cell_size1,pos,ambient,environment,gi_probe_blend_ambient1,gi_probe_multiplier1,normal_mat,ref_vec,roughness,gi_probe_bias1,gi_probe_normal_bias1,spec_accum,diff_accum); + + if (gi_probe2_enabled) { + + gi_probe_compute(gi_probe2,gi_probe_xform2,gi_probe_bounds2,gi_probe_cell_size2,pos,ambient,environment,gi_probe_blend_ambient2,gi_probe_multiplier2,normal_mat,ref_vec,roughness,gi_probe_bias2,gi_probe_normal_bias2,spec_accum,diff_accum); + } + + if (diff_accum.a>0.0) { + diff_accum.rgb/=diff_accum.a; + } + + if (spec_accum.a>0.0) { + spec_accum.rgb/=spec_accum.a; + } + + out_specular+=spec_accum.rgb; + out_ambient+=diff_accum.rgb; + +} + +#endif + + + +void main() { + +#ifdef RENDER_DEPTH_DUAL_PARABOLOID + + if (dp_clip>0.0) + discard; +#endif + + //lay out everything, whathever is unused is optimized away anyway + highp vec3 vertex = vertex_interp; + vec3 albedo = vec3(0.8,0.8,0.8); + vec3 transmission = vec3(0.0); + float metallic = 0.0; + float specular = 0.5; + vec3 emission = vec3(0.0,0.0,0.0); + float roughness = 1.0; + float rim = 0.0; + float rim_tint = 0.0; + float clearcoat=0.0; + float clearcoat_gloss=0.0; + float anisotropy = 1.0; + vec2 anisotropy_flow = vec2(1.0,0.0); + +#if defined(ENABLE_AO) + float ao=1.0; + float ao_light_affect=0.0; +#endif + + float alpha = 1.0; + +#ifdef METERIAL_DOUBLESIDED + float side=float(gl_FrontFacing)*2.0-1.0; +#else + float side=1.0; +#endif + + +#if defined(ALPHA_SCISSOR_USED) + float alpha_scissor = 0.5; +#endif + +#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + vec3 binormal = normalize(binormal_interp)*side; + vec3 tangent = normalize(tangent_interp)*side; +#else + vec3 binormal = vec3(0.0); + vec3 tangent = vec3(0.0); +#endif + vec3 normal = normalize(normal_interp)*side; + +#if defined(ENABLE_UV_INTERP) + vec2 uv = uv_interp; +#endif + +#if defined(ENABLE_UV2_INTERP) + vec2 uv2 = uv2_interp; +#endif + +#if defined(ENABLE_COLOR_INTERP) + vec4 color = color_interp; +#endif + +#if defined(ENABLE_NORMALMAP) + + vec3 normalmap = vec3(0.0); +#endif + + float normaldepth=1.0; + +#if defined(SCREEN_UV_USED) + vec2 screen_uv = gl_FragCoord.xy*screen_pixel_size; +#endif + +#if defined (ENABLE_SSS) + float sss_strength=0.0; +#endif + +{ + + +FRAGMENT_SHADER_CODE + +} + + +#if defined(ALPHA_SCISSOR_USED) + if (alpha<alpha_scissor) { + discard; + } +#endif + +#ifdef USE_OPAQUE_PREPASS + + if (alpha<0.99) { + discard; + } +#endif + +#if defined(ENABLE_NORMALMAP) + + normalmap.xy=normalmap.xy*2.0-1.0; + normalmap.z=sqrt(1.0-dot(normalmap.xy,normalmap.xy)); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. + + normal = normalize( mix(normal_interp,tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z,normaldepth) ) * side; + +#endif + +#if defined(LIGHT_USE_ANISOTROPY) + + if (anisotropy>0.01) { + //rotation matrix + mat3 rot = mat3( tangent, binormal, normal ); + //make local to space + tangent = normalize(rot * vec3(anisotropy_flow.x,anisotropy_flow.y,0.0)); + binormal = normalize(rot * vec3(-anisotropy_flow.y,anisotropy_flow.x,0.0)); + } + +#endif + +#ifdef ENABLE_CLIP_ALPHA + if (albedo.a<0.99) { + //used for doublepass and shadowmapping + discard; + } +#endif + +/////////////////////// LIGHTING ////////////////////////////// + + //apply energy conservation + +#ifdef USE_VERTEX_LIGHTING + + vec3 specular_light = specular_light_interp.rgb; + vec3 diffuse_light = diffuse_light_interp.rgb; +#else + + vec3 specular_light = vec3(0.0,0.0,0.0); + vec3 diffuse_light = vec3(0.0,0.0,0.0); + +#endif + + vec3 ambient_light; + vec3 env_reflection_light = vec3(0.0,0.0,0.0); + + vec3 eye_vec = -normalize( vertex_interp ); + + + +#ifdef USE_RADIANCE_MAP + + if (no_ambient_light) { + ambient_light=vec3(0.0,0.0,0.0); + } else { + { + + { //read radiance from dual paraboloid + + vec3 ref_vec = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n); + ref_vec=normalize((radiance_inverse_xform * vec4(ref_vec,0.0)).xyz); + vec3 radiance = textureDualParaboloid(radiance_map,ref_vec,roughness) * bg_energy; + env_reflection_light = radiance; + + } + //no longer a cubemap + //vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y); + + } + + { + + vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz); + vec3 env_ambient=textureDualParaboloid(radiance_map,ambient_dir,1.0) * bg_energy; + + ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution); + //ambient_light=vec3(0.0,0.0,0.0); + } + } + +#else + + if (no_ambient_light){ + ambient_light=vec3(0.0,0.0,0.0); + } else { + ambient_light=ambient_light_color.rgb; + } +#endif + + ambient_light*=ambient_energy; + + float specular_blob_intensity=1.0; +#if defined(SPECULAR_TOON) + specular_blob_intensity*=specular * 2.0; +#endif + +#if defined(USE_LIGHT_DIRECTIONAL) + + vec3 light_attenuation=vec3(1.0); + + float depth_z = -vertex.z; +#ifdef LIGHT_DIRECTIONAL_SHADOW + +#ifdef LIGHT_USE_PSSM4 + if (depth_z < shadow_split_offsets.w) { +#elif defined(LIGHT_USE_PSSM2) + if (depth_z < shadow_split_offsets.y) { +#else + if (depth_z < shadow_split_offsets.x) { +#endif //LIGHT_USE_PSSM4 + + vec3 pssm_coord; + float pssm_fade=0.0; + +#ifdef LIGHT_USE_PSSM_BLEND + float pssm_blend; + vec3 pssm_coord2; + bool use_blend=true; +#endif + + +#ifdef LIGHT_USE_PSSM4 + + + if (depth_z < shadow_split_offsets.y) { + + if (depth_z < shadow_split_offsets.x) { + + highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + + +#if defined(LIGHT_USE_PSSM_BLEND) + + splane=(shadow_matrix2 * vec4(vertex,1.0)); + pssm_coord2=splane.xyz/splane.w; + pssm_blend=smoothstep(0.0,shadow_split_offsets.x,depth_z); +#endif + + } else { + + highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + +#if defined(LIGHT_USE_PSSM_BLEND) + splane=(shadow_matrix3 * vec4(vertex,1.0)); + pssm_coord2=splane.xyz/splane.w; + pssm_blend=smoothstep(shadow_split_offsets.x,shadow_split_offsets.y,depth_z); +#endif + + } + } else { + + + if (depth_z < shadow_split_offsets.z) { + + highp vec4 splane=(shadow_matrix3 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + +#if defined(LIGHT_USE_PSSM_BLEND) + splane=(shadow_matrix4 * vec4(vertex,1.0)); + pssm_coord2=splane.xyz/splane.w; + pssm_blend=smoothstep(shadow_split_offsets.y,shadow_split_offsets.z,depth_z); +#endif + + } else { + + highp vec4 splane=(shadow_matrix4 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + pssm_fade = smoothstep(shadow_split_offsets.z,shadow_split_offsets.w,depth_z); + +#if defined(LIGHT_USE_PSSM_BLEND) + use_blend=false; + +#endif + + } + } + + + +#endif //LIGHT_USE_PSSM4 + +#ifdef LIGHT_USE_PSSM2 + + if (depth_z < shadow_split_offsets.x) { + + highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + + +#if defined(LIGHT_USE_PSSM_BLEND) + + splane=(shadow_matrix2 * vec4(vertex,1.0)); + pssm_coord2=splane.xyz/splane.w; + pssm_blend=smoothstep(0.0,shadow_split_offsets.x,depth_z); +#endif + + } else { + highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + pssm_fade = smoothstep(shadow_split_offsets.x,shadow_split_offsets.y,depth_z); +#if defined(LIGHT_USE_PSSM_BLEND) + use_blend=false; + +#endif + + } + +#endif //LIGHT_USE_PSSM2 + +#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) + { //regular orthogonal + highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0)); + pssm_coord=splane.xyz/splane.w; + } +#endif + + + //one one sample + + float shadow = sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp); + +#if defined(LIGHT_USE_PSSM_BLEND) + + if (use_blend) { + shadow=mix(shadow, sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp),pssm_blend); + } +#endif + +#ifdef USE_CONTACT_SHADOWS + if (shadow>0.01 && shadow_color_contact.a>0.0) { + + float contact_shadow = contact_shadow_compute(vertex,-light_direction_attenuation.xyz,shadow_color_contact.a); + shadow=min(shadow,contact_shadow); + + } +#endif + light_attenuation=mix(mix(shadow_color_contact.rgb,vec3(1.0),shadow),vec3(1.0),pssm_fade); + + + } + + +#endif //LIGHT_DIRECTIONAL_SHADOW + +#ifdef USE_VERTEX_LIGHTING + diffuse_light*=mix(vec3(1.0),light_attenuation,diffuse_light_interp.a); + specular_light*=mix(vec3(1.0),light_attenuation,specular_light_interp.a); + +#else + light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb,light_attenuation,albedo,transmission,light_params.z*specular_blob_intensity,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light); +#endif + + +#endif //#USE_LIGHT_DIRECTIONAL + +#ifdef USE_GI_PROBES + gi_probes_compute(vertex,normal,roughness,env_reflection_light,ambient_light); + +#endif + +#ifdef USE_FORWARD_LIGHTING + + + highp vec4 reflection_accum = vec4(0.0,0.0,0.0,0.0); + highp vec4 ambient_accum = vec4(0.0,0.0,0.0,0.0); + for(int i=0;i<reflection_count;i++) { + reflection_process(reflection_indices[i],vertex,normal,binormal,tangent,roughness,anisotropy,ambient_light,env_reflection_light,reflection_accum,ambient_accum); + } + + if (reflection_accum.a>0.0) { + specular_light+=reflection_accum.rgb/reflection_accum.a; + } else { + specular_light+=env_reflection_light; + } + + if (ambient_accum.a>0.0) { + ambient_light+=ambient_accum.rgb/ambient_accum.a; + } + + + +#ifdef USE_VERTEX_LIGHTING + + diffuse_light*=albedo; +#else + + for(int i=0;i<omni_light_count;i++) { + light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,transmission,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light); + } + + for(int i=0;i<spot_light_count;i++) { + light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,transmission,roughness,metallic,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light); + } + +#endif //USE_VERTEX_LIGHTING + +#endif + + + + +#ifdef RENDER_DEPTH +//nothing happens, so a tree-ssa optimizer will result in no fragment shader :) +#else + + specular_light*=reflection_multiplier; + ambient_light*=albedo; //ambient must be multiplied by albedo at the end + +#if defined(ENABLE_AO) + ambient_light*=ao; + ao_light_affect = mix(1.0,ao,ao_light_affect); + specular_light*=ao_light_affect; + diffuse_light*=ao_light_affect; +#endif + + + + //energy conservation + diffuse_light *= 1.0-metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point + ambient_light *= 1.0-metallic; + + + { + +#if defined(DIFFUSE_TOON) + //simplify for toon, as + specular_light *= specular * metallic * albedo * 2.0; +#else + // Environment brdf approximation (Lazarov 2013) + // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile + const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); + const vec4 c1 = vec4( 1.0, 0.0425, 1.04, -0.04); + vec4 r = roughness * c0 + c1; + float ndotv = clamp(dot(normal,eye_vec),0.0,1.0); + float a004 = min( r.x * r.x, exp2( -9.28 * ndotv ) ) * r.x + r.y; + vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw; + + vec3 specular_color = metallic_to_specular_color(metallic, specular, albedo); + specular_light *= AB.x * specular_color + AB.y; +#endif + + } + + if (fog_color_enabled.a > 0.5) { + + float fog_amount=0.0; + + + +#ifdef USE_LIGHT_DIRECTIONAL + + vec3 fog_color = mix( fog_color_enabled.rgb, fog_sun_color_amount.rgb,fog_sun_color_amount.a * pow(max( dot(normalize(vertex),-light_direction_attenuation.xyz), 0.0),8.0) ); +#else + + vec3 fog_color = fog_color_enabled.rgb; +#endif + + //apply fog + + if (fog_depth_enabled) { + + float fog_z = smoothstep(fog_depth_begin,z_far,length(vertex)); + + fog_amount = pow(fog_z,fog_depth_curve); + if (fog_transmit_enabled) { + vec3 total_light = emission + ambient_light + specular_light + diffuse_light; + float transmit = pow(fog_z,fog_transmit_curve); + fog_color = mix(max(total_light,fog_color),fog_color,transmit); + } + } + + if (fog_height_enabled) { + float y = (camera_matrix * vec4(vertex,1.0)).y; + fog_amount = max(fog_amount,pow(smoothstep(fog_height_min,fog_height_max,y),fog_height_curve)); + } + + float rev_amount = 1.0 - fog_amount; + + + emission = emission * rev_amount + fog_color * fog_amount; + ambient_light*=rev_amount; + specular_light*rev_amount; + diffuse_light*=rev_amount; + + } + +#ifdef USE_MULTIPLE_RENDER_TARGETS + + +#ifdef SHADELESS + diffuse_buffer=vec4(albedo.rgb,0.0); + specular_buffer=vec4(0.0); + +#else + +#if defined(ENABLE_AO) + + float ambient_scale=0.0; // AO is supplied by material +#else + //approximate ambient scale for SSAO, since we will lack full ambient + float max_emission=max(emission.r,max(emission.g,emission.b)); + float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b)); + float max_diffuse=max(diffuse_light.r,max(diffuse_light.g,diffuse_light.b)); + float total_ambient = max_ambient+max_diffuse+max_emission; + float ambient_scale = (total_ambient>0.0) ? (max_ambient+ambient_occlusion_affect_light*max_diffuse)/total_ambient : 0.0; +#endif //ENABLE_AO + + diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale); + specular_buffer=vec4(specular_light,metallic); + +#endif //SHADELESS + + normal_mr_buffer=vec4(normalize(normal)*0.5+0.5,roughness); + +#if defined (ENABLE_SSS) + sss_buffer = sss_strength; +#endif + + +#else //USE_MULTIPLE_RENDER_TARGETS + + +#ifdef SHADELESS + frag_color=vec4(albedo,alpha); +#else + frag_color=vec4(emission+ambient_light+diffuse_light+specular_light,alpha); +#endif //SHADELESS + + +#endif //USE_MULTIPLE_RENDER_TARGETS + + + +#endif //RENDER_DEPTH + + +} diff --git a/drivers/gles2/shaders/screen_space_reflection.glsl b/drivers/gles2/shaders/screen_space_reflection.glsl new file mode 100644 index 0000000000..b2e6f7a736 --- /dev/null +++ b/drivers/gles2/shaders/screen_space_reflection.glsl @@ -0,0 +1,318 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; +out vec2 pos_interp; + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; + pos_interp.xy=gl_Position.xy; +} + +[fragment] + + +in vec2 uv_interp; +in vec2 pos_interp; + +uniform sampler2D source_diffuse; //texunit:0 +uniform sampler2D source_normal_roughness; //texunit:1 +uniform sampler2D source_depth; //texunit:2 + +uniform float camera_z_near; +uniform float camera_z_far; + +uniform vec2 viewport_size; +uniform vec2 pixel_size; + +uniform float filter_mipmap_levels; + +uniform mat4 inverse_projection; +uniform mat4 projection; + +uniform int num_steps; +uniform float depth_tolerance; +uniform float distance_fade; +uniform float curve_fade_in; + + +layout(location = 0) out vec4 frag_color; + + +vec2 view_to_screen(vec3 view_pos,out float w) { + vec4 projected = projection * vec4(view_pos, 1.0); + projected.xyz /= projected.w; + projected.xy = projected.xy * 0.5 + 0.5; + w=projected.w; + return projected.xy; +} + + + +#define M_PI 3.14159265359 + +void main() { + + + //// + + vec4 diffuse = texture( source_diffuse, uv_interp ); + vec4 normal_roughness = texture( source_normal_roughness, uv_interp); + + vec3 normal; + + normal = normal_roughness.xyz*2.0-1.0; + + float roughness = normal_roughness.w; + + float depth_tex = texture(source_depth,uv_interp).r; + + vec4 world_pos = inverse_projection * vec4( uv_interp*2.0-1.0, depth_tex*2.0-1.0, 1.0 ); + vec3 vertex = world_pos.xyz/world_pos.w; + + vec3 view_dir = normalize(vertex); + vec3 ray_dir = normalize(reflect(view_dir, normal)); + + if (dot(ray_dir,normal)<0.001) { + frag_color=vec4(0.0); + return; + } + //ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0); + + //ray_dir = normalize(vec3(1,1,-1)); + + + //////////////// + + + //make ray length and clip it against the near plane (don't want to trace beyond visible) + float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far; + vec3 ray_end = vertex + ray_dir*ray_len; + + float w_begin; + vec2 vp_line_begin = view_to_screen(vertex,w_begin); + float w_end; + vec2 vp_line_end = view_to_screen( ray_end, w_end); + vec2 vp_line_dir = vp_line_end-vp_line_begin; + + //we need to interpolate w along the ray, to generate perspective correct reflections + + w_begin = 1.0/w_begin; + w_end = 1.0/w_end; + + + float z_begin = vertex.z*w_begin; + float z_end = ray_end.z*w_end; + + vec2 line_begin = vp_line_begin/pixel_size; + vec2 line_dir = vp_line_dir/pixel_size; + float z_dir = z_end - z_begin; + float w_dir = w_end - w_begin; + + + // clip the line to the viewport edges + + float scale_max_x = min(1.0, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x)); + float scale_max_y = min(1.0, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y)); + float scale_min_x = min(1.0, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x)); + float scale_min_y = min(1.0, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y)); + float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y); + line_dir *= line_clip; + z_dir *= line_clip; + w_dir *=line_clip; + + //clip z and w advance to line advance + vec2 line_advance = normalize(line_dir); //down to pixel + float step_size = length(line_advance)/length(line_dir); + float z_advance = z_dir*step_size; // adapt z advance to line advance + float w_advance = w_dir*step_size; // adapt w advance to line advance + + //make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice) + float advance_angle_adj = 1.0/max(abs(line_advance.x),abs(line_advance.y)); + line_advance*=advance_angle_adj; // adapt z advance to line advance + z_advance*=advance_angle_adj; + w_advance*=advance_angle_adj; + + vec2 pos = line_begin; + float z = z_begin; + float w = w_begin; + float z_from=z/w; + float z_to=z_from; + float depth; + vec2 prev_pos=pos; + + bool found=false; + + float steps_taken=0.0; + + for(int i=0;i<num_steps;i++) { + + pos+=line_advance; + z+=z_advance; + w+=w_advance; + + //convert to linear depth + + depth = texture(source_depth, pos*pixel_size).r * 2.0 - 1.0; +#ifdef USE_ORTHOGONAL_PROJECTION + depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#else + depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); +#endif + depth=-depth; + + z_from = z_to; + z_to = z/w; + + if (depth>z_to) { + //if depth was surpassed + if (depth<=max(z_to,z_from)+depth_tolerance) { + //check the depth tolerance + found=true; + } + break; + } + + steps_taken+=1.0; + prev_pos=pos; + } + + + + + if (found) { + + float margin_blend=1.0; + + + vec2 margin = vec2((viewport_size.x+viewport_size.y)*0.5*0.05); //make a uniform margin + if (any(bvec4(lessThan(pos,-margin),greaterThan(pos,viewport_size+margin)))) { + //clip outside screen + margin + frag_color=vec4(0.0); + return; + } + + { + //blend fading out towards external margin + vec2 margin_grad = mix(pos-viewport_size,-pos,lessThan(pos,vec2(0.0))); + margin_blend = 1.0-smoothstep(0.0,margin.x,max(margin_grad.x,margin_grad.y)); + //margin_blend=1.0; + + } + + vec2 final_pos; + float grad; + grad=steps_taken/float(num_steps); + float initial_fade = curve_fade_in==0.0 ? 1.0 : pow(clamp(grad,0.0,1.0),curve_fade_in); + float fade = pow(clamp(1.0-grad,0.0,1.0),distance_fade)*initial_fade; + final_pos=pos; + + + + + + + +#ifdef REFLECT_ROUGHNESS + + + vec4 final_color; + //if roughness is enabled, do screen space cone tracing + if (roughness > 0.001) { + /////////////////////////////////////////////////////////////////////////////////////// + //use a blurred version (in consecutive mipmaps) of the screen to simulate roughness + + float gloss = 1.0-roughness; + float cone_angle = roughness * M_PI * 0.5; + vec2 cone_dir = final_pos - line_begin; + float cone_len = length(cone_dir); + cone_dir = normalize(cone_dir); //will be used normalized from now on + float max_mipmap = filter_mipmap_levels - 1.0; + float gloss_mult=gloss; + + float rem_alpha=1.0; + final_color = vec4(0.0); + + for(int i=0;i<7;i++) { + + float op_len = 2.0 * tan(cone_angle) * cone_len; //opposite side of iso triangle + float radius; + { + //fit to sphere inside cone (sphere ends at end of cone), something like this: + // ___ + // \O/ + // V + // + // as it avoids bleeding from beyond the reflection as much as possible. As a plus + // it also makes the rough reflection more elongated. + float a = op_len; + float h = cone_len; + float a2 = a * a; + float fh2 = 4.0f * h * h; + radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h); + } + + //find the place where screen must be sampled + vec2 sample_pos = ( line_begin + cone_dir * (cone_len - radius) ) * pixel_size; + //radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels + float mipmap = clamp( log2( radius ), 0.0, max_mipmap ); + + //mipmap = max(mipmap-1.0,0.0); + //do sampling + + vec4 sample_color; + { + sample_color = textureLod(source_diffuse,sample_pos,mipmap); + } + + //multiply by gloss + sample_color.rgb*=gloss_mult; + sample_color.a=gloss_mult; + + rem_alpha -= sample_color.a; + if(rem_alpha < 0.0) { + sample_color.rgb *= (1.0 - abs(rem_alpha)); + } + + final_color+=sample_color; + + if (final_color.a>=0.95) { + // This code of accumulating gloss and aborting on near one + // makes sense when you think of cone tracing. + // Think of it as if roughness was 0, then we could abort on the first + // iteration. For lesser roughness values, we need more iterations, but + // each needs to have less influence given the sphere is smaller + break; + } + + cone_len-=radius*2.0; //go to next (smaller) circle. + + gloss_mult*=gloss; + + + } + } else { + final_color = textureLod(source_diffuse,final_pos*pixel_size,0.0); + } + + frag_color = vec4(final_color.rgb,fade*margin_blend); + +#else + frag_color = vec4(textureLod(source_diffuse,final_pos*pixel_size,0.0).rgb,fade*margin_blend); +#endif + + + + } else { + frag_color = vec4(0.0,0.0,0.0,0.0); + } + + + +} + diff --git a/drivers/gles2/shaders/ssao.glsl b/drivers/gles2/shaders/ssao.glsl new file mode 100644 index 0000000000..219f0957e0 --- /dev/null +++ b/drivers/gles2/shaders/ssao.glsl @@ -0,0 +1,293 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + +void main() { + + gl_Position = vertex_attrib; + gl_Position.z=1.0; +} + +[fragment] + +#define TWO_PI 6.283185307179586476925286766559 + +#ifdef SSAO_QUALITY_HIGH + +#define NUM_SAMPLES (80) + +#endif + +#ifdef SSAO_QUALITY_LOW + +#define NUM_SAMPLES (15) + +#endif + +#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) + +#define NUM_SAMPLES (40) + +#endif + +// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower +// miplevel to maintain reasonable spatial locality in the cache +// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing. +// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively +#define LOG_MAX_OFFSET (3) + +// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp +#define MAX_MIP_LEVEL (4) + +// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent +// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 + +const int ROTATIONS[] = int[]( 1, 1, 2, 3, 2, 5, 2, 3, 2, +3, 3, 5, 5, 3, 4, 7, 5, 5, 7, +9, 8, 5, 5, 7, 7, 7, 8, 5, 8, +11, 12, 7, 10, 13, 8, 11, 8, 7, 14, +11, 11, 13, 12, 13, 19, 17, 13, 11, 18, +19, 11, 11, 14, 17, 21, 15, 16, 17, 18, +13, 17, 11, 17, 19, 18, 25, 18, 19, 19, +29, 21, 19, 27, 31, 29, 21, 18, 17, 29, +31, 31, 23, 18, 25, 26, 25, 23, 19, 34, +19, 27, 21, 25, 39, 29, 17, 21, 27 ); + +//#define NUM_SPIRAL_TURNS (7) +const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES-1]; + +uniform sampler2D source_depth; //texunit:0 +uniform highp usampler2D source_depth_mipmaps; //texunit:1 +uniform sampler2D source_normal; //texunit:2 + +uniform ivec2 screen_size; +uniform float camera_z_far; +uniform float camera_z_near; + +uniform float intensity_div_r6; +uniform float radius; + +#ifdef ENABLE_RADIUS2 +uniform float intensity_div_r62; +uniform float radius2; +#endif + +uniform float bias; +uniform float proj_scale; + +layout(location = 0) out float visibility; + +uniform vec4 proj_info; + +vec3 reconstructCSPosition(vec2 S, float z) { +#ifdef USE_ORTHOGONAL_PROJECTION + return vec3((S.xy * proj_info.xy + proj_info.zw), z); +#else + return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z); + +#endif +} + +vec3 getPosition(ivec2 ssP) { + vec3 P; + P.z = texelFetch(source_depth, ssP, 0).r; + + P.z = P.z * 2.0 - 1.0; +#ifdef USE_ORTHOGONAL_PROJECTION + P.z = ((P.z + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#else + P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); +#endif + P.z = -P.z; + + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + return P; +} + +/** Reconstructs screen-space unit normal from screen-space position */ +vec3 reconstructCSFaceNormal(vec3 C) { + return normalize(cross(dFdy(C), dFdx(C))); +} + + + +/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ +vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){ + // Radius relative to ssR + float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES)); + float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle; + + ssR = alpha; + return vec2(cos(angle), sin(angle)); +} + + +/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ +vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) { + // Derivation: + // mipLevel = floor(log(ssR / MAX_OFFSET)); + int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); + + ivec2 ssP = ivec2(ssR * unitOffset) + ssC; + + vec3 P; + + // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. + // Manually clamp to the texture size because texelFetch bypasses the texture unit + ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1)); + + + if (mipLevel < 1) { + //read from depth buffer + P.z = texelFetch(source_depth, mipP, 0).r; + P.z = P.z * 2.0 - 1.0; +#ifdef USE_ORTHOGONAL_PROJECTION + P.z = ((P.z + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#else + P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); + +#endif + P.z = -P.z; + + } else { + //read from mipmaps + uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel-1).r; + P.z = -(float(d)/65535.0)*camera_z_far; + } + + + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + + return P; +} + + + +/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds + to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius + + Note that units of H() in the HPG12 paper are meters, not + unitless. The whole falloff/sampling function is therefore + unitless. In this implementation, we factor out (9 / radius). + + Four versions of the falloff function are implemented below +*/ +float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius,in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { + // Offset on the unit disk, spun for this pixel + float ssR; + vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); + ssR *= ssDiskRadius; + + // The occluding point in camera space + vec3 Q = getOffsetPosition(ssC, unitOffset, ssR); + + vec3 v = Q - C; + + float vv = dot(v, v); + float vn = dot(v, n_C); + + const float epsilon = 0.01; + float radius2 = p_radius*p_radius; + + // A: From the HPG12 paper + // Note large epsilon to avoid overdarkening within cracks + //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; + + // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] + float f=max(radius2 - vv, 0.0); + return f * f * f * max((vn - bias) / (epsilon + vv), 0.0); + + // C: Medium contrast (which looks better at high radii), no division. Note that the + // contribution still falls off with radius^2, but we've adjusted the rate in a way that is + // more computationally efficient and happens to be aesthetically pleasing. + // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); + + // D: Low contrast, no division operation + // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); +} + + + +void main() { + + + // Pixel being shaded + ivec2 ssC = ivec2(gl_FragCoord.xy); + + // World space point being shaded + vec3 C = getPosition(ssC); + +/* if (C.z <= -camera_z_far*0.999) { + // We're on the skybox + visibility=1.0; + return; + }*/ + + //visibility=-C.z/camera_z_far; + //return; +#if 0 + vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0; +#else + vec3 n_C = reconstructCSFaceNormal(C); + n_C = -n_C; +#endif + + // Hash function used in the HPG12 AlchemyAO paper + float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI); + + // Reconstruct normals from positions. These will lead to 1-pixel black lines + // at depth discontinuities, however the blur will wipe those out so they are not visible + // in the final image. + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere +#ifdef USE_ORTHOGONAL_PROJECTION + float ssDiskRadius = -proj_scale * radius; +#else + float ssDiskRadius = -proj_scale * radius / C.z; +#endif + float sum = 0.0; + for (int i = 0; i < NUM_SAMPLES; ++i) { + sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius,i, randomPatternRotationAngle); + } + + float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / float(NUM_SAMPLES))); + +#ifdef ENABLE_RADIUS2 + + //go again for radius2 + randomPatternRotationAngle = mod(float((5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11), TWO_PI); + + // Reconstruct normals from positions. These will lead to 1-pixel black lines + // at depth discontinuities, however the blur will wipe those out so they are not visible + // in the final image. + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere + ssDiskRadius = -proj_scale * radius2 / C.z; + + sum = 0.0; + for (int i = 0; i < NUM_SAMPLES; ++i) { + sum += sampleAO(ssC, C, n_C, ssDiskRadius,radius2, i, randomPatternRotationAngle); + } + + A= min(A,max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / float(NUM_SAMPLES)))); +#endif + // Bilateral box-filter over a quad for free, respecting depth edges + // (the difference that this makes is subtle) + if (abs(dFdx(C.z)) < 0.02) { + A -= dFdx(A) * (float(ssC.x & 1) - 0.5); + } + if (abs(dFdy(C.z)) < 0.02) { + A -= dFdy(A) * (float(ssC.y & 1) - 0.5); + } + + visibility = A; + +} + + + diff --git a/drivers/gles2/shaders/ssao_blur.glsl b/drivers/gles2/shaders/ssao_blur.glsl new file mode 100644 index 0000000000..472dc21acf --- /dev/null +++ b/drivers/gles2/shaders/ssao_blur.glsl @@ -0,0 +1,124 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + + +void main() { + + gl_Position = vertex_attrib; + gl_Position.z=1.0; +} + +[fragment] + + +uniform sampler2D source_ssao; //texunit:0 +uniform sampler2D source_depth; //texunit:1 +uniform sampler2D source_normal; //texunit:3 + + +layout(location = 0) out float visibility; + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Tunable Parameters: + +/** Increase to make depth edges crisper. Decrease to reduce flicker. */ +uniform float edge_sharpness; + +/** Step in 2-pixel intervals since we already blurred against neighbors in the + first AO pass. This constant can be increased while R decreases to improve + performance at the expense of some dithering artifacts. + + Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was + unobjectionable after shading was applied but eliminated most temporal incoherence + from using small numbers of sample taps. + */ + +uniform int filter_scale; + +/** Filter radius in pixels. This will be multiplied by SCALE. */ +#define R (4) + + +////////////////////////////////////////////////////////////////////////////////////////////// + + +// Gaussian coefficients +const float gaussian[R + 1] = +// float[](0.356642, 0.239400, 0.072410, 0.009869); +// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 + float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 +// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 + +/** (1, 0) or (0, 1)*/ +uniform ivec2 axis; + +uniform float camera_z_far; +uniform float camera_z_near; + +uniform ivec2 screen_size; + +void main() { + + ivec2 ssC = ivec2(gl_FragCoord.xy); + + float depth = texelFetch(source_depth, ssC, 0).r; + //vec3 normal = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0; + + depth = depth * 2.0 - 1.0; + depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); + + float depth_divide = 1.0 / camera_z_far; + +// depth*=depth_divide; + + /* + if (depth > camera_z_far*0.999) { + discard;//skybox + } + */ + + float sum = texelFetch(source_ssao, ssC, 0).r; + + // Base weight for depth falloff. Increase this for more blurriness, + // decrease it for better edge discrimination + float BASE = gaussian[0]; + float totalWeight = BASE; + sum *= totalWeight; + + ivec2 clamp_limit = screen_size - ivec2(1); + + for (int r = -R; r <= R; ++r) { + // We already handled the zero case above. This loop should be unrolled and the static branch optimized out, + // so the IF statement has no runtime cost + if (r != 0) { + + ivec2 ppos = ssC + axis * (r * filter_scale); + float value = texelFetch(source_ssao, clamp(ppos,ivec2(0),clamp_limit), 0).r; + ivec2 rpos = clamp(ppos,ivec2(0),clamp_limit); + float temp_depth = texelFetch(source_depth, rpos, 0).r; + //vec3 temp_normal = texelFetch(source_normal, rpos, 0).rgb * 2.0 - 1.0; + + temp_depth = temp_depth * 2.0 - 1.0; + temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near)); +// temp_depth *= depth_divide; + + // spatial domain: offset gaussian tap + float weight = 0.3 + gaussian[abs(r)]; + //weight *= max(0.0,dot(temp_normal,normal)); + + // range domain (the "bilateral" weight). As depth difference increases, decrease weight. + weight *= max(0.0, 1.0 + - edge_sharpness * abs(temp_depth - depth) + ); + + sum += value * weight; + totalWeight += weight; + } + } + + const float epsilon = 0.0001; + visibility = sum / (totalWeight + epsilon); +} diff --git a/drivers/gles2/shaders/ssao_minify.glsl b/drivers/gles2/shaders/ssao_minify.glsl new file mode 100644 index 0000000000..647c762438 --- /dev/null +++ b/drivers/gles2/shaders/ssao_minify.glsl @@ -0,0 +1,59 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + +void main() { + + gl_Position = vertex_attrib; +} + +[fragment] + + +#ifdef MINIFY_START + +#define SDEPTH_TYPE highp sampler2D +uniform float camera_z_far; +uniform float camera_z_near; + +#else + +#define SDEPTH_TYPE mediump usampler2D + +#endif + +uniform SDEPTH_TYPE source_depth; //texunit:0 + +uniform ivec2 from_size; +uniform int source_mipmap; + +layout(location = 0) out mediump uint depth; + +void main() { + + + ivec2 ssP = ivec2(gl_FragCoord.xy); + + // Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling. + // On DX9, the bit-and can be implemented with floating-point modulo + +#ifdef MINIFY_START + float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; + fdepth = fdepth * 2.0 - 1.0; +#ifdef USE_ORTHOGONAL_PROJECTION + fdepth = ((fdepth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#else + fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near)); +#endif + fdepth /= camera_z_far; + depth = uint(clamp(fdepth*65535.0,0.0,65535.0)); + +#else + depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; +#endif + + +} + + diff --git a/drivers/gles2/shaders/subsurf_scattering.glsl b/drivers/gles2/shaders/subsurf_scattering.glsl new file mode 100644 index 0000000000..fc66d66198 --- /dev/null +++ b/drivers/gles2/shaders/subsurf_scattering.glsl @@ -0,0 +1,192 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +} + +[fragment] + +//#define QUALIFIER uniform // some guy on the interweb says it may be faster with this +#define QUALIFIER const + +#ifdef USE_25_SAMPLES + +const int kernel_size=25; +QUALIFIER vec2 kernel[25] = vec2[] ( + vec2(0.530605, 0.0), + vec2(0.000973794, -3.0), + vec2(0.00333804, -2.52083), + vec2(0.00500364, -2.08333), + vec2(0.00700976, -1.6875), + vec2(0.0094389, -1.33333), + vec2(0.0128496, -1.02083), + vec2(0.017924, -0.75), + vec2(0.0263642, -0.520833), + vec2(0.0410172, -0.333333), + vec2(0.0493588, -0.1875), + vec2(0.0402784, -0.0833333), + vec2(0.0211412, -0.0208333), + vec2(0.0211412, 0.0208333), + vec2(0.0402784, 0.0833333), + vec2(0.0493588, 0.1875), + vec2(0.0410172, 0.333333), + vec2(0.0263642, 0.520833), + vec2(0.017924, 0.75), + vec2(0.0128496, 1.02083), + vec2(0.0094389, 1.33333), + vec2(0.00700976, 1.6875), + vec2(0.00500364, 2.08333), + vec2(0.00333804, 2.52083), + vec2(0.000973794, 3.0) +); + +#endif //USE_25_SAMPLES + +#ifdef USE_17_SAMPLES + +const int kernel_size=17; + +QUALIFIER vec2 kernel[17] = vec2[]( + vec2(0.536343, 0.0), + vec2(0.00317394, -2.0), + vec2(0.0100386, -1.53125), + vec2(0.0144609, -1.125), + vec2(0.0216301, -0.78125), + vec2(0.0347317, -0.5), + vec2(0.0571056, -0.28125), + vec2(0.0582416, -0.125), + vec2(0.0324462, -0.03125), + vec2(0.0324462, 0.03125), + vec2(0.0582416, 0.125), + vec2(0.0571056, 0.28125), + vec2(0.0347317, 0.5), + vec2(0.0216301, 0.78125), + vec2(0.0144609, 1.125), + vec2(0.0100386, 1.53125), + vec2(0.00317394,2.0) +); + +#endif //USE_17_SAMPLES + + +#ifdef USE_11_SAMPLES + +const int kernel_size=11; + +QUALIFIER vec2 kernel[11] = vec2[]( + vec2(0.560479, 0.0), + vec2(0.00471691, -2.0), + vec2(0.0192831, -1.28), + vec2(0.03639, -0.72), + vec2(0.0821904, -0.32), + vec2(0.0771802, -0.08), + vec2(0.0771802, 0.08), + vec2(0.0821904, 0.32), + vec2(0.03639, 0.72), + vec2(0.0192831, 1.28), + vec2(0.00471691,2.0) +); + +#endif //USE_11_SAMPLES + + + +uniform float max_radius; +uniform float camera_z_far; +uniform float camera_z_near; +uniform float unit_size; +uniform vec2 dir; +in vec2 uv_interp; + +uniform sampler2D source_diffuse; //texunit:0 +uniform sampler2D source_sss; //texunit:1 +uniform sampler2D source_depth; //texunit:2 + +layout(location = 0) out vec4 frag_color; + +void main() { + + float strength = texture(source_sss,uv_interp).r; + strength*=strength; //stored as sqrt + + // Fetch color of current pixel: + vec4 base_color = texture(source_diffuse, uv_interp); + + + if (strength>0.0) { + + + // Fetch linear depth of current pixel: + float depth = texture(source_depth, uv_interp).r * 2.0 - 1.0; +#ifdef USE_ORTHOGONAL_PROJECTION + depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + float scale = unit_size; //remember depth is negative by default in OpenGL +#else + depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); + float scale = unit_size / depth; //remember depth is negative by default in OpenGL +#endif + + + + // Calculate the final step to fetch the surrounding pixels: + vec2 step = max_radius * scale * dir; + step *= strength; // Modulate it using the alpha channel. + step *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3. + + // Accumulate the center sample: + vec3 color_accum = base_color.rgb; + color_accum *= kernel[0].x; +#ifdef ENABLE_STRENGTH_WEIGHTING + float color_weight = kernel[0].x; +#endif + + // Accumulate the other samples: + for (int i = 1; i < kernel_size; i++) { + // Fetch color and depth for current sample: + vec2 offset = uv_interp + kernel[i].y * step; + vec3 color = texture(source_diffuse, offset).rgb; + +#ifdef ENABLE_FOLLOW_SURFACE + // If the difference in depth is huge, we lerp color back to "colorM": + float depth_cmp = texture(source_depth, offset).r *2.0 - 1.0; + +#ifdef USE_ORTHOGONAL_PROJECTION + depth_cmp = ((depth_cmp + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#else + depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near)); +#endif + + float s = clamp(300.0f * scale * + max_radius * abs(depth - depth_cmp),0.0,1.0); + color = mix(color, base_color.rgb, s); +#endif + + // Accumulate: + color*=kernel[i].x; + +#ifdef ENABLE_STRENGTH_WEIGHTING + float color_s = texture(source_sss, offset).r; + color_weight+=color_s * kernel[i].x; + color*=color_s; +#endif + color_accum += color; + + } + +#ifdef ENABLE_STRENGTH_WEIGHTING + color_accum/=color_weight; +#endif + frag_color = vec4(color_accum,base_color.a); //keep alpha (used for SSAO) + } else { + frag_color = base_color; + } +} diff --git a/drivers/gles2/shaders/tonemap.glsl b/drivers/gles2/shaders/tonemap.glsl new file mode 100644 index 0000000000..2f671158b2 --- /dev/null +++ b/drivers/gles2/shaders/tonemap.glsl @@ -0,0 +1,323 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + +void main() { + + gl_Position = vertex_attrib; + uv_interp = uv_in; +#ifdef V_FLIP + uv_interp.y = 1.0-uv_interp.y; +#endif + +} + +[fragment] + +#if !defined(GLES_OVER_GL) +precision mediump float; +#endif + + +in vec2 uv_interp; + +uniform highp sampler2D source; //texunit:0 + +uniform float exposure; +uniform float white; + +#ifdef USE_AUTO_EXPOSURE + +uniform highp sampler2D source_auto_exposure; //texunit:1 +uniform highp float auto_exposure_grey; + +#endif + +#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7) + +uniform highp sampler2D source_glow; //texunit:2 +uniform highp float glow_intensity; + +#endif + +#ifdef USE_BCS + +uniform vec3 bcs; + +#endif + +#ifdef USE_COLOR_CORRECTION + +uniform sampler2D color_correction; //texunit:3 + +#endif + + +layout(location = 0) out vec4 frag_color; + +#ifdef USE_GLOW_FILTER_BICUBIC + +// w0, w1, w2, and w3 are the four cubic B-spline basis functions +float w0(float a) +{ + return (1.0/6.0)*(a*(a*(-a + 3.0) - 3.0) + 1.0); +} + +float w1(float a) +{ + return (1.0/6.0)*(a*a*(3.0*a - 6.0) + 4.0); +} + +float w2(float a) +{ + return (1.0/6.0)*(a*(a*(-3.0*a + 3.0) + 3.0) + 1.0); +} + +float w3(float a) +{ + return (1.0/6.0)*(a*a*a); +} + +// g0 and g1 are the two amplitude functions +float g0(float a) +{ + return w0(a) + w1(a); +} + +float g1(float a) +{ + return w2(a) + w3(a); +} + +// h0 and h1 are the two offset functions +float h0(float a) +{ + return -1.0 + w1(a) / (w0(a) + w1(a)); +} + +float h1(float a) +{ + return 1.0 + w3(a) / (w2(a) + w3(a)); +} + +uniform ivec2 glow_texture_size; + +vec4 texture2D_bicubic(sampler2D tex, vec2 uv,int p_lod) +{ + float lod=float(p_lod); + vec2 tex_size = vec2(glow_texture_size >> p_lod); + vec2 pixel_size =1.0/tex_size; + uv = uv*tex_size + 0.5; + vec2 iuv = floor( uv ); + vec2 fuv = fract( uv ); + + float g0x = g0(fuv.x); + float g1x = g1(fuv.x); + float h0x = h0(fuv.x); + float h1x = h1(fuv.x); + float h0y = h0(fuv.y); + float h1y = h1(fuv.y); + + vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - 0.5) * pixel_size; + vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - 0.5) * pixel_size; + vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - 0.5) * pixel_size; + vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - 0.5) * pixel_size; + + return g0(fuv.y) * (g0x * textureLod(tex, p0,lod) + + g1x * textureLod(tex, p1,lod)) + + g1(fuv.y) * (g0x * textureLod(tex, p2,lod) + + g1x * textureLod(tex, p3,lod)); +} + + + +#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) texture2D_bicubic(m_tex,m_uv,m_lod) + +#else + +#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) textureLod(m_tex,m_uv,float(m_lod)) + +#endif + + +vec3 tonemap_filmic(vec3 color,float white) { + + float A = 0.15; + float B = 0.50; + float C = 0.10; + float D = 0.20; + float E = 0.02; + float F = 0.30; + float W = 11.2; + + vec3 coltn = ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; + float whitetn = ((white*(A*white+C*B)+D*E)/(white*(A*white+B)+D*F))-E/F; + + return coltn/whitetn; + +} + +vec3 tonemap_aces(vec3 color) { + float a = 2.51f; + float b = 0.03f; + float c = 2.43f; + float d = 0.59f; + float e = 0.14f; + return color = clamp((color*(a*color+b))/(color*(c*color+d)+e),vec3(0.0),vec3(1.0)); +} + +vec3 tonemap_reindhart(vec3 color,float white) { + + return ( color * ( 1.0 + ( color / ( white) ) ) ) / ( 1.0 + color ); +} + +void main() { + + vec4 color = textureLod(source, uv_interp, 0.0); + +#ifdef USE_AUTO_EXPOSURE + + color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey; +#endif + + color*=exposure; + +#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7) +#define USING_GLOW +#endif + +#if defined(USING_GLOW) + vec3 glow = vec3(0.0); + +#ifdef USE_GLOW_LEVEL1 + + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,1).rgb; +#endif + +#ifdef USE_GLOW_LEVEL2 + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,2).rgb; +#endif + +#ifdef USE_GLOW_LEVEL3 + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,3).rgb; +#endif + +#ifdef USE_GLOW_LEVEL4 + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,4).rgb; +#endif + +#ifdef USE_GLOW_LEVEL5 + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,5).rgb; +#endif + +#ifdef USE_GLOW_LEVEL6 + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,6).rgb; +#endif + +#ifdef USE_GLOW_LEVEL7 + glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,7).rgb; +#endif + + + glow *= glow_intensity; + +#endif + + +#ifdef USE_REINDHART_TONEMAPPER + + color.rgb = tonemap_reindhart(color.rgb,white); + +# if defined(USING_GLOW) + glow = tonemap_reindhart(glow,white); +# endif + +#endif + +#ifdef USE_FILMIC_TONEMAPPER + + color.rgb = tonemap_filmic(color.rgb,white); + +# if defined(USING_GLOW) + glow = tonemap_filmic(glow,white); +# endif + +#endif + +#ifdef USE_ACES_TONEMAPPER + + color.rgb = tonemap_aces(color.rgb); + +# if defined(USING_GLOW) + glow = tonemap_aces(glow); +# endif + +#endif + + //regular Linear -> SRGB conversion + vec3 a = vec3(0.055); + color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308))); + +#if defined(USING_GLOW) + glow = mix( (vec3(1.0)+a)*pow(glow,vec3(1.0/2.4))-a , 12.92*glow , lessThan(glow,vec3(0.0031308))); +#endif + +//glow needs to be added in SRGB space (together with image space effects) + + color.rgb = clamp(color.rgb,0.0,1.0); + +#if defined(USING_GLOW) + glow = clamp(glow,0.0,1.0); +#endif + +#ifdef USE_GLOW_REPLACE + + color.rgb = glow; + +#endif + +#ifdef USE_GLOW_SCREEN + + color.rgb = max((color.rgb + glow) - (color.rgb * glow), vec3(0.0)); + +#endif + +#ifdef USE_GLOW_SOFTLIGHT + + { + + glow = (glow * 0.5) + 0.5; + color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r))); + color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g))); + color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b))); + } + +#endif + +#if defined(USING_GLOW) && !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE) + //additive + color.rgb+=glow; +#endif + +#ifdef USE_BCS + + color.rgb = mix(vec3(0.0),color.rgb,bcs.x); + color.rgb = mix(vec3(0.5),color.rgb,bcs.y); + color.rgb = mix(vec3(dot(vec3(1.0),color.rgb)*0.33333),color.rgb,bcs.z); + +#endif + +#ifdef USE_COLOR_CORRECTION + + color.r = texture(color_correction,vec2(color.r,0.0)).r; + color.g = texture(color_correction,vec2(color.g,0.0)).g; + color.b = texture(color_correction,vec2(color.b,0.0)).b; +#endif + + + frag_color=vec4(color.rgb,1.0); +} diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 37a2450377..c33fdaa355 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -450,6 +450,16 @@ void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_v storage->frame.canvas_draw_commands++; } +static const GLenum gl_primitive[] = { + GL_POINTS, + GL_LINES, + GL_LINE_STRIP, + GL_LINE_LOOP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN +}; + void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip) { int cc = p_item->commands.size(); @@ -556,7 +566,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } else { - _draw_generic(GL_LINES, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); + _draw_generic(GL_LINE_STRIP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); } #ifdef GLES_OVER_GL @@ -735,6 +745,36 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur #endif } break; + case Item::Command::TYPE_MESH: { + + Item::CommandMesh *mesh = static_cast<Item::CommandMesh *>(c); + _set_texture_rect_mode(false); + + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mesh->texture, mesh->normal_map); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + } + + RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); + if (mesh_data) { + + for (int j = 0; j < mesh_data->surfaces.size(); j++) { + RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; + // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing + glBindVertexArray(s->array_id); + + if (s->index_array_len) { + glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); + } else { + glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); + } + + glBindVertexArray(0); + } + } + } break; case Item::Command::TYPE_PARTICLES: { Item::CommandParticles *particles_cmd = static_cast<Item::CommandParticles *>(c); @@ -993,18 +1033,16 @@ void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) { glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); - state.canvas_shader.bind(); //back to canvas - _bind_canvas_texture(state.current_tex, state.current_normal); + // back to canvas, force rebind + state.using_texture_rect = true; + _set_texture_rect_mode(false); - if (state.using_texture_rect) { - state.using_texture_rect = false; - _set_texture_rect_mode(state.using_texture_rect, state.using_ninepatch); - } + _bind_canvas_texture(state.current_tex, state.current_normal); glEnable(GL_BLEND); } -void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light) { +void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform) { Item *current_clip = NULL; RasterizerStorageGLES3::Shader *shader_cache = NULL; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 9f1a9466f1..1dc17f98d5 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -129,7 +129,7 @@ public: _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip); _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); + virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform); virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow); virtual void 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_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index b43deab58f..ca39d9f966 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -160,29 +160,31 @@ void RasterizerGLES3::initialize() { "Fatal error: Insufficient OpenGL / GLES driver support"); } -#ifdef __APPLE__ -// FIXME glDebugMessageCallbackARB does not seem to work on Mac OS X and opengl 3, this may be an issue with our opengl canvas.. -#else if (OS::get_singleton()->is_stdout_verbose()) { - glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - glDebugMessageCallbackARB(_gl_debug_print, NULL); - glEnable(_EXT_DEBUG_OUTPUT); + if (GLAD_GL_ARB_debug_output) { + glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + glDebugMessageCallbackARB(_gl_debug_print, NULL); + glEnable(_EXT_DEBUG_OUTPUT); + } else { + print_line("OpenGL debugging not supported!"); + } } -#endif #endif // GLAD_ENABLED /* // For debugging - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_ERROR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PORTABILITY_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PERFORMANCE_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_OTHER_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); - glDebugMessageInsertARB( - GL_DEBUG_SOURCE_API_ARB, - GL_DEBUG_TYPE_OTHER_ARB, 1, - GL_DEBUG_SEVERITY_HIGH_ARB,5, "hello"); + if (GLAD_GL_ARB_debug_output) { + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_ERROR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PORTABILITY_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_PERFORMANCE_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB,GL_DEBUG_TYPE_OTHER_ARB,GL_DEBUG_SEVERITY_HIGH_ARB,0,NULL,GL_TRUE); + glDebugMessageInsertARB( + GL_DEBUG_SOURCE_API_ARB, + GL_DEBUG_TYPE_OTHER_ARB, 1, + GL_DEBUG_SEVERITY_HIGH_ARB,5, "hello"); + } */ const GLubyte *renderer = glGetString(GL_RENDERER); @@ -413,4 +415,5 @@ RasterizerGLES3::~RasterizerGLES3() { memdelete(storage); memdelete(canvas); + memdelete(scene); } diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 7c053e8f60..02d851288a 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2356,8 +2356,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) { - if (!p_sky) - return; + ERR_FAIL_COND(!p_sky); RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_sky->panorama); @@ -4337,7 +4336,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters */ - _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy); + if (sky && sky->panorama.is_valid()) + _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy); } //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); @@ -5118,3 +5118,23 @@ void RasterizerSceneGLES3::finalize() { RasterizerSceneGLES3::RasterizerSceneGLES3() { } + +RasterizerSceneGLES3::~RasterizerSceneGLES3() { + + memdelete(default_material.get_data()); + memdelete(default_material_twosided.get_data()); + memdelete(default_shader.get_data()); + memdelete(default_shader_twosided.get_data()); + + memdelete(default_worldcoord_material.get_data()); + memdelete(default_worldcoord_material_twosided.get_data()); + memdelete(default_worldcoord_shader.get_data()); + memdelete(default_worldcoord_shader_twosided.get_data()); + + memdelete(default_overdraw_material.get_data()); + memdelete(default_overdraw_shader.get_data()); + + memfree(state.spot_array_tmp); + memfree(state.omni_array_tmp); + memfree(state.reflection_array_tmp); +} diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 1b99e119ce..a6faeef473 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -852,6 +852,7 @@ public: void initialize(); void finalize(); RasterizerSceneGLES3(); + ~RasterizerSceneGLES3(); }; #endif // RASTERIZERSCENEGLES3_H diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 0fc095a868..a287dca1ed 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -908,7 +908,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSi return Ref<Image>(img); #else - ERR_EXPLAIN("Sorry, It's not posible to obtain images back in OpenGL ES"); + ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES"); return Ref<Image>(); #endif } diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index f1d7085d54..070c661c8a 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -477,22 +477,22 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener current_func_name = fnode->name; - if (fnode->name == "vertex") { + if (fnode->name == vertex_name) { _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.vertex_global, added_vtx); - r_gen_code.vertex = function_code["vertex"]; + r_gen_code.vertex = function_code[vertex_name]; } - if (fnode->name == "fragment") { + if (fnode->name == fragment_name) { _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); - r_gen_code.fragment = function_code["fragment"]; + r_gen_code.fragment = function_code[fragment_name]; } - if (fnode->name == "light") { + if (fnode->name == light_name) { _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); - r_gen_code.light = function_code["light"]; + r_gen_code.light = function_code[light_name]; } } @@ -573,7 +573,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener if (current_func_name == vertex_name) { r_gen_code.uses_vertex_time = true; } - if (current_func_name == fragment_name) { + if (current_func_name == fragment_name || current_func_name == light_name) { r_gen_code.uses_fragment_time = true; } } @@ -939,6 +939,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { vertex_name = "vertex"; fragment_name = "fragment"; + light_name = "light"; time_name = "TIME"; List<String> func_list; diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h index 85e8e02b8e..bf776ee062 100644 --- a/drivers/gles3/shader_compiler_gles3.h +++ b/drivers/gles3/shader_compiler_gles3.h @@ -83,6 +83,7 @@ private: StringName current_func_name; StringName vertex_name; StringName fragment_name; + StringName light_name; StringName time_name; Set<StringName> used_name_defines; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index e90245b300..9639f06345 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -156,38 +156,50 @@ Error AudioDriverPulseAudio::init() { exit_thread = false; mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE); - channels = detect_channels(); - switch (channels) { + // Detect the amount of channels PulseAudio is using + // Note: If using an even amount of channels (2, 4, etc) channels and pa_channels will be equal, + // if not then pa_channels will have the real amount of channels PulseAudio is using and channels + // will have the amount of channels Godot is using (in this case it's pa_channels + 1) + pa_channels = detect_channels(); + switch (pa_channels) { + case 1: // Mono + case 3: // Surround 2.1 + case 5: // Surround 5.0 + case 7: // Surround 7.0 + channels = pa_channels + 1; + break; + case 2: // Stereo - case 4: // Surround 3.1 + case 4: // Surround 4.0 case 6: // Surround 5.1 case 8: // Surround 7.1 + channels = pa_channels; break; default: - ERR_PRINTS("PulseAudio: Unsupported number of channels: " + itos(channels)); + ERR_PRINTS("PulseAudio: Unsupported number of channels: " + itos(pa_channels)); ERR_FAIL_V(ERR_CANT_OPEN); break; } pa_sample_spec spec; spec.format = PA_SAMPLE_S16LE; - spec.channels = channels; + spec.channels = pa_channels; spec.rate = mix_rate; int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY); buffer_frames = closest_power_of_2(latency * mix_rate / 1000); - buffer_size = buffer_frames * channels; + pa_buffer_size = buffer_frames * pa_channels; if (OS::get_singleton()->is_stdout_verbose()) { - print_line("PulseAudio: detected " + itos(channels) + " channels"); + print_line("PulseAudio: detected " + itos(pa_channels) + " channels"); print_line("PulseAudio: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); } pa_buffer_attr attr; // set to appropriate buffer length (in bytes) from global settings - attr.tlength = buffer_size * sizeof(int16_t); + attr.tlength = pa_buffer_size * sizeof(int16_t); // set them to be automatically chosen attr.prebuf = (uint32_t)-1; attr.maxlength = (uint32_t)-1; @@ -209,8 +221,8 @@ Error AudioDriverPulseAudio::init() { ERR_FAIL_COND_V(pulse == NULL, ERR_CANT_OPEN); } - samples_in.resize(buffer_size); - samples_out.resize(buffer_size); + samples_in.resize(buffer_frames * channels); + samples_out.resize(pa_buffer_size); mutex = Mutex::create(); thread = Thread::create(AudioDriverPulseAudio::thread_func, this); @@ -235,7 +247,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { while (!ad->exit_thread) { if (!ad->active) { - for (unsigned int i = 0; i < ad->buffer_size; i++) { + for (unsigned int i = 0; i < ad->pa_buffer_size; i++) { ad->samples_out[i] = 0; } @@ -246,15 +258,30 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { ad->unlock(); - for (unsigned int i = 0; i < ad->buffer_size; i++) { - ad->samples_out[i] = ad->samples_in[i] >> 16; + if (ad->channels == ad->pa_channels) { + for (unsigned int i = 0; i < ad->pa_buffer_size; i++) { + ad->samples_out[i] = ad->samples_in[i] >> 16; + } + } else { + // Uneven amount of channels + unsigned int in_idx = 0; + unsigned int out_idx = 0; + + for (unsigned int i = 0; i < ad->buffer_frames; i++) { + for (unsigned int j = 0; j < ad->pa_channels - 1; j++) { + ad->samples_out[out_idx++] = ad->samples_in[in_idx++] >> 16; + } + uint32_t l = ad->samples_in[in_idx++]; + uint32_t r = ad->samples_in[in_idx++]; + ad->samples_out[out_idx++] = (l >> 1 + r >> 1) >> 16; + } } } // pa_simple_write always consumes the entire buffer int error_code; - int byte_size = ad->buffer_size * sizeof(int16_t); + int byte_size = ad->pa_buffer_size * sizeof(int16_t); if (pa_simple_write(ad->pulse, ad->samples_out.ptr(), byte_size, &error_code) < 0) { // can't recover here fprintf(stderr, "PulseAudio failed and can't recover: %s\n", pa_strerror(error_code)); @@ -328,17 +355,16 @@ AudioDriverPulseAudio::AudioDriverPulseAudio() { samples_out.clear(); mix_rate = 0; - buffer_size = 0; + buffer_frames = 0; + pa_buffer_size = 0; channels = 0; + pa_channels = 0; active = false; thread_exited = false; exit_thread = false; latency = 0; - buffer_frames = 0; - buffer_size = 0; - channels = 0; } AudioDriverPulseAudio::~AudioDriverPulseAudio() { diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 3bd1146f53..5737f24314 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -51,8 +51,9 @@ class AudioDriverPulseAudio : public AudioDriver { unsigned int mix_rate; unsigned int buffer_frames; - unsigned int buffer_size; + unsigned int pa_buffer_size; int channels; + int pa_channels; bool active; bool thread_exited; diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 4a467293fd..5a4be6df4f 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -244,7 +244,7 @@ static void _get_drives(List<String> *list) { // Parse only file:// links if (strncmp(string, "file://", 7) == 0) { // Strip any unwanted edges on the strings and push_back if it's not a duplicate - String fpath = String(string + 7).strip_edges(); + String fpath = String(string + 7).strip_edges().split_spaces()[0].percent_decode(); if (!list->find(fpath)) { list->push_back(fpath); } @@ -361,6 +361,7 @@ Error DirAccessUnix::rename(String p_path, String p_new_path) { return ::rename(p_path.utf8().get_data(), p_new_path.utf8().get_data()) == 0 ? OK : FAILED; } + Error DirAccessUnix::remove(String p_path) { if (p_path.is_rel_path()) diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 5b093a5885..a7a3eef935 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -69,6 +69,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) { fclose(f); f = NULL; + path_src = p_path; path = fix_path(p_path); //printf("opening %ls, %i\n", path.c_str(), Memory::get_static_mem_usage()); @@ -152,6 +153,16 @@ bool FileAccessUnix::is_open() const { return (f != NULL); } +String FileAccessUnix::get_path() const { + + return path_src; +} + +String FileAccessUnix::get_path_absolute() const { + + return path; +} + void FileAccessUnix::seek(size_t p_position) { ERR_FAIL_COND(!f); diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index dbb1c9f3b5..88bb39fbd1 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -51,6 +51,7 @@ class FileAccessUnix : public FileAccess { mutable Error last_error; String save_path; String path; + String path_src; static FileAccess *create_libc(); @@ -61,6 +62,9 @@ public: virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open + virtual String get_path() const; /// returns the path for the current open file + virtual String get_path_absolute() const; /// returns the absolute path for the current open file + virtual void seek(size_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file virtual size_t get_position() const; ///< get position in the file diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index aa01f22673..31c8e4ade9 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -73,15 +73,6 @@ void OS_Unix::debug_break() { assert(false); }; -int OS_Unix::get_audio_driver_count() const { - - return 1; -} -const char *OS_Unix::get_audio_driver_name(int p_driver) const { - - return "dummy"; -} - int OS_Unix::unix_initialize_audio(int p_audio_driver) { return 0; @@ -98,10 +89,11 @@ void handle_sigchld(int sig) { void OS_Unix::initialize_core() { -#ifdef NO_PTHREADS +#ifdef NO_THREADS ThreadDummy::make_default(); SemaphoreDummy::make_default(); MutexDummy::make_default(); + RWLockDummy::make_default(); #else ThreadPosix::make_default(); SemaphorePosix::make_default(); diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index a7c9015330..db0fe1e00b 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -48,12 +48,6 @@ protected: // UNIX only handles the core functions. // inheriting platforms under unix (eg. X11) should handle the rest - //virtual int get_video_driver_count() const; - //virtual const char * get_video_driver_name(int p_driver) const; - - virtual int get_audio_driver_count() const; - virtual const char *get_audio_driver_name(int p_driver) const; - virtual void initialize_core(); virtual int unix_initialize_audio(int p_audio_driver); //virtual Error initialize(int p_video_driver,int p_audio_driver); diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp index f079ae2ae2..a73b40a6f2 100644 --- a/drivers/unix/thread_posix.cpp +++ b/drivers/unix/thread_posix.cpp @@ -31,7 +31,7 @@ #include "thread_posix.h" #include "script_language.h" -#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) +#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS) #ifdef PTHREAD_BSD_SET_NAME #include <pthread_np.h> diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h index 15c9265e6d..ea2de61bd5 100644 --- a/drivers/unix/thread_posix.h +++ b/drivers/unix/thread_posix.h @@ -35,7 +35,7 @@ @author Juan Linietsky <reduzio@gmail.com> */ -#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) +#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS) #include "os/thread.h" #include <pthread.h> diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 2e64b55430..cf4d82fb07 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -261,13 +261,30 @@ Error DirAccessWindows::rename(String p_path, String p_new_path) { p_new_path = fix_path(p_new_path); - if (file_exists(p_new_path)) { - if (remove(p_new_path) != OK) { + // If we're only changing file name case we need to do a little juggling + if (p_path.to_lower() == p_new_path.to_lower()) { + WCHAR tmpfile[MAX_PATH]; + + if (!GetTempFileNameW(fix_path(get_current_dir()).c_str(), NULL, 0, tmpfile)) { return FAILED; - }; - }; + } + + if (!::ReplaceFileW(tmpfile, p_path.c_str(), NULL, 0, NULL, NULL)) { + DeleteFileW(tmpfile); + return FAILED; + } - return ::_wrename(p_path.c_str(), p_new_path.c_str()) == 0 ? OK : FAILED; + return ::_wrename(tmpfile, p_new_path.c_str()) == 0 ? OK : FAILED; + + } else { + if (file_exists(p_new_path)) { + if (remove(p_new_path) != OK) { + return FAILED; + } + } + + return ::_wrename(p_path.c_str(), p_new_path.c_str()) == 0 ? OK : FAILED; + } } Error DirAccessWindows::remove(String p_path) { diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 072790876f..e10f4d05e8 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -57,7 +57,8 @@ void FileAccessWindows::check_errors() const { Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { - String filename = fix_path(p_path); + path_src = p_path; + path = fix_path(p_path); if (f) close(); @@ -78,19 +79,19 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { backend supports utf8 encoding */ struct _stat st; - if (_wstat(filename.c_str(), &st) == 0) { + if (_wstat(path.c_str(), &st) == 0) { if (!S_ISREG(st.st_mode)) return ERR_FILE_CANT_OPEN; }; if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) { - save_path = filename; - filename = filename + ".tmp"; + save_path = path; + path = path + ".tmp"; //print_line("saving instead to "+path); } - f = _wfopen(filename.c_str(), mode_string); + f = _wfopen(path.c_str(), mode_string); if (f == NULL) { last_error = ERR_FILE_CANT_OPEN; @@ -154,6 +155,17 @@ void FileAccessWindows::close() { ERR_FAIL_COND(rename_error); } } + +String FileAccessWindows::get_path() const { + + return path_src; +} + +String FileAccessWindows::get_path_absolute() const { + + return path; +} + bool FileAccessWindows::is_open() const { return (f != NULL); diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 26bd08b7af..0462c1e942 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -46,6 +46,8 @@ class FileAccessWindows : public FileAccess { int flags; void check_errors() const; mutable Error last_error; + String path; + String path_src; String save_path; public: @@ -53,6 +55,9 @@ public: virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open + virtual String get_path() const; /// returns the path for the current open file + virtual String get_path_absolute() const; /// returns the absolute path for the current open file + virtual void seek(size_t p_position); ///< seek to a given position virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file virtual size_t get_position() const; ///< get position in the file diff --git a/editor/SCsub b/editor/SCsub index 8f87e12cb9..4ca6b9e3fd 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -4,6 +4,7 @@ Import('env') env.editor_sources = [] import os +import os.path from compat import encode_utf8, byte_to_str, open_utf8, escape_string @@ -29,6 +30,9 @@ def make_certs_header(target, source, env): g.write("};\n") g.write("#endif") + g.close() + f.close() + def make_doc_header(target, source, env): @@ -41,8 +45,8 @@ def make_doc_header(target, source, env): src = s.srcnode().abspath if not src.endswith(".xml"): continue - f = open_utf8(src, "r") - content = f.read() + with open_utf8(src, "r") as f: + content = f.read() buf += content buf = encode_utf8(docbegin + buf + docend) @@ -62,6 +66,8 @@ def make_doc_header(target, source, env): g.write("#endif") + g.close() + def make_fonts_header(target, source, env): @@ -76,9 +82,8 @@ def make_fonts_header(target, source, env): # saving uncompressed, since freetype will reference from memory pointer xl_names = [] for i in range(len(source)): - f = open(source[i].srcnode().abspath, "rb") - buf = f.read() - import os.path + with open(source[i].srcnode().abspath, "rb")as f: + buf = f.read() name = os.path.splitext(os.path.basename(source[i].srcnode().abspath))[0] @@ -91,6 +96,8 @@ def make_fonts_header(target, source, env): g.write("#endif") + g.close() + def make_translations_header(target, source, env): @@ -110,8 +117,8 @@ def make_translations_header(target, source, env): xl_names = [] for i in range(len(sorted_paths)): - f = open(sorted_paths[i], "rb") - buf = f.read() + with open(sorted_paths[i], "rb") as f: + buf = f.read() decomp_size = len(buf) buf = zlib.compress(buf) name = os.path.splitext(os.path.basename(sorted_paths[i]))[0] @@ -138,6 +145,9 @@ def make_translations_header(target, source, env): g.write("#endif") + g.close() + + def make_authors_header(target, source, env): sections = ["Project Founders", "Lead Developer", "Project Manager", "Developers"] @@ -180,6 +190,9 @@ def make_authors_header(target, source, env): g.write("#endif\n") + g.close() + f.close() + def make_donors_header(target, source, env): sections = ["Platinum sponsors", "Gold sponsors", "Mini sponsors", "Gold donors", "Silver donors", "Bronze donors"] @@ -222,6 +235,10 @@ def make_donors_header(target, source, env): g.write("#endif\n") + g.close() + f.close() + + def make_license_header(target, source, env): src_copyright = source[0].srcnode().abspath @@ -387,17 +404,23 @@ def make_license_header(target, source, env): g.write("#endif\n") + g.close() + fc.close() + f.close() + def _make_doc_data_class_path(to_path): - g = open_utf8(os.path.join(to_path,"doc_data_class_path.gen.h"), "w") - g.write("static const int _doc_data_class_path_count = " + str(len(env.doc_class_path)) + ";\n") - g.write("struct _DocDataClassPath { const char* name; const char* path; };\n") + g = open_utf8(os.path.join(to_path,"doc_data_class_path.gen.h"), "w") + g.write("static const int _doc_data_class_path_count = " + str(len(env.doc_class_path)) + ";\n") + g.write("struct _DocDataClassPath { const char* name; const char* path; };\n") + + g.write("static const _DocDataClassPath _doc_data_class_paths[" + str(len(env.doc_class_path) + 1) + "] = {\n"); + for c in sorted(env.doc_class_path): + g.write("\t{\"" + c + "\", \"" + env.doc_class_path[c] + "\"},\n") + g.write("\t{NULL, NULL}\n") + g.write("};\n") - g.write("static const _DocDataClassPath _doc_data_class_paths[" + str(len(env.doc_class_path) + 1) + "] = {\n"); - for c in sorted(env.doc_class_path): - g.write("\t{\"" + c + "\", \"" + env.doc_class_path[c] + "\"},\n") - g.write("\t{NULL, NULL}\n") - g.write("};\n") + g.close() if env['tools']: @@ -409,10 +432,9 @@ if env['tools']: reg_exporters += '\tregister_' + e + '_exporter();\n' reg_exporters_inc += '#include "platform/' + e + '/export/export.h"\n' reg_exporters += '}\n' - f = open_utf8("register_exporters.gen.cpp", "w") - f.write(reg_exporters_inc) - f.write(reg_exporters) - f.close() + with open_utf8("register_exporters.gen.cpp", "w") as f: + f.write(reg_exporters_inc) + f.write(reg_exporters) # API documentation docs = [] @@ -466,6 +488,7 @@ if env['tools']: env.add_source_files(env.editor_sources, "*.cpp") + env.add_source_files(env.editor_sources, ["#thirdparty/misc/clipper.cpp"]) SConscript('collada/SCsub') SConscript('doc/SCsub') diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp index c064f9cbdf..439ec37e71 100644 --- a/editor/animation_editor.cpp +++ b/editor/animation_editor.cpp @@ -1149,15 +1149,13 @@ void AnimationKeyEditor::_track_editor_draw() { get_icon("KeyCall", "EditorIcons") }; + Ref<Texture> valid_icon = get_icon("KeyValid", "EditorIcons"); Ref<Texture> invalid_icon = get_icon("KeyInvalid", "EditorIcons"); - Ref<Texture> invalid_icon_hover = get_icon("KeyInvalidHover", "EditorIcons"); + const Color modulate_selected = Color(0x84 / 255.0, 0xc2 / 255.0, 0xff / 255.0); Ref<Texture> hsize_icon = get_icon("Hsize", "EditorIcons"); - Ref<Texture> type_hover = get_icon("KeyHover", "EditorIcons"); - Ref<Texture> type_selected = get_icon("KeySelected", "EditorIcons"); - - int right_separator_ofs = down_icon->get_width() * 3 + add_key_icon->get_width() + interp_icon[0]->get_width() + wrap_icon[0]->get_width() + cont_icon[0]->get_width() + hsep * 9; + int right_separator_ofs = right_data_size_cache; int h = font->get_height() + sep; @@ -1268,8 +1266,21 @@ void AnimationKeyEditor::_track_editor_draw() { int decimals = 2; bool step_found = false; + const int period_width = font->get_char_size('.').width; + int max_digit_width = font->get_char_size('0').width; + for (int i = 1; i <= 9; i++) { + const int digit_width = font->get_char_size('0' + i).width; + max_digit_width = MAX(digit_width, max_digit_width); + } + const int max_sc = int(Math::ceil(zoomw / scale)); + const int max_sc_width = String::num(max_sc).length() * max_digit_width; + while (!step_found) { + min = max_sc_width; + if (decimals > 0) + min += period_width + max_digit_width * decimals; + static const int _multp[3] = { 1, 2, 5 }; for (int i = 0; i < 3; i++) { @@ -1464,6 +1475,10 @@ void AnimationKeyEditor::_track_editor_draw() { float x = key_hofs + name_limit + (time - keys_from) * zoom_scale; Ref<Texture> tex = type_icon[tt]; + Color modulate = Color(1, 1, 1); + + bool is_hover = false; + bool is_selected = false; SelectedKey sk; sk.key = i; @@ -1472,13 +1487,33 @@ void AnimationKeyEditor::_track_editor_draw() { if (click.click == ClickOver::CLICK_MOVE_KEYS) continue; - tex = type_selected; + is_selected = true; } if (mouse_over.over == MouseOver::OVER_KEY && mouse_over.track == idx && mouse_over.over_key == i) - tex = type_hover; + is_hover = true; Variant value = animation->track_get_key_value(idx, i); + + if (prop_exists && !Variant::can_convert(value.get_type(), valid_type)) { + + tex = invalid_icon; + if (is_hover) + modulate = Color(1.5, 1.5, 1.5); + else + modulate = Color(1, 1, 1); + } else if (is_selected) { + + tex = valid_icon; + modulate = modulate_selected; + if (is_hover) + modulate = modulate.lightened(0.2); + } else if (is_hover) { + + tex = valid_icon; + modulate = Color(1, 1, 1); + } + if (first && i > 0 && value == animation->track_get_key_value(idx, i - 1)) { te->draw_line(ofs + Vector2(name_limit, y + h / 2), ofs + Point2(x, y + h / 2), color); @@ -1491,19 +1526,7 @@ void AnimationKeyEditor::_track_editor_draw() { te->draw_line(ofs + Point2(x_n, y + h / 2), ofs + Point2(x, y + h / 2), color); } - if (prop_exists && !Variant::can_convert(value.get_type(), valid_type)) { - te->draw_texture(invalid_icon, ofs + Point2(x, y + key_vofs).floor()); - } - - if (prop_exists && !Variant::can_convert(value.get_type(), valid_type)) { - if (tex == type_hover) - te->draw_texture(invalid_icon_hover, ofs + Point2(x, y + key_vofs).floor()); - else - te->draw_texture(invalid_icon, ofs + Point2(x, y + key_vofs).floor()); - } else { - - te->draw_texture(tex, ofs + Point2(x, y + key_vofs).floor()); - } + te->draw_texture(tex, ofs + Point2(x, y + key_vofs).floor(), modulate); first = false; } @@ -1539,8 +1562,8 @@ void AnimationKeyEditor::_track_editor_draw() { continue; int y = h + i * h + sep; - float key_vofs = Math::floor((float)(h - type_selected->get_height()) / 2); - float key_hofs = -Math::floor((float)type_selected->get_height() / 2); + float key_vofs = Math::floor((float)(h - valid_icon->get_height()) / 2); + float key_hofs = -Math::floor((float)valid_icon->get_height() / 2); float time = animation->track_get_key_time(idx, E->key().key); float diff = time - from_t; @@ -1554,7 +1577,7 @@ void AnimationKeyEditor::_track_editor_draw() { x += name_limit; - te->draw_texture(type_selected, ofs + Point2(x + key_hofs, y + key_vofs).floor()); + te->draw_texture(valid_icon, ofs + Point2(x + key_hofs, y + key_vofs).floor(), modulate_selected); } } break; default: {}; @@ -1830,7 +1853,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input) get_icon("KeyXform", "EditorIcons"), get_icon("KeyCall", "EditorIcons") }; - int right_separator_ofs = down_icon->get_width() * 3 + add_key_icon->get_width() + interp_icon[0]->get_width() + wrap_icon[0]->get_width() + cont_icon[0]->get_width() + hsep * 9; + int right_separator_ofs = right_data_size_cache; int h = font->get_height() + sep; @@ -2930,8 +2953,8 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input) Ref<InputEventPanGesture> pan_gesture = p_input; if (pan_gesture.is_valid()) { - h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * pan_gesture->get_delta().x / 8); - v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * pan_gesture->get_delta().y / 8); + h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8); + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8); } } @@ -3042,7 +3065,7 @@ void AnimationKeyEditor::_notification(int p_what) { get_icon("InterpWrapClamp", "EditorIcons"), get_icon("InterpWrapLoop", "EditorIcons"), }; - right_data_size_cache = down_icon->get_width() * 3 + add_key_icon->get_width() + interp_icon[0]->get_width() + cont_icon[0]->get_width() + wrap_icon[0]->get_width() + hsep * 8; + right_data_size_cache = down_icon->get_width() * 3 + add_key_icon->get_width() + interp_icon[0]->get_width() + cont_icon[0]->get_width() + wrap_icon[0]->get_width() + hsep * 9; } } break; } @@ -3998,6 +4021,7 @@ AnimationKeyEditor::AnimationKeyEditor() { //key_edit->ke_dialog=key_edit_dialog; type_menu = memnew(PopupMenu); + type_menu->set_pass_on_modal_close_click(false); add_child(type_menu); for (int i = 0; i < Variant::VARIANT_MAX; i++) type_menu->add_item(Variant::get_type_name(Variant::Type(i)), i); @@ -4038,6 +4062,7 @@ AnimationKeyEditor::AnimationKeyEditor() { add_child(track_name); track_name->connect("text_entered", this, "_track_name_changed"); track_menu = memnew(PopupMenu); + track_menu->set_pass_on_modal_close_click(false); add_child(track_menu); track_menu->connect("id_pressed", this, "_track_menu_selected"); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 70334c2343..9ae9ab1501 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -666,6 +666,7 @@ void CodeTextEditor::_reset_zoom() { if (font.is_valid()) { EditorSettings::get_singleton()->set("interface/editor/code_font_size", 14); font->set_size(14); + zoom_nb->set_text("100%"); } } @@ -727,6 +728,9 @@ 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); + + zoom_nb->set_text(itos(100 * new_size / 14) + "%"); + if (new_size != font->get_size()) { EditorSettings::get_singleton()->set("interface/editor/code_font_size", new_size / EDSCALE); font->set_size(new_size); @@ -771,6 +775,14 @@ void CodeTextEditor::set_error(const String &p_error) { void CodeTextEditor::_update_font() { text_editor->add_font_override("font", get_font("source", "EditorFonts")); + + Ref<Font> status_bar_font = get_font("status_source", "EditorFonts"); + int count = status_bar->get_child_count(); + for (int i = 0; i < count; i++) { + Control *n = Object::cast_to<Control>(status_bar->get_child(i)); + if (n) + n->add_font_override("font", status_bar_font); + } } void CodeTextEditor::_on_settings_change() { @@ -851,7 +863,7 @@ CodeTextEditor::CodeTextEditor() { text_editor->set_brace_matching(true); text_editor->set_auto_indent(true); - HBoxContainer *status_bar = memnew(HBoxContainer); + status_bar = memnew(HBoxContainer); add_child(status_bar); status_bar->set_h_size_flags(SIZE_EXPAND_FILL); @@ -878,6 +890,24 @@ CodeTextEditor::CodeTextEditor() { status_bar->add_child(memnew(Label)); //to keep the height if the other labels are not visible + Label *zoom_txt = memnew(Label); + status_bar->add_child(zoom_txt); + zoom_txt->set_align(Label::ALIGN_RIGHT); + zoom_txt->set_valign(Label::VALIGN_CENTER); + zoom_txt->set_v_size_flags(SIZE_FILL); + zoom_txt->set_text(TTR("Zoom:")); + zoom_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + + zoom_nb = memnew(Label); + status_bar->add_child(zoom_nb); + zoom_nb->set_valign(Label::VALIGN_CENTER); + zoom_nb->set_v_size_flags(SIZE_FILL); + zoom_nb->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch + zoom_nb->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch + zoom_nb->set_custom_minimum_size(Size2(60, 1) * EDSCALE); + zoom_nb->set_align(Label::ALIGN_RIGHT); + zoom_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); @@ -931,7 +961,8 @@ CodeTextEditor::CodeTextEditor() { code_complete_timer->connect("timeout", this, "_code_complete_timer_timeout"); font_resize_val = 0; - font_size = -1; + font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size"); + zoom_nb->set_text(itos(100 * font_size / 14) + "%"); 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 db2e25b922..a860ad24e2 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -141,9 +141,11 @@ class CodeTextEditor : public VBoxContainer { TextEdit *text_editor; FindReplaceBar *find_replace_bar; + HBoxContainer *status_bar; Label *line_nb; Label *col_nb; + Label *zoom_nb; Label *info; Timer *idle; Timer *code_complete_timer; diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index fdc58e6292..13ef6e9e0e 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -476,6 +476,8 @@ void CreateDialog::_item_selected() { return; help_bit->set_text(EditorHelp::get_doc_data()->class_list[name].brief_description); + + get_ok()->set_disabled(false); } void CreateDialog::_favorite_toggled() { diff --git a/editor/dictionary_property_edit.cpp b/editor/dictionary_property_edit.cpp index 4c0ad59385..a87edfd00d 100644 --- a/editor/dictionary_property_edit.cpp +++ b/editor/dictionary_property_edit.cpp @@ -41,7 +41,7 @@ void DictionaryPropertyEdit::_notif_changev(const String &p_v) { void DictionaryPropertyEdit::_set_key(const Variant &p_old_key, const Variant &p_new_key) { - // TODO: Set key of a dictionary is not allowd yet + // TODO: Set key of a dictionary is not allowed yet return; } diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp index 3a418e5f33..3434aa33f9 100644 --- a/editor/doc/doc_data.cpp +++ b/editor/doc/doc_data.cpp @@ -974,7 +974,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri if (c.category == "") category = "Core"; header += " category=\"" + category + "\""; - header += String(" version=\"") + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + VERSION_STATUS + "\""; + header += String(" version=\"") + VERSION_NUMBER + "\""; header += ">"; _write_string(f, 0, header); _write_string(f, 1, "<brief_description>"); diff --git a/editor/doc/doc_dump.cpp b/editor/doc/doc_dump.cpp index 905732a43f..adbe23dcd5 100644 --- a/editor/doc/doc_dump.cpp +++ b/editor/doc/doc_dump.cpp @@ -83,7 +83,7 @@ void DocDump::dump(const String &p_file) { FileAccess *f = FileAccess::open(p_file, FileAccess::WRITE); _write_string(f, 0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); - _write_string(f, 0, String("<doc version=\"") + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + VERSION_STATUS + "\" name=\"Engine Types\">"); + _write_string(f, 0, String("<doc version=\"") + VERSION_NUMBER + "\" name=\"Engine Types\">"); while (class_list.size()) { diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 9ab539da07..360ed620f6 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -44,9 +44,11 @@ void EditorAbout::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - Ref<Font> font = EditorNode::get_singleton()->get_gui_base()->get_font("source", "EditorFonts"); + Control *base = EditorNode::get_singleton()->get_gui_base(); + Ref<Font> font = base->get_font("source", "EditorFonts"); _tpl_text->add_font_override("normal_font", font); _license_text->add_font_override("normal_font", font); + _logo->set_texture(base->get_icon("Logo", "EditorIcons")); } break; } } diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 9d0de930f2..ac4402d50b 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -121,6 +121,26 @@ void EditorAudioBus::_notification(int p_what) { set_process(is_visible_in_tree()); } + + if (p_what == NOTIFICATION_THEME_CHANGED) { + + for (int i = 0; i < cc; i++) { + channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons")); + channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons")); + channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons")); + channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons")); + channel[i].prev_active = true; + } + scale->set_texture(get_icon("BusVuDb", "EditorIcons")); + + disabled_vu = get_icon("BusVuFrozen", "EditorIcons"); + + solo->set_icon(get_icon("AudioBusSolo", "EditorIcons")); + mute->set_icon(get_icon("AudioBusMute", "EditorIcons")); + bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons")); + + bus_options->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons")); + } } void EditorAudioBus::update_send() { @@ -707,6 +727,9 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { channel[i].vu_r->set_min(-80); channel[i].vu_r->set_max(24); channel[i].vu_r->set_step(0.1); + + channel[i].peak_l = 0.0f; + channel[i].peak_r = 0.0f; } scale = memnew(TextureRect); @@ -716,6 +739,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { effects->set_hide_root(true); effects->set_custom_minimum_size(Size2(0, 100) * EDSCALE); effects->set_hide_folding(true); + effects->set_v_size_flags(SIZE_EXPAND_FILL); vb->add_child(effects); effects->connect("item_edited", this, "_effect_edited"); effects->connect("cell_selected", this, "_effect_selected"); @@ -1148,6 +1172,7 @@ EditorAudioBuses::EditorAudioBuses() { bus_scroll->set_enable_v_scroll(false); add_child(bus_scroll); bus_hb = memnew(HBoxContainer); + bus_hb->set_v_size_flags(SIZE_EXPAND_FILL); bus_scroll->add_child(bus_hb); save_timer = memnew(Timer); diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index d3e697ac35..a2f5c1aa1a 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -92,45 +92,7 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin void EditorAutoloadSettings::_autoload_add() { - String name = autoload_add_name->get_text(); - - String error; - if (!_autoload_name_is_valid(name, &error)) { - EditorNode::get_singleton()->show_warning(error); - return; - } - - String path = autoload_add_path->get_line_edit()->get_text(); - if (!FileAccess::exists(path)) { - EditorNode::get_singleton()->show_warning(TTR("Invalid Path.") + "\n" + TTR("File does not exist.")); - return; - } - - if (!path.begins_with("res://")) { - EditorNode::get_singleton()->show_warning(TTR("Invalid Path.") + "\n" + TTR("Not in resource path.")); - return; - } - - name = "autoload/" + name; - - UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); - - undo_redo->create_action(TTR("Add AutoLoad")); - undo_redo->add_do_property(ProjectSettings::get_singleton(), name, "*" + path); - - if (ProjectSettings::get_singleton()->has_setting(name)) { - undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, ProjectSettings::get_singleton()->get(name)); - } else { - undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, Variant()); - } - - undo_redo->add_do_method(this, "update_autoload"); - undo_redo->add_undo_method(this, "update_autoload"); - - undo_redo->add_do_method(this, "emit_signal", autoload_changed); - undo_redo->add_undo_method(this, "emit_signal", autoload_changed); - - undo_redo->commit_action(); + autoload_add(autoload_add_name->get_text(), autoload_add_path->get_line_edit()->get_text()); autoload_add_path->get_line_edit()->set_text(""); autoload_add_name->set_text(""); @@ -539,6 +501,74 @@ void EditorAutoloadSettings::drop_data_fw(const Point2 &p_point, const Variant & undo_redo->commit_action(); } +void EditorAutoloadSettings::autoload_add(const String &p_name, const String &p_path) { + + String name = p_name; + + String error; + if (!_autoload_name_is_valid(name, &error)) { + EditorNode::get_singleton()->show_warning(error); + return; + } + + String path = p_path; + if (!FileAccess::exists(path)) { + EditorNode::get_singleton()->show_warning(TTR("Invalid Path.") + "\n" + TTR("File does not exist.")); + return; + } + + if (!path.begins_with("res://")) { + EditorNode::get_singleton()->show_warning(TTR("Invalid Path.") + "\n" + TTR("Not in resource path.")); + return; + } + + name = "autoload/" + name; + + UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); + + undo_redo->create_action(TTR("Add AutoLoad")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), name, "*" + path); + + if (ProjectSettings::get_singleton()->has_setting(name)) { + undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, ProjectSettings::get_singleton()->get(name)); + } else { + undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, Variant()); + } + + undo_redo->add_do_method(this, "update_autoload"); + undo_redo->add_undo_method(this, "update_autoload"); + + undo_redo->add_do_method(this, "emit_signal", autoload_changed); + undo_redo->add_undo_method(this, "emit_signal", autoload_changed); + + undo_redo->commit_action(); +} + +void EditorAutoloadSettings::autoload_remove(const String &p_name) { + + String name = "autoload/" + p_name; + + UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); + + int order = ProjectSettings::get_singleton()->get_order(name); + + undo_redo->create_action(TTR("Remove Autoload")); + + undo_redo->add_do_property(ProjectSettings::get_singleton(), name, Variant()); + + undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, ProjectSettings::get_singleton()->get(name)); + undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_persisting", name, true); + undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", order); + + undo_redo->add_do_method(this, "update_autoload"); + undo_redo->add_undo_method(this, "update_autoload"); + + undo_redo->add_do_method(this, "emit_signal", autoload_changed); + undo_redo->add_undo_method(this, "emit_signal", autoload_changed); + + undo_redo->commit_action(); +} + void EditorAutoloadSettings::_bind_methods() { ClassDB::bind_method("_autoload_add", &EditorAutoloadSettings::_autoload_add); @@ -554,6 +584,8 @@ void EditorAutoloadSettings::_bind_methods() { ClassDB::bind_method("drop_data_fw", &EditorAutoloadSettings::drop_data_fw); ClassDB::bind_method("update_autoload", &EditorAutoloadSettings::update_autoload); + ClassDB::bind_method("autoload_add", &EditorAutoloadSettings::autoload_add); + ClassDB::bind_method("autoload_remove", &EditorAutoloadSettings::autoload_remove); ADD_SIGNAL(MethodInfo("autoload_changed")); } @@ -611,10 +643,10 @@ EditorAutoloadSettings::EditorAutoloadSettings() { tree->set_column_title(2, TTR("Singleton")); tree->set_column_expand(2, false); - tree->set_column_min_width(2, 80); + tree->set_column_min_width(2, 80 * EDSCALE); tree->set_column_expand(3, false); - tree->set_column_min_width(3, 120); + tree->set_column_min_width(3, 120 * EDSCALE); tree->connect("cell_selected", this, "_autoload_selected"); tree->connect("item_edited", this, "_autoload_edited"); diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h index 2e34a8b17f..6f622de6d5 100644 --- a/editor/editor_autoload_settings.h +++ b/editor/editor_autoload_settings.h @@ -87,6 +87,8 @@ protected: public: void update_autoload(); + void autoload_add(const String &p_name, const String &p_path); + void autoload_remove(const String &p_name); EditorAutoloadSettings(); }; diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index c9ac62a74d..7456cc902a 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -274,8 +274,6 @@ void EditorExportPlatform::gen_debug_flags(Vector<String> &r_flags, int p_flags) } Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) { - if (p_path.ends_with(".so") || p_path.ends_with(".dylib") || p_path.ends_with(".dll")) - return OK; PackData *pd = (PackData *)p_userdata; @@ -337,7 +335,7 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat String EditorExportPlatform::find_export_template(String template_file_name, String *err) const { - String current_version = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + VERSION_STATUS + VERSION_MODULE_CONFIG; + String current_version = VERSION_FULL_CONFIG; String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(current_version).plus_file(template_file_name); if (FileAccess::exists(template_path)) { @@ -1354,27 +1352,24 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Error err = da->copy(template_path, p_path, get_chmod_flags()); - memdelete(da); - - if (err != OK) { - return err; - } - - String pck_path = p_path.get_basename() + ".pck"; + if (err == OK) { + String pck_path = p_path.get_basename() + ".pck"; - Vector<SharedObject> so_files; + Vector<SharedObject> so_files; - err = save_pack(p_preset, pck_path, &so_files); + err = save_pack(p_preset, pck_path, &so_files); - if (err != OK || so_files.empty()) - return err; - //if shared object files, copy them - da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - for (int i = 0; i < so_files.size(); i++) { - da->copy(so_files[i].path, p_path.get_base_dir().plus_file(so_files[i].path.get_file())); + if (err == OK && !so_files.empty()) { + //if shared object files, copy them + da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + for (int i = 0; i < so_files.size() && err == OK; i++) { + err = da->copy(so_files[i].path, p_path.get_base_dir().plus_file(so_files[i].path.get_file())); + } + } } + memdelete(da); - return OK; + return err; } void EditorExportPlatformPC::set_extension(const String &p_extension, const String &p_feature_key) { diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 22b33cc98f..c52f25e66b 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -551,7 +551,7 @@ void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p } if (single_item_selected) { - item_menu->add_icon_item(get_icon("CopyNodePath", "EditorIcons"), TTR("Copy Path"), ITEM_MENU_COPY_PATH); + item_menu->add_icon_item(get_icon("ActionCopy", "EditorIcons"), TTR("Copy Path"), ITEM_MENU_COPY_PATH); } if (allow_delete) { item_menu->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete"), ITEM_MENU_DELETE, KEY_DELETE); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index dca32d7492..d8ae1da72e 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -275,9 +275,13 @@ void EditorFileSystem::_scan_filesystem() { memdelete(d); f = FileAccess::open(fscache, FileAccess::WRITE); - _save_filesystem_cache(new_filesystem, f); - f->close(); - memdelete(f); + if (f == NULL) { + ERR_PRINTS("Error writing fscache: " + fscache); + } else { + _save_filesystem_cache(new_filesystem, f); + f->close(); + memdelete(f); + } scanning = false; } @@ -286,9 +290,13 @@ void EditorFileSystem::_save_filesystem_cache() { String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_cache3"); FileAccess *f = FileAccess::open(fscache, FileAccess::WRITE); - _save_filesystem_cache(filesystem, f); - f->close(); - memdelete(f); + if (f == NULL) { + ERR_PRINTS("Error writing fscache: " + fscache); + } else { + _save_filesystem_cache(filesystem, f); + f->close(); + memdelete(f); + } } void EditorFileSystem::_thread_func(void *_userdata) { @@ -321,10 +329,10 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo List<String> to_check; - String source_file; - String source_md5; + String source_file = ""; + String source_md5 = ""; Vector<String> dest_files; - String dest_md5; + String dest_md5 = ""; while (true) { @@ -334,7 +342,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true); if (err == ERR_FILE_EOF) { - memdelete(f); break; } else if (err != OK) { ERR_PRINTS("ResourceFormatImporter::load - " + p_path + ".import:" + itos(lines) + " error: " + error_text); @@ -351,12 +358,8 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo to_check.push_back(fa[i]); } } else if (!p_only_imported_files) { - if (assign == "source_md5") { - source_md5 = value; - } else if (assign == "source_file") { + if (assign == "source_file") { source_file = value; - } else if (assign == "dest_md5") { - dest_md5 = value; } else if (assign == "dest_files") { dest_files = value; } @@ -369,6 +372,42 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo memdelete(f); + // Read the md5's from a separate file (so the import parameters aren't dependant on the file version + String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_path); + FileAccess *md5s = FileAccess::open(base_path + ".md5", FileAccess::READ, &err); + if (!md5s) { // No md5's stored for this resource + return true; + } + + VariantParser::StreamFile md5_stream; + md5_stream.f = md5s; + + while (true) { + assign = Variant(); + next_tag.fields.clear(); + next_tag.name = String(); + + err = VariantParser::parse_tag_assign_eof(&md5_stream, lines, error_text, next_tag, assign, value, NULL, true); + + if (err == ERR_FILE_EOF) { + break; + } else if (err != OK) { + ERR_PRINTS("ResourceFormatImporter::load - " + p_path + ".import.md5:" + itos(lines) + " error: " + error_text); + memdelete(md5s); + return false; // parse error + } + if (assign != String()) { + if (!p_only_imported_files) { + if (assign == "source_md5") { + source_md5 = value; + } else if (assign == "dest_md5") { + dest_md5 = value; + } + } + } + } + memdelete(md5s); + //imported files are gone, reimport for (List<String>::Element *E = to_check.front(); E; E = E->next()) { if (!FileAccess::exists(E->get())) { @@ -1316,6 +1355,9 @@ void EditorFileSystem::update_file(const String &p_file) { fs->files[cpos]->deps = _get_dependencies(p_file); fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file); + // Update preview + EditorResourcePreview::get_singleton()->check_for_invalidation(p_file); + call_deferred("emit_signal", "filesystem_changed"); //update later } @@ -1456,15 +1498,13 @@ void EditorFileSystem::_reimport_file(const String &p_file) { } f->store_line("source_file=" + Variant(p_file).get_construct_string()); - f->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\"\n"); if (dest_paths.size()) { Array dp; for (int i = 0; i < dest_paths.size(); i++) { dp.push_back(dest_paths[i]); } - f->store_line("dest_files=" + Variant(dp).get_construct_string()); - f->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n"); + f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n"); } f->store_line("[params]"); @@ -1483,6 +1523,16 @@ void EditorFileSystem::_reimport_file(const String &p_file) { f->close(); memdelete(f); + // Store the md5's of the various files. These are stored separately so that the .import files can be version controlled. + FileAccess *md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE); + ERR_FAIL_COND(!md5s); + md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\""); + if (dest_paths.size()) { + md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n"); + } + md5s->close(); + memdelete(md5s); + //update modified times, to avoid reimport fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import"); diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index a58257962a..2ec3cdb08f 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -103,9 +103,11 @@ void editor_register_fonts(Ref<Theme> p_theme) { /* Custom font */ String custom_font = EditorSettings::get_singleton()->get("interface/editor/main_font"); + DynamicFontData::Hinting font_hinting = (DynamicFontData::Hinting)(int)EditorSettings::get_singleton()->get("interface/editor/main_font_hinting"); Ref<DynamicFontData> CustomFont; if (custom_font.length() > 0) { CustomFont.instance(); + CustomFont->set_hinting(font_hinting); CustomFont->set_font_path(custom_font); CustomFont->set_force_autohinter(true); //just looks better..i think? } @@ -113,9 +115,11 @@ void editor_register_fonts(Ref<Theme> p_theme) { /* Custom source code font */ String custom_font_source = EditorSettings::get_singleton()->get("interface/editor/code_font"); + DynamicFontData::Hinting font_source_hinting = (DynamicFontData::Hinting)(int)EditorSettings::get_singleton()->get("interface/editor/code_font_hinting"); Ref<DynamicFontData> CustomFontSource; if (custom_font_source.length() > 0) { CustomFontSource.instance(); + CustomFontSource->set_hinting(font_source_hinting); CustomFontSource->set_font_path(custom_font_source); } @@ -123,38 +127,45 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<DynamicFontData> DefaultFont; DefaultFont.instance(); + DefaultFont->set_hinting(font_hinting); DefaultFont->set_font_ptr(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size); DefaultFont->set_force_autohinter(true); //just looks better..i think? Ref<DynamicFontData> FontFallback; FontFallback.instance(); + FontFallback->set_hinting(font_hinting); FontFallback->set_font_ptr(_font_DroidSansFallback, _font_DroidSansFallback_size); FontFallback->set_force_autohinter(true); //just looks better..i think? Ref<DynamicFontData> FontJapanese; FontJapanese.instance(); + FontJapanese->set_hinting(font_hinting); FontJapanese->set_font_ptr(_font_DroidSansJapanese, _font_DroidSansJapanese_size); FontJapanese->set_force_autohinter(true); //just looks better..i think? Ref<DynamicFontData> FontArabic; FontArabic.instance(); + FontArabic->set_hinting(font_hinting); FontArabic->set_font_ptr(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size); FontArabic->set_force_autohinter(true); //just looks better..i think? Ref<DynamicFontData> FontHebrew; FontHebrew.instance(); + FontHebrew->set_hinting(font_hinting); FontHebrew->set_font_ptr(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size); FontHebrew->set_force_autohinter(true); //just looks better..i think? Ref<DynamicFontData> FontThai; FontThai.instance(); + FontThai->set_hinting(font_hinting); FontThai->set_font_ptr(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size); FontThai->set_force_autohinter(true); //just looks better..i think? - /* Source Code Pro */ + /* Hack */ Ref<DynamicFontData> dfmono; dfmono.instance(); + dfmono->set_hinting(font_source_hinting); dfmono->set_font_ptr(_font_Hack_Regular, _font_Hack_Regular_size); //dfd->set_force_autohinter(true); //just looks better..i think? diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index e301d12214..158eedfb0f 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -88,6 +88,7 @@ void EditorLog::_notification(int p_what) { void EditorLog::_clear_request() { log->clear(); + tool_button->set_icon(Ref<Texture>()); } void EditorLog::clear() { @@ -103,9 +104,7 @@ void EditorLog::add_message(const String &p_msg, bool p_error) { Ref<Texture> icon = get_icon("Error", "EditorIcons"); log->add_image(icon); log->add_text(" "); - //button->set_icon(icon); - } else { - //button->set_icon(Ref<Texture>()); + tool_button->set_icon(icon); } log->add_text(p_msg); @@ -115,6 +114,10 @@ void EditorLog::add_message(const String &p_msg, bool p_error) { log->pop(); } +void EditorLog::set_tool_button(ToolButton *p_tool_button) { + tool_button = p_tool_button; +} + /* void EditorLog::_dragged(const Point2& p_ofs) { diff --git a/editor/editor_log.h b/editor/editor_log.h index 42137f71cc..f9bc82de7d 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -51,6 +51,7 @@ class EditorLog : public VBoxContainer { RichTextLabel *log; HBoxContainer *title_hb; //PaneDrag *pd; + ToolButton *tool_button; static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type); @@ -68,6 +69,7 @@ protected: public: void add_message(const String &p_msg, bool p_error = false); + void set_tool_button(ToolButton *p_tool_button); void deinit(); void clear(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index e56cf044f6..97b466f75a 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -99,7 +99,9 @@ #include "editor/plugins/script_text_editor.h" #include "editor/plugins/shader_editor_plugin.h" #include "editor/plugins/shader_graph_editor_plugin.h" +#include "editor/plugins/skeleton_2d_editor_plugin.h" #include "editor/plugins/spatial_editor_plugin.h" +#include "editor/plugins/sprite_editor_plugin.h" #include "editor/plugins/sprite_frames_editor_plugin.h" #include "editor/plugins/style_box_editor_plugin.h" #include "editor/plugins/texture_editor_plugin.h" @@ -347,14 +349,20 @@ void EditorNode::_notification(int p_what) { // update_icons for (int i = 0; i < singleton->main_editor_buttons.size(); i++) { - Ref<Texture> icon = singleton->main_editor_buttons[i]->get_icon(); + + ToolButton *tb = singleton->main_editor_buttons[i]; + EditorPlugin *p_editor = singleton->editor_table[i]; + Ref<Texture> icon = p_editor->get_icon(); if (icon.is_valid()) { - main_editor_buttons[i]->set_icon(icon); - } else if (singleton->gui_base->has_icon(singleton->main_editor_buttons[i]->get_name(), "EditorIcons")) { - main_editor_buttons[i]->set_icon(gui_base->get_icon(singleton->main_editor_buttons[i]->get_name(), "EditorIcons")); + tb->set_icon(icon); + } else if (singleton->gui_base->has_icon(p_editor->get_name(), "EditorIcons")) { + tb->set_icon(singleton->gui_base->get_icon(p_editor->get_name(), "EditorIcons")); } } + + _build_icon_type_cache(); + play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons")); play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons")); play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons")); @@ -380,6 +388,15 @@ void EditorNode::_notification(int p_what) { dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons")); dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons")); update_menu->set_icon(gui_base->get_icon("Progress1", "EditorIcons")); + + PopupMenu *p = help_menu->get_popup(); + p->set_item_icon(p->get_item_index(HELP_CLASSES), gui_base->get_icon("ClassList", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_icon("HelpSearch", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_icon("Instance", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_icon("Instance", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_ISSUES), gui_base->get_icon("Instance", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_icon("Instance", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_icon("Godot", "EditorIcons")); } if (p_what == Control::NOTIFICATION_RESIZED) { @@ -587,6 +604,10 @@ void EditorNode::open_resource(const String &p_type) { void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) { editor_data.apply_changes_in_editors(); + if (p_resource->get_last_modified_time() == p_resource->get_import_last_modified_time()) { + return; + } + int flg = 0; if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) flg |= ResourceSaver::FLAG_COMPRESS; @@ -595,6 +616,7 @@ void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const St Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS); if (err != OK) { + current_option = -1; accept->set_text(TTR("Error saving resource!")); accept->popup_centered_minsize(); return; @@ -981,6 +1003,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { String file = cache_base + ".png"; + post_process_preview(img); img->save_png(file); } @@ -1070,7 +1093,8 @@ void EditorNode::_save_scene(String p_file, int idx) { void EditorNode::_save_all_scenes() { - for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { + int i = _next_unsaved_scene(true, 0); + while (i != -1) { Node *scene = editor_data.get_edited_scene_root(i); if (scene && scene->get_filename() != "") { if (i != editor_data.get_edited_scene()) @@ -1078,6 +1102,7 @@ void EditorNode::_save_all_scenes() { else _save_scene_with_preview(scene->get_filename()); } // else: ignore new scenes + i = _next_unsaved_scene(true, ++i); } _save_default_environment(); @@ -1192,6 +1217,7 @@ void EditorNode::_dialog_action(String p_file) { Error err = ResourceSaver::save(p_file, ml); if (err) { + current_option = -1; accept->get_ok()->set_text(TTR("I see..")); accept->set_text(TTR("Error saving MeshLibrary!")); accept->popup_centered_minsize(); @@ -1226,6 +1252,7 @@ void EditorNode::_dialog_action(String p_file) { Error err = ResourceSaver::save(p_file, ml); if (err) { + current_option = -1; accept->get_ok()->set_text(TTR("I see..")); accept->set_text(TTR("Error saving TileSet!")); accept->popup_centered_minsize(); @@ -1572,7 +1599,8 @@ void EditorNode::_edit_current() { // special case if use of external editor is true if (main_plugin->get_name() == "Script" && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { - main_plugin->edit(current_obj); + if (!changing_scene) + main_plugin->edit(current_obj); } else if (main_plugin != editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) { @@ -1784,7 +1812,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { editor_data.save_editor_external_data(); } - if (!_call_build()) + if (!call_build()) return; if (bool(EDITOR_DEF("run/output/always_clear_output_on_play", true))) { @@ -2317,7 +2345,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (run_native->is_deploy_debug_remote_enabled()) { _menu_option_confirm(RUN_STOP, true); - if (!_call_build()) + if (!call_build()) break; // build failed emit_signal("play_pressed"); @@ -2927,7 +2955,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { if (p_state.has("editor_index")) { int index = p_state["editor_index"]; - if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if curently in script, stay there + if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there if (index < 2 || !get_edited_scene()) { _editor_select(index); } @@ -3459,6 +3487,19 @@ Ref<Texture> EditorNode::_file_dialog_get_icon(const String &p_path) { return singleton->icon_type_cache["Object"]; } +void EditorNode::_build_icon_type_cache() { + + List<StringName> tl; + StringName ei = "EditorIcons"; + theme_base->get_theme()->get_icon_list(ei, &tl); + for (List<StringName>::Element *E = tl.front(); E; E = E->next()) { + + if (!ClassDB::class_exists(E->get())) + continue; + icon_type_cache[E->get()] = theme_base->get_theme()->get_icon(E->get(), ei); + } +} + void EditorNode::_file_dialog_register(FileDialog *p_dialog) { singleton->file_dialogs.insert(p_dialog); @@ -4584,7 +4625,7 @@ void EditorNode::add_build_callback(EditorBuildCallback p_callback) { EditorBuildCallback EditorNode::build_callbacks[EditorNode::MAX_BUILD_CALLBACKS]; -bool EditorNode::_call_build() { +bool EditorNode::call_build() { for (int i = 0; i < build_callback_count; i++) { if (!build_callbacks[i]()) @@ -5190,7 +5231,6 @@ EditorNode::EditorNode() { gui_base->add_child(export_template_manager); about = memnew(EditorAbout); - about->get_logo()->set_texture(gui_base->get_icon("Logo", "EditorIcons")); gui_base->add_child(about); warning = memnew(AcceptDialog); @@ -5615,7 +5655,8 @@ EditorNode::EditorNode() { bottom_panel_vb->add_child(bottom_panel_hb); log = memnew(EditorLog); - add_bottom_panel_item(TTR("Output"), log); + ToolButton *output_button = add_bottom_panel_item(TTR("Output"), log); + log->set_tool_button(output_button); old_split_ofs = 0; @@ -5731,6 +5772,8 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(AnimationTreeEditorPlugin(this))); add_editor_plugin(memnew(MeshLibraryEditorPlugin(this))); add_editor_plugin(memnew(StyleBoxEditorPlugin(this))); + add_editor_plugin(memnew(SpriteEditorPlugin(this))); + add_editor_plugin(memnew(Skeleton2DEditorPlugin(this))); add_editor_plugin(memnew(ParticlesEditorPlugin(this))); add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this))); add_editor_plugin(memnew(ItemListEditorPlugin(this))); @@ -5753,7 +5796,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(CollisionShape2DEditorPlugin(this))); add_editor_plugin(memnew(CurveEditorPlugin(this))); add_editor_plugin(memnew(TextureEditorPlugin(this))); - add_editor_plugin(memnew(MeshEditorPlugin(this))); + add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(NavigationMeshEditorPlugin(this))); @@ -5853,17 +5896,7 @@ EditorNode::EditorNode() { EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_fs_changed"); EditorFileSystem::get_singleton()->connect("resources_reimported", this, "_resources_reimported"); - { - List<StringName> tl; - StringName ei = "EditorIcons"; - theme_base->get_theme()->get_icon_list(ei, &tl); - for (List<StringName>::Element *E = tl.front(); E; E = E->next()) { - - if (!ClassDB::class_exists(E->get())) - continue; - icon_type_cache[E->get()] = theme_base->get_theme()->get_icon(E->get(), ei); - } - } + _build_icon_type_cache(); Node::set_human_readable_collision_renaming(true); diff --git a/editor/editor_node.h b/editor/editor_node.h index 5f3deb6698..90bebffca6 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -498,6 +498,7 @@ private: Set<EditorFileDialog *> editor_file_dialogs; Map<String, Ref<Texture> > icon_type_cache; + void _build_icon_type_cache(); bool _initializing_addons; Map<String, EditorPlugin *> plugin_addons; @@ -598,7 +599,6 @@ private: static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS]; void _save_default_environment(); - bool _call_build(); static int build_callback_count; static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS]; @@ -621,6 +621,8 @@ protected: static void _bind_methods(); public: + bool call_build(); + static void add_plugin_init_callback(EditorPluginInitializeCallback p_callback); enum EditorTable { @@ -640,6 +642,8 @@ public: PropertyEditor *get_property_editor() { return property_editor; } VBoxContainer *get_property_editor_vb() { return prop_editor_vb; } + ProjectSettingsEditor *get_project_settings() { return project_settings; } + static void add_editor_plugin(EditorPlugin *p_editor); static void remove_editor_plugin(EditorPlugin *p_editor); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 13f0cc9b73..4f38c0188d 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -301,6 +301,14 @@ void EditorPlugin::remove_custom_type(const String &p_type) { EditorNode::get_editor_data().remove_custom_type(p_type); } +void EditorPlugin::add_autoload_singleton(const String &p_name, const String &p_path) { + EditorNode::get_singleton()->get_project_settings()->get_autoload_settings()->autoload_add(p_name, p_path); +} + +void EditorPlugin::remove_autoload_singleton(const String &p_name) { + EditorNode::get_singleton()->get_project_settings()->get_autoload_settings()->autoload_remove(p_name); +} + ToolButton *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) { return EditorNode::get_singleton()->add_bottom_panel_item(p_title, p_control); @@ -702,6 +710,9 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("add_custom_type", "type", "base", "script", "icon"), &EditorPlugin::add_custom_type); ClassDB::bind_method(D_METHOD("remove_custom_type", "type"), &EditorPlugin::remove_custom_type); + ClassDB::bind_method(D_METHOD("add_autoload_singleton", "name", "path"), &EditorPlugin::add_autoload_singleton); + ClassDB::bind_method(D_METHOD("remove_autoload_singleton", "name"), &EditorPlugin::remove_autoload_singleton); + ClassDB::bind_method(D_METHOD("update_overlays"), &EditorPlugin::update_overlays); ClassDB::bind_method(D_METHOD("make_bottom_panel_item_visible", "item"), &EditorPlugin::make_bottom_panel_item_visible); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index e3e405479c..05cc6e07e3 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -212,6 +212,9 @@ public: void add_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer); void remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer); + void add_autoload_singleton(const String &p_name, const String &p_path); + void remove_autoload_singleton(const String &p_name); + EditorPlugin(); virtual ~EditorPlugin(); }; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 29363e29c1..3a75673560 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -290,6 +290,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { hints["interface/editor/main_font_size"] = PropertyInfo(Variant::INT, "interface/editor/main_font_size", PROPERTY_HINT_RANGE, "10,40,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); _initial_set("interface/editor/code_font_size", 14); hints["interface/editor/code_font_size"] = PropertyInfo(Variant::INT, "interface/editor/code_font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + _initial_set("interface/editor/main_font_hinting", 2); + hints["interface/editor/main_font_hinting"] = PropertyInfo(Variant::INT, "interface/editor/main_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + _initial_set("interface/editor/code_font_hinting", 2); + hints["interface/editor/code_font_hinting"] = PropertyInfo(Variant::INT, "interface/editor/code_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); _initial_set("interface/editor/main_font", ""); hints["interface/editor/main_font"] = PropertyInfo(Variant::STRING, "interface/editor/main_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); _initial_set("interface/editor/code_font", ""); @@ -959,11 +963,8 @@ void EditorSettings::save() { Error err = ResourceSaver::save(singleton->config_file_path, singleton); if (err != OK) { - ERR_PRINT("Can't Save!"); - return; - } - - if (OS::get_singleton()->is_stdout_verbose()) { + ERR_PRINTS("Error saving editor settings to " + singleton->config_file_path); + } else if (OS::get_singleton()->is_stdout_verbose()) { print_line("EditorSettings Save OK!"); } } diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 096a60afa3..b10f785a28 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1139,7 +1139,9 @@ Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) { String custom_theme = EditorSettings::get_singleton()->get("interface/theme/custom_theme"); if (custom_theme != "") { theme = ResourceLoader::load(custom_theme); - } else { + } + + if (!theme.is_valid()) { theme = create_editor_theme(p_theme); } diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index c4ecf3c098..101deb9126 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -70,7 +70,7 @@ void ExportTemplateManager::_update_template_list() { memdelete(d); - String current_version = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + VERSION_STATUS + VERSION_MODULE_CONFIG; + String current_version = VERSION_FULL_CONFIG; Label *current = memnew(Label); current->set_h_size_flags(SIZE_EXPAND_FILL); @@ -217,25 +217,15 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ data_str.parse_utf8((const char *)data.ptr(), data.size()); data_str = data_str.strip_edges(); - if (data_str.get_slice_count("-") != 2 || data_str.get_slice_count(".") != 2) { - EditorNode::get_singleton()->show_warning(TTR("Invalid version.txt format inside templates.")); + // Version number should be of the form major.minor[.patch].status[.module_config] + // so it can in theory have 3 or more slices. + if (data_str.get_slice_count(".") < 3) { + EditorNode::get_singleton()->show_warning(vformat(TTR("Invalid version.txt format inside templates: %s."), data_str)); unzClose(pkg); return; } - String ver = data_str.get_slice("-", 0); - - int major = ver.get_slice(".", 0).to_int(); - int minor = ver.get_slice(".", 1).to_int(); - String rev = data_str.get_slice("-", 1); - - if (!rev.is_valid_identifier()) { - EditorNode::get_singleton()->show_warning(TTR("Invalid version.txt format inside templates. Revision is not a valid identifier.")); - unzClose(pkg); - return; - } - - version = itos(major) + "." + itos(minor) + "-" + rev; + version = data_str; } fc++; @@ -402,19 +392,10 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int if (p_code != 200) { template_list_state->set_text(TTR("Failed:") + " " + itos(p_code)); } else { - String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_templates.tpz"); - FileAccess *f = FileAccess::open(path, FileAccess::WRITE); - if (!f) { - template_list_state->set_text(TTR("Can't write file.")); - } else { - int size = p_data.size(); - PoolVector<uint8_t>::Read r = p_data.read(); - f->store_buffer(r.ptr(), size); - memdelete(f); - template_list_state->set_text(TTR("Download Complete.")); - template_downloader->hide(); - _install_from_file(path, false); - } + String path = download_templates->get_download_file(); + template_list_state->set_text(TTR("Download Complete.")); + template_downloader->hide(); + _install_from_file(path, false); } } break; } @@ -437,6 +418,8 @@ void ExportTemplateManager::_begin_template_download(const String &p_url) { } download_data.clear(); + download_templates->set_download_file(EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_templates.tpz")); + download_templates->set_use_threads(true); Error err = download_templates->request(p_url); if (err != OK) { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index e26f4ba449..9bfa50148f 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -918,7 +918,7 @@ void FileSystemDock::_make_dir_confirm() { if (dir_name.length() == 0) { EditorNode::get_singleton()->show_warning(TTR("No name provided")); return; - } else if (dir_name.find("/") != -1 || dir_name.find("\\") != -1 || dir_name.find(":") != -1) { + } else if (dir_name.find("/") != -1 || dir_name.find("\\") != -1 || dir_name.find(":") != -1 || dir_name.ends_with(".")) { EditorNode::get_singleton()->show_warning(TTR("Provided name contains invalid characters")); return; } @@ -958,7 +958,12 @@ void FileSystemDock::_rename_operation_confirm() { //Present a more user friendly warning for name conflict DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); +#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED) + // Workaround case insensitivity on Windows + if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) { +#else if (da->file_exists(new_path) || da->dir_exists(new_path)) { +#endif EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists.")); memdelete(da); return; diff --git a/editor/icons/SCsub b/editor/icons/SCsub index 9bd036dfa9..7f94073e01 100644 --- a/editor/icons/SCsub +++ b/editor/icons/SCsub @@ -34,7 +34,7 @@ def make_editor_icons_action(target, source, env): s.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") s.write("#ifndef _EDITOR_ICONS_H\n") s.write("#define _EDITOR_ICONS_H\n") - s.write("static const int editor_icons_count = %s;\n" % len(svg_icons)) + s.write("static const int editor_icons_count = {};\n".format(len(svg_icons))) s.write("static const char *editor_icons_sources[] = {\n") s.write(icons_string.getvalue()) s.write('};\n\n') @@ -57,7 +57,7 @@ def make_editor_icons_action(target, source, env): if icon_name.endswith("BigThumb"): # don't know a better way to handle this thumb_big_indices.append(str(index)) - s.write('\t"%s"' % icon_name) + s.write('\t"{0}"'.format(icon_name)) if fname != svg_icons[-1]: s.write(",") @@ -69,23 +69,22 @@ def make_editor_icons_action(target, source, env): if thumb_medium_indices: s.write("\n\n") - s.write("static const int editor_md_thumbs_count = %s;\n" % len(thumb_medium_indices)) + s.write("static const int editor_md_thumbs_count = {};\n".format(len(thumb_medium_indices))) s.write("static const int editor_md_thumbs_indices[] = {") s.write(", ".join(thumb_medium_indices)) s.write("};\n") if thumb_big_indices: s.write("\n\n") - s.write("static const int editor_bg_thumbs_count = %s;\n" % len(thumb_big_indices)) + s.write("static const int editor_bg_thumbs_count = {};\n".format(len(thumb_big_indices))) s.write("static const int editor_bg_thumbs_indices[] = {") s.write(", ".join(thumb_big_indices)) s.write("};\n") s.write("#endif\n") + with open(dst, "w") as f: + f.write(s.getvalue()) - f = open(dst, "w") - f.write(s.getvalue()) - f.close() s.close() icons_string.close() diff --git a/editor/icons/icon_action_copy.svg b/editor/icons/icon_action_copy.svg new file mode 100644 index 0000000000..d5da233bc9 --- /dev/null +++ b/editor/icons/icon_action_copy.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m2 1c-0.554 0-1 0.446-1 1v9c0 0.554 0.446 1 1 1h1v-9h9v-1c0-0.554-0.446-1-1-1h-9zm3 3c-0.554 0-1 0.446-1 1v9c0 0.554 0.446 1 1 1h9c0.554 0 1-0.446 1-1v-9c0-0.554-0.446-1-1-1h-9zm1 2h7v7h-7v-7z" fill="#e0e0e0"/> +</svg> diff --git a/editor/icons/icon_action_cut.svg b/editor/icons/icon_action_cut.svg new file mode 100644 index 0000000000..776ca3a4c4 --- /dev/null +++ b/editor/icons/icon_action_cut.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m3.6348 0.50977c-2.9641 2.866 0.53553 8.9289 2.7676 8.7949l0.44141 0.76562-0.56445 0.97852a3 3 0 0 0 -2.2793 -1.0488 3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 2.5938 -1.502l0.0039062 0.001953 1.4023-2.4277 1.4023 2.4277 0.0019531-0.001953a3 3 0 0 0 2.5957 1.502 3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3 3 3 0 0 0 -2.2773 1.0527l-0.56641-0.98242 0.44141-0.76562c2.2321 0.13397 5.7317-5.9289 2.7676-8.7949l-4.3652 7.5605-4.3652-7.5605zm0.36523 11.49a1 1 0 0 1 1 1 1 1 0 0 1 -0.12305 0.47852l-0.011719 0.021484a1 1 0 0 1 -0.86523 0.5 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm8 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#e0e0e0"/> +</svg> diff --git a/editor/icons/icon_action_paste.svg b/editor/icons/icon_action_paste.svg new file mode 100644 index 0000000000..b71e5531df --- /dev/null +++ b/editor/icons/icon_action_paste.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m8 1c-1.3045 0-2.4033 0.8372-2.8164 2h-3.1836c-0.554 0-1 0.446-1 1v10c0 0.554 0.446 1 1 1h12c0.554 0 1-0.446 1-1v-10c0-0.554-0.446-1-1-1h-3.1836c-0.41312-1.1628-1.5119-2-2.8164-2zm0 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-5 2h2v2h6v-2h2v8h-10v-8z" fill="#e0e0e0"/> +</svg> diff --git a/editor/icons/icon_add_split.svg b/editor/icons/icon_add_split.svg new file mode 100644 index 0000000000..6cfd419e7f --- /dev/null +++ b/editor/icons/icon_add_split.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="icon_add_split.svg" + inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="3066" + inkscape:window-height="1689" + id="namedview6" + showgrid="false" + inkscape:zoom="41.7193" + inkscape:cx="7.7924561" + inkscape:cy="6.0148972" + inkscape:window-x="134" + inkscape:window-y="55" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <rect + style="fill:#800000" + id="rect12" + width="1.8456686" + height="2.0853658" + x="0.62321275" + y="6.9394455" /> + <rect + style="fill:#800000" + id="rect14" + width="1.6299411" + height="1.9894869" + x="12.488225" + y="7.1791425" /> + <rect + style="fill:#e9afaf" + id="rect16" + width="10.067283" + height="0.69512194" + x="2.492851" + y="7.7304463" /> +</svg> diff --git a/editor/icons/icon_array_mesh.svg b/editor/icons/icon_array_mesh.svg index 867fc95b0c..7c086e1a44 100644 --- a/editor/icons/icon_array_mesh.svg +++ b/editor/icons/icon_array_mesh.svg @@ -1,3 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm10 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-2 7v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2zm-8 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> +<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm10 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-2 7v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2zm-8 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_asset_lib.svg b/editor/icons/icon_asset_lib.svg index fcd670817d..1348c491fc 100644 --- a/editor/icons/icon_asset_lib.svg +++ b/editor/icons/icon_asset_lib.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m8 1c-1.6569 0-3 1.3431-3 3v2h-4v7c0 1.108 0.89199 2 2 2h10c1.108 0 2-0.89199 2-2v-7h-4v-2c0-1.6569-1.3431-3-3-3zm0 2c0.55228 0 1 0.44772 1 1v2h-2v-2c0-0.55228 0.44772-1 1-1z" fill="#e0e0e0"/> -</g> +<path d="m8 1c-1.6569 0-3 1.3431-3 3v2h-4v7c0 1.108 0.89199 2 2 2h10c1.108 0 2-0.89199 2-2v-7h-4v-2c0-1.6569-1.3431-3-3-3zm0 2c0.55228 0 1 0.44772 1 1v2h-2v-2c0-0.55228 0.44772-1 1-1z" fill="#e0e0e0"/> </svg> diff --git a/editor/icons/icon_capsule_mesh.svg b/editor/icons/icon_capsule_mesh.svg index bc736200a4..c375e6adfb 100644 --- a/editor/icons/icon_capsule_mesh.svg +++ b/editor/icons/icon_capsule_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path d="m8 1037.4c-2.7527 0-5 2.2419-5 4.9903v4.0175c0 2.7484 2.2473 4.9922 5 4.9922 2.7527 0 5-2.2438 5-4.9922v-4.0175c0-2.7484-2.2473-4.9903-5-4.9903zm-1.0059 2.1264v4.8576c-0.66556-0.1047-1.2973-0.372-1.9941-0.6618v-1.3222c0-1.3474 0.79838-2.4648 1.9941-2.8736zm2.0118 0c1.1957 0.4088 1.9941 1.5262 1.9941 2.8736v1.3451c-0.68406 0.3054-1.3142 0.5732-1.9941 0.6663zm-4.0059 6.334c0.67836 0.2231 1.3126 0.447 1.9941 0.5264v2.8848c-1.1957-0.4092-1.9941-1.5242-1.9941-2.8716zm6 0.03v0.5094c0 1.3474-0.79838 2.4619-1.9941 2.8711v-2.8711c0.68606-0.068 1.3207-0.2828 1.9941-0.5094z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> -</g> +<path d="m8 1c-2.7527 0-5 2.2419-5 4.9903v4.0175c0 2.7484 2.2473 4.9922 5 4.9922 2.7527 0 5-2.2438 5-4.9922v-4.0175c0-2.7484-2.2473-4.9903-5-4.9903zm-1.0059 2.1264v4.8576c-0.66556-0.1047-1.2973-0.372-1.9941-0.6618v-1.3222c0-1.3474 0.79838-2.4648 1.9941-2.8736zm2.0118 0c1.1957 0.4088 1.9941 1.5262 1.9941 2.8736v1.3451c-0.68406 0.3054-1.3142 0.5732-1.9941 0.6663zm-4.0059 6.334c0.67836 0.2231 1.3126 0.447 1.9941 0.5264v2.8848c-1.1957-0.4092-1.9941-1.5242-1.9941-2.8716zm6 0.03v0.5094c0 1.3474-0.79838 2.4619-1.9941 2.8711v-2.8711c0.68606-0.068 1.3207-0.2828 1.9941-0.5094z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_cone_twist_joint.svg b/editor/icons/icon_cone_twist_joint.svg index c9d92d6537..8d869fa1d5 100644 --- a/editor/icons/icon_cone_twist_joint.svg +++ b/editor/icons/icon_cone_twist_joint.svg @@ -1,7 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)" fill="none" stroke="#fc9c9c" stroke-linecap="round" stroke-width="2"> -<path transform="translate(0 1036.4)" d="m8 2l-6 9a6 3 0 0 0 3 2.5977 6 3 0 0 0 6 0 6 3 0 0 0 3 -2.5977l-6-9z" stroke-linejoin="round"/> -<ellipse cx="8" cy="1047.4" rx="6" ry="3" stroke-linejoin="round"/> -<path d="m8 1039.4v8"/> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m7.9824 1a1.0001 1.0001 0 0 0 -0.81445 0.44531l-4.7012 7.0527c-0.80117 0.58197-1.3801 1.3563-1.4492 2.3145a1.0001 1.0001 0 0 0 -0.017578 0.1875c0 0.21449 0.033976 0.41628 0.082031 0.61328 0.0071983 0.028314 0.015306 0.055972 0.023438 0.083985 0.053631 0.19149 0.1274 0.37452 0.2207 0.54883 0.19678 0.36764 0.47105 0.69651 0.80273 0.98633 0.007988 0.007025 0.013442 0.016473 0.021484 0.023437 0.016953 0.014679 0.03747 0.026532 0.054688 0.041016 0.10299 0.086112 0.21259 0.16531 0.32422 0.24414 0.23883 0.16992 0.49083 0.33075 0.76953 0.4707 0.0025295 0.00127 0.0052799 0.002638 0.0078125 0.003906 0.001313 6.58e-4 0.0025928 0.001296 0.0039063 0.001953 0.0085785 0.00429 0.018732 0.007456 0.027344 0.011719 0.26499 0.13103 0.55174 0.24596 0.84961 0.35156 0.10487 0.037634 0.21202 0.071147 0.32031 0.10547 0.072945 0.022902 0.1402 0.050715 0.21484 0.072266 0.16777 0.04843 0.34161 0.086385 0.51367 0.12695 0.093562 0.021905 0.18185 0.048745 0.27734 0.068359 0.010733 0.002205 0.022447 0.003684 0.033203 0.00586 0.34623 0.071177 0.69974 0.12196 1.0566 0.16211 0.057889 0.006228 0.11544 0.01213 0.17383 0.017578 0.81052 0.079498 1.6348 0.079498 2.4453 0 0.058387-0.005448 0.11594-0.01135 0.17383-0.017578 0.3569-0.040146 0.71041-0.090932 1.0566-0.16211 0.010948-0.002251 0.022269-0.003578 0.033203-0.00586 0.095491-0.019614 0.18378-0.046454 0.27734-0.068359 0.17206-0.040568 0.3459-0.078523 0.51367-0.12695 0.074642-0.021551 0.1419-0.049364 0.21484-0.072266 0.10829-0.034322 0.21544-0.067835 0.32031-0.10547 0.29787-0.1056 0.58462-0.22053 0.84961-0.35156 0.009951-0.00492 0.021348-0.008715 0.03125-0.013672 0.002626-0.001315 0.005189-0.002588 0.007813-0.003906 0.2787-0.13995 0.5307-0.30078 0.76953-0.4707 0.11163-0.07883 0.22123-0.15803 0.32422-0.24414 0.017218-0.014484 0.037734-0.026337 0.054687-0.041016 0.008042-0.006964 0.013497-0.016412 0.021485-0.023437 0.33169-0.28982 0.60596-0.61869 0.80273-0.98633 0.093299-0.17431 0.16707-0.35733 0.2207-0.54883 0.008132-0.028013 0.016239-0.055671 0.023438-0.083985 0.048055-0.197 0.082031-0.39879 0.082031-0.61328a1.0001 1.0001 0 0 0 -0.017578 -0.18164 1.0001 1.0001 0 0 0 -0.001953 -0.017578c-0.073081-0.95265-0.64941-1.7232-1.4473-2.3027l-4.7012-7.0527a1.0001 1.0001 0 0 0 -0.84961 -0.44531zm-0.98242 4.3027v1.7461c-0.43911 0.033461-0.86366 0.087835-1.2734 0.16406l1.2734-1.9102zm2 0l1.2734 1.9102c-0.40978-0.076228-0.83432-0.1306-1.2734-0.16406v-1.7461zm-2 3.748v1.9492a1.0001 1.0001 0 1 0 2 0v-1.9492c1.1126 0.10487 2.0951 0.37277 2.7949 0.72266 0.12146 0.060728 0.20622 0.12218 0.30664 0.18359l0.80078 1.2012c-0.032965 0.14677-0.089654 0.30658-0.30469 0.51758-0.051464 0.049149-0.10034 0.098137-0.16406 0.14844-0.045193 0.035312-0.091373 0.070148-0.14258 0.10547-0.11245 0.07827-0.24511 0.15838-0.39062 0.23633-0.075428 0.040204-0.1553 0.078371-0.23828 0.11719-0.16195 0.075482-0.33452 0.14662-0.52148 0.21289-0.070588 0.025324-0.14454 0.048409-0.21875 0.072265-0.23425 0.074473-0.48077 0.14392-0.74414 0.20117-0.021343 0.004579-0.041038 0.011189-0.0625 0.015625-0.2559 0.05368-0.53101 0.090517-0.80859 0.125-0.856 0.10229-1.7573 0.10229-2.6133 0-0.27759-0.034483-0.5527-0.07132-0.80859-0.125-0.021462-0.004436-0.041156-0.011046-0.0625-0.015625-0.26337-0.057254-0.50989-0.1267-0.74414-0.20117-0.074211-0.023856-0.14816-0.046941-0.21875-0.072265-0.18697-0.066266-0.35954-0.13741-0.52148-0.21289-0.082979-0.038816-0.16285-0.076983-0.23828-0.11719-0.14552-0.077951-0.27818-0.15806-0.39062-0.23633-0.051205-0.035321-0.097386-0.070157-0.14258-0.10547-0.06372-0.050301-0.1126-0.099289-0.16406-0.14844-0.21503-0.21099-0.27173-0.37081-0.30469-0.51758l0.80078-1.2012c0.10043-0.061415 0.18518-0.12287 0.30664-0.18359 0.69978-0.34989 1.6823-0.61778 2.7949-0.72266z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fc9c9c" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> </g> </svg> diff --git a/editor/icons/icon_cube_mesh.svg b/editor/icons/icon_cube_mesh.svg index 45275216ab..d1897dd710 100644 --- a/editor/icons/icon_cube_mesh.svg +++ b/editor/icons/icon_cube_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 14.999999 14.999999" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1037.4)"> -<path d="m7.5 1038.2-6.5625 3.2804v6.772l6.5625 3.2804 6.5625-3.2804v-6.772zm0 1.9831 3.6926 1.8463-3.6926 1.8463-3.6926-1.8463zm-4.7889 3.2804 3.9022 1.9502v3.6944l-3.9022-1.952zm9.5779 0v3.6926l-3.9022 1.952v-3.6944z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> -</g> +<path transform="scale(.9375)" d="m8 0.88867-7 3.5v7.2227l7 3.5 7-3.5v-7.2227zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002zm10 0v3.9395l-4 2.002v-3.9414z" fill="#ffd684" stroke-width="1.0667"/> </svg> diff --git a/editor/icons/icon_cylinder_mesh.svg b/editor/icons/icon_cylinder_mesh.svg index 92a93ec220..21b5fc144b 100644 --- a/editor/icons/icon_cylinder_mesh.svg +++ b/editor/icons/icon_cylinder_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 14.999999 14.999999" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1037.4)"> -<path transform="matrix(.9375 0 0 .9375 0 1037.4)" d="m8 1c-1.7469 0-3.328 0.22648-4.5586 0.63672-0.61528 0.20512-1.1471 0.45187-1.5898 0.80078s-0.85156 0.88101-0.85156 1.5625v8c0 0.68149 0.40884 1.2155 0.85156 1.5645s0.97457 0.59577 1.5898 0.80078c1.2306 0.41024 2.8117 0.63477 4.5586 0.63477s3.328-0.22453 4.5586-0.63477c0.61527-0.20501 1.1471-0.45187 1.5898-0.80078 0.44272-0.34891 0.85156-0.88296 0.85156-1.5645v-8c0-0.68149-0.40884-1.2136-0.85156-1.5625-0.44272-0.34891-0.97457-0.59566-1.5898-0.80078-1.2306-0.41024-2.8117-0.63672-4.5586-0.63672zm0 2c1.5668 0 2.9867 0.22145 3.9277 0.53516 0.46368 0.15456 0.80138 0.33741 0.96875 0.4668-0.16752 0.12928-0.50546 0.3105-0.96875 0.46484-0.94102 0.31371-2.361 0.5332-3.9277 0.5332s-2.9867-0.2195-3.9277-0.5332c-0.46329-0.15435-0.80123-0.33556-0.96875-0.46484 0.16737-0.12939 0.50507-0.31224 0.96875-0.4668 0.94102-0.31371 2.361-0.53516 3.9277-0.53516zm-5 3.1875c0.1468 0.059071 0.2835 0.12512 0.44141 0.17773 1.2306 0.41024 2.8117 0.63477 4.5586 0.63477s3.328-0.22453 4.5586-0.63477c0.15791-0.052617 0.29461-0.11866 0.44141-0.17773v5.8125c-0.16752 0.12928-0.60898 0.31245-1.0723 0.4668-0.94102 0.31371-2.361 0.5332-3.9277 0.5332s-2.9867-0.2195-3.9277-0.5332c-0.46329-0.15435-0.90474-0.33752-1.0723-0.4668z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> -</g> +<path d="m7.5 0.9375c-1.6377 0-3.12 0.2123-4.2737 0.5969-0.57682 0.1923-1.0754 0.4237-1.4905 0.7508-0.41505 0.3271-0.79834 0.8259-0.79834 1.4648v7.5c0 0.6389 0.38329 1.1396 0.79834 1.4667 0.41505 0.3271 0.91366 0.5585 1.4905 0.7507 1.1536 0.3846 2.6359 0.5951 4.2737 0.5951s3.12-0.2105 4.2737-0.5951c0.57682-0.1922 1.0754-0.4236 1.4905-0.7507 0.41505-0.3271 0.79834-0.8278 0.79834-1.4667v-7.5c0-0.6389-0.38329-1.1377-0.79834-1.4648-0.41505-0.3271-0.91366-0.5585-1.4905-0.7508-1.1536-0.3846-2.6359-0.5969-4.2737-0.5969zm0 1.875c1.4689 0 2.8 0.2076 3.6823 0.5017 0.4347 0.1449 0.7513 0.3163 0.9082 0.4376-0.15705 0.1212-0.47387 0.2911-0.9082 0.4358-0.88221 0.2941-2.2134 0.4999-3.6823 0.4999s-2.8-0.2058-3.6823-0.4999c-0.43433-0.1447-0.75115-0.3146-0.9082-0.4358 0.15691-0.1213 0.47351-0.2927 0.9082-0.4376 0.88221-0.2941 2.2134-0.5017 3.6823-0.5017zm-4.6875 2.9883c0.13762 0.055 0.26578 0.1173 0.41382 0.1666 1.1536 0.3846 2.6359 0.5951 4.2737 0.5951s3.12-0.2105 4.2737-0.5951c0.14804-0.049 0.2762-0.1112 0.41382-0.1666v5.4492c-0.15705 0.1212-0.57092 0.2929-1.0052 0.4376-0.88221 0.2941-2.2134 0.4999-3.6823 0.4999s-2.8-0.2058-3.6823-0.4999c-0.43433-0.1447-0.8482-0.3164-1.0052-0.4376z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_delete_split.svg b/editor/icons/icon_delete_split.svg new file mode 100644 index 0000000000..c24f7449d6 --- /dev/null +++ b/editor/icons/icon_delete_split.svg @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="icon_delete_split.svg" + inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="3066" + inkscape:window-height="1689" + id="namedview6" + showgrid="false" + inkscape:zoom="41.7193" + inkscape:cx="7.7924561" + inkscape:cy="6.0148972" + inkscape:window-x="134" + inkscape:window-y="55" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <rect + style="fill:#800000" + id="rect12" + width="1.8456686" + height="2.0853658" + x="0.62321275" + y="6.9394455" /> + <rect + style="fill:#800000" + id="rect14" + width="1.6299411" + height="1.9894869" + x="12.488225" + y="7.1791425" /> + <rect + style="fill:#e9afaf" + id="rect37" + width="3.1640031" + height="0.40748528" + x="2.5407906" + y="7.9701433" /> + <rect + style="fill:#e9afaf" + id="rect39" + width="3.5235491" + height="0.52733386" + x="9.0126152" + y="8.0420523" /> + <rect + style="fill:#e9afaf" + id="rect41" + width="3.6433976" + height="0.4554247" + x="1.5110972" + y="-9.732645" + transform="rotate(123.99908)" /> + <rect + style="fill:#e9afaf" + id="rect41-3" + width="3.6433976" + height="0.4554247" + x="0.072069742" + y="-12.144793" + transform="rotate(123.99908)" /> +</svg> diff --git a/editor/icons/icon_enum.svg b/editor/icons/icon_enum.svg new file mode 100644 index 0000000000..e9c3fbbd2e --- /dev/null +++ b/editor/icons/icon_enum.svg @@ -0,0 +1,3 @@ +<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg"> +<path d="m3 2c-0.5304 8.01e-5 -1.0391 0.21085-1.4141 0.58594-0.37509 0.37501-0.58586 0.88366-0.58594 1.4141v1c-0.2652 4.01e-5 -0.51953 0.10542-0.70703 0.29297-0.18755 0.18751-0.29293 0.44183-0.29297 0.70703 4.0076e-5 0.2652 0.10542 0.51953 0.29297 0.70703 0.18751 0.18755 0.44183 0.29293 0.70703 0.29297v1c8.01e-5 0.5304 0.21085 1.0391 0.58594 1.4141 0.37501 0.37509 0.88366 0.58586 1.4141 0.58594h1v-2h-1v-4h1v-2zm3 0v8h4v-2h-2v-1h2v-2h-2v-1h2v-2zm6 0v2h1v4h-1v2h1c0.5304-8.03e-5 1.0391-0.21085 1.4141-0.58594 0.37509-0.37501 0.58586-0.88366 0.58594-1.4141v-1c0.2652-4.01e-5 0.51953-0.10542 0.70703-0.29297 0.18755-0.18751 0.29293-0.44183 0.29297-0.70703-4e-5 -0.2652-0.10542-0.51953-0.29297-0.70703-0.1875-0.18755-0.44183-0.29293-0.70703-0.29297v-1c-8e-5 -0.5304-0.21085-1.0391-0.58594-1.4141-0.37501-0.37509-0.88366-0.58586-1.4141-0.58594z" fill="#e0e0e0"/> +</svg> diff --git a/editor/icons/icon_help_search.svg b/editor/icons/icon_help_search.svg index c0768ea5ed..8e4f97d781 100644 --- a/editor/icons/icon_help_search.svg +++ b/editor/icons/icon_help_search.svg @@ -1,7 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)" stroke-width="2"> -<path transform="translate(0 1036.4)" d="m0 10v6h2c1.6569 0 3-1.3431 3-3s-1.3431-3-3-3zm5 3c0 1.6569 1.3431 3 3 3s3-1.3431 3-3-1.3431-3-3-3-3 1.3431-3 3zm6 0c0 1.6569 1.3431 3 3 3h1v-2h-1c-0.55228-1e-5 -0.99999-0.44772-1-1 1e-5 -0.55228 0.44772-0.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3zm-9-1c0.55228 0 1 0.44772 1 1s-0.44772 1-1 1zm6 0c0.55228 1e-5 0.99999 0.44772 1 1-9.6e-6 0.55228-0.44772 0.99999-1 1-0.55228-1e-5 -0.99999-0.44772-1-1 9.6e-6 -0.55228 0.44772-0.99999 1-1z" fill="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".32549"/> -<path d="m9 1036.4a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 4 -4 4 4 0 0 0 -4 -4zm0 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2z" fill="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".32549"/> -<path d="m7 1042.4-3 3" fill="none" stroke="#e0e0e0"/> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m9 0a4 4 0 0 0 -4 4 4 4 0 0 0 0.55859 2.0273l-2.2656 2.2656 1.4141 1.4141 2.2656-2.2656a4 4 0 0 0 2.0273 0.55859 4 4 0 0 0 4 -4 4 4 0 0 0 -4 -4zm0 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm-9 8v6h2c1.6569 0 3-1.3431 3-3s-1.3431-3-3-3h-2zm5 3c0 1.6569 1.3431 3 3 3s3-1.3431 3-3-1.3431-3-3-3-3 1.3431-3 3zm6 0c0 1.6569 1.3431 3 3 3h1v-2h-1c-0.55228-1e-5 -0.99999-0.44772-1-1 1e-5 -0.55228 0.44772-0.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3zm-9-1c0.55228 0 1 0.44772 1 1s-0.44772 1-1 1v-2zm6 0c0.55228 1e-5 0.99999 0.44772 1 1-9.6e-6 0.55228-0.44772 0.99999-1 1-0.55228-1e-5 -0.99999-0.44772-1-1 9.6e-6 -0.55228 0.44772-0.99999 1-1z" fill="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".32549" stroke-width="2"/> </g> </svg> diff --git a/editor/icons/icon_key_selected.svg b/editor/icons/icon_key_selected.svg deleted file mode 100644 index c73d31981d..0000000000 --- a/editor/icons/icon_key_selected.svg +++ /dev/null @@ -1,5 +0,0 @@ -<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1044.4)"> -<rect transform="rotate(-45)" x="-741.53" y="741.08" width="6.1027" height="6.1027" ry=".76286" fill="#84c2ff"/> -</g> -</svg> diff --git a/editor/icons/icon_key_hover.svg b/editor/icons/icon_key_valid.svg index 4a3fab4754..4a3fab4754 100644 --- a/editor/icons/icon_key_hover.svg +++ b/editor/icons/icon_key_valid.svg diff --git a/editor/icons/icon_mesh.svg b/editor/icons/icon_mesh.svg index d90dc14b5b..f96efb0430 100644 --- a/editor/icons/icon_mesh.svg +++ b/editor/icons/icon_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2 -2 2 2 0 0 0 -1.0312 -1.75h0.03125v-6.5215a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm2.4141 3h5.8574a2 2 0 0 0 0.72852 0.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141l6.5859 6.5859h-5.8574a2 2 0 0 0 -0.72852 -0.73047v-5.8555z" fill="#ffd684"/> -</g> +<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2 -2 2 2 0 0 0 -1.0312 -1.75h0.03125v-6.5215a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm2.4141 3h5.8574a2 2 0 0 0 0.72852 0.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141l6.5859 6.5859h-5.8574a2 2 0 0 0 -0.72852 -0.73047v-5.8555z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_mesh_instance.svg b/editor/icons/icon_mesh_instance.svg index 3342a3e06d..2860cf6889 100644 --- a/editor/icons/icon_mesh_instance.svg +++ b/editor/icons/icon_mesh_instance.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2 -2 2 2 0 0 0 -1.0312 -1.75h0.03125v-6.5215a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm2.4141 3h5.8574a2 2 0 0 0 0.72852 0.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141l6.5859 6.5859h-5.8574a2 2 0 0 0 -0.72852 -0.73047v-5.8555z" fill="#fc9c9c" fill-opacity=".99608"/> -</g> +<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2 -2 2 2 0 0 0 -1.0312 -1.75h0.03125v-6.5215a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm2.4141 3h5.8574a2 2 0 0 0 0.72852 0.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141l6.5859 6.5859h-5.8574a2 2 0 0 0 -0.72852 -0.73047v-5.8555z" fill="#fc9c9c" fill-opacity=".99608"/> </svg> diff --git a/editor/icons/icon_mesh_instance_2d.svg b/editor/icons/icon_mesh_instance_2d.svg new file mode 100644 index 0000000000..051547b524 --- /dev/null +++ b/editor/icons/icon_mesh_instance_2d.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2 -2 2 2 0 0 0 -1.0312 -1.75h0.03125v-6.5215a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm2.4141 3h5.8574a2 2 0 0 0 0.72852 0.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141l6.5859 6.5859h-5.8574a2 2 0 0 0 -0.72852 -0.73047v-5.8555z" fill="#a5b7f3"/> +</svg> diff --git a/editor/icons/icon_mesh_library.svg b/editor/icons/icon_mesh_library.svg index 3bef2df33c..3683650e2e 100644 --- a/editor/icons/icon_mesh_library.svg +++ b/editor/icons/icon_mesh_library.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h2.2695v-2h-2.2715a2 2 0 0 0 -0.72852 -0.73047v-5.8555l3 3v-0.41406a2.0002 2.0002 0 0 1 0.80859 -1.6055l-2.3945-2.3945h5.8574a2 2 0 0 0 0.72852 0.73047v1.2695a2.0002 2.0002 0 0 1 0.99805 0.27148 2.0002 2.0002 0 0 1 1.002 -0.27148v-1.2715a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm6 7v1 5 1h5c0.55228 0 1-0.4477 1-1v-5c0-0.5523-0.44772-1-1-1v4l-1-1-1 1v-4h-3z" fill="#ffd684"/> -</g> +<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h2.2695v-2h-2.2715a2 2 0 0 0 -0.72852 -0.73047v-5.8555l3 3v-0.41406a2.0002 2.0002 0 0 1 0.80859 -1.6055l-2.3945-2.3945h5.8574a2 2 0 0 0 0.72852 0.73047v1.2695a2.0002 2.0002 0 0 1 0.99805 0.27148 2.0002 2.0002 0 0 1 1.002 -0.27148v-1.2715a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm6 7v1 5 1h5c0.55228 0 1-0.4477 1-1v-5c0-0.5523-0.44772-1-1-1v4l-1-1-1 1v-4h-3z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_multi_mesh.svg b/editor/icons/icon_multi_mesh.svg index 2582ba9e51..522561bb28 100644 --- a/editor/icons/icon_multi_mesh.svg +++ b/editor/icons/icon_multi_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2 5.649e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35663-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.65e-4 1.3735-0.38169 1.7305-1h1.2695v-2h-1.2715c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c0.17532 0.30158 0.42647 0.55205 0.72852 0.72656v1.2734h2v-1.2695c0.61831-0.35698 0.99944-1.0165 1-1.7305 0-1.1046-0.89543-2-2-2-0.71397 5.648e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35663-0.61771-1.0152-0.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#ffd684"/> -</g> +<path d="m3 1c-1.1046 0-2 0.89543-2 2 5.649e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35663-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.65e-4 1.3735-0.38169 1.7305-1h1.2695v-2h-1.2715c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c0.17532 0.30158 0.42647 0.55205 0.72852 0.72656v1.2734h2v-1.2695c0.61831-0.35698 0.99944-1.0165 1-1.7305 0-1.1046-0.89543-2-2-2-0.71397 5.648e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35663-0.61771-1.0152-0.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_multi_mesh_instance.svg b/editor/icons/icon_multi_mesh_instance.svg index 0140f1137b..f873ac2bf3 100644 --- a/editor/icons/icon_multi_mesh_instance.svg +++ b/editor/icons/icon_multi_mesh_instance.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2 5.649e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35663-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.65e-4 1.3735-0.38169 1.7305-1h1.2695v-2h-1.2715c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c0.17532 0.30158 0.42647 0.55205 0.72852 0.72656v1.2734h2v-1.2695c0.61831-0.35698 0.99944-1.0165 1-1.7305 0-1.1046-0.89543-2-2-2-0.71397 5.648e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35663-0.61771-1.0152-0.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fc9c9c" fill-opacity=".99608"/> -</g> +<path d="m3 1c-1.1046 0-2 0.89543-2 2 5.649e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35663-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.65e-4 1.3735-0.38169 1.7305-1h1.2695v-2h-1.2715c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-5.8555l3.5859 3.5859h1.4141v-1.4141l-3.5859-3.5859h5.8574c0.17532 0.30158 0.42647 0.55205 0.72852 0.72656v1.2734h2v-1.2695c0.61831-0.35698 0.99944-1.0165 1-1.7305 0-1.1046-0.89543-2-2-2-0.71397 5.648e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35663-0.61771-1.0152-0.99874-1.7285-1zm8 7v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fc9c9c" fill-opacity=".99608"/> </svg> diff --git a/editor/icons/icon_navigation_mesh.svg b/editor/icons/icon_navigation_mesh.svg index cc04e06b51..831d1a0769 100644 --- a/editor/icons/icon_navigation_mesh.svg +++ b/editor/icons/icon_navigation_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h2.5078l0.75-2h-3.2598a2 2 0 0 0 -0.72852 -0.73047v-5.8555l4.6973 4.6973 0.77148-2.0566-4.0547-4.0547h5.8574a2 2 0 0 0 0.72852 0.73047v0.27148a2.0002 2.0002 0 0 1 0.023438 0 2.0002 2.0002 0 0 1 1.8496 1.2969l0.12695 0.33789v-1.9082a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm9 6l-3 8 3-2 3 2-3-8z" fill="#ffd684"/> -</g> +<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h2.5078l0.75-2h-3.2598a2 2 0 0 0 -0.72852 -0.73047v-5.8555l4.6973 4.6973 0.77148-2.0566-4.0547-4.0547h5.8574a2 2 0 0 0 0.72852 0.73047v0.27148a2.0002 2.0002 0 0 1 0.023438 0 2.0002 2.0002 0 0 1 1.8496 1.2969l0.12695 0.33789v-1.9082a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm9 6l-3 8 3-2 3 2-3-8z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_navigation_mesh_instance.svg b/editor/icons/icon_navigation_mesh_instance.svg index 85c6292290..e6636807af 100644 --- a/editor/icons/icon_navigation_mesh_instance.svg +++ b/editor/icons/icon_navigation_mesh_instance.svg @@ -1,7 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)" fill="#fc9c9c" fill-opacity=".99608"> -<path transform="translate(0 1036.4)" d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h2.5078l0.75-2h-3.2598a2 2 0 0 0 -0.72852 -0.73047v-5.8555l4.6973 4.6973 0.77148-2.0566-4.0547-4.0547h5.8574a2 2 0 0 0 0.72852 0.73047v0.27148a2.0002 2.0002 0 0 1 0.023438 0 2.0002 2.0002 0 0 1 1.8496 1.2969l0.12695 0.33789v-1.9082a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm9 6l-3 8 3-2 3 2-3-8z"/> -<rect x="12" y="1040.4" width="2" height="1"/> -<rect x="12" y="1040.4" width="2" height="1"/> -</g> +<path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h2.5078l0.75-2h-3.2598a2 2 0 0 0 -0.72852 -0.73047v-5.8555l4.6973 4.6973 0.77148-2.0566-4.0547-4.0547h5.8574a2 2 0 0 0 0.72852 0.73047v0.27148a2.0002 2.0002 0 0 1 0.023438 0 2.0002 2.0002 0 0 1 1.8496 1.2969l0.12695 0.33789v-1.9082a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm9 6l-3 8 3-2 3 2-3-8z" fill="#fc9c9c" fill-opacity=".99608"/> </svg> diff --git a/editor/icons/icon_plane_mesh.svg b/editor/icons/icon_plane_mesh.svg index 7a5c8f4354..dae7b02da5 100644 --- a/editor/icons/icon_plane_mesh.svg +++ b/editor/icons/icon_plane_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path d="m2 1048.4h12l-3-8h-6z" fill="none" stroke="#ffd684" stroke-linejoin="round" stroke-width="2"/> -</g> +<path d="m2 12h12l-3-8h-6z" fill="none" stroke="#ffd684" stroke-linejoin="round" stroke-width="2"/> </svg> diff --git a/editor/icons/icon_prism_mesh.svg b/editor/icons/icon_prism_mesh.svg index 68dfa117f7..8f8feb2eb6 100644 --- a/editor/icons/icon_prism_mesh.svg +++ b/editor/icons/icon_prism_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m7.9824 1.002a1.0001 1.0001 0 0 0 -0.81445 0.44336l-5.9727 8.9609-0.027344 0.039062a1 1 0 0 0 -0.0625 0.10742 1 1 0 0 0 0.44727 1.3418l6 3a1.0001 1.0001 0 0 0 0.89453 0l6-3a1 1 0 0 0 0.44726 -1.3418 1 1 0 0 0 -0.0625 -0.10742l-6-9a1.0001 1.0001 0 0 0 -0.84961 -0.44336zm-0.98242 4.3008v7.0801l-3.5391-1.7715 3.5391-5.3086zm2 0l3.5391 5.3086-3.5391 1.7715v-7.0801z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> -</g> +<path d="m7.9824 1.002a1.0001 1.0001 0 0 0 -0.81445 0.44336l-5.9727 8.9609-0.027344 0.03906a1 1 0 0 0 -0.0625 0.10742 1 1 0 0 0 0.44727 1.3418l6 3a1.0001 1.0001 0 0 0 0.89453 0l6-3a1 1 0 0 0 0.44726 -1.3418 1 1 0 0 0 -0.0625 -0.10742l-6-9a1.0001 1.0001 0 0 0 -0.84961 -0.44336zm-0.98242 4.3008v7.0801l-3.5391-1.7715zm2 0 3.5391 5.3086l-3.5391 1.7715z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> </svg> diff --git a/editor/icons/icon_quad_mesh.svg b/editor/icons/icon_quad_mesh.svg index bf7b593e9e..40a07b36f7 100644 --- a/editor/icons/icon_quad_mesh.svg +++ b/editor/icons/icon_quad_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path d="m15 1037.4v14h-14v-14zm-2 2h-8.5859l8.5859 8.5859zm-10 1.4141v8.5859h8.5859z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> -</g> +<path d="m15 1v14h-14v-14zm-2 2h-8.5859l8.5859 8.5859zm-10 1.4141v8.5859h8.5859z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_rayito.svg b/editor/icons/icon_rayito.svg index e1891e783a..937a5cc4d7 100644 --- a/editor/icons/icon_rayito.svg +++ b/editor/icons/icon_rayito.svg @@ -1,6 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)" fill="#ffd684"> -<rect transform="matrix(1 0 -.14142 .98995 0 0)" x="152.19" y="1047.9" width="7" height="7.0711"/> -<path d="m6 1043.4h8l-9 8z"/> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m4 1l-1 7h2.875l-0.875 7 9-8h-3.8574l0.85742-6h-7z" fill="#ffd684"/> </g> </svg> diff --git a/editor/icons/icon_reflection_probe.svg b/editor/icons/icon_reflection_probe.svg index 0a7f537737..e0f1572317 100644 --- a/editor/icons/icon_reflection_probe.svg +++ b/editor/icons/icon_reflection_probe.svg @@ -1,7 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)" fill="none" stroke="#fc9c9c" stroke-linejoin="round" stroke-opacity=".99608" stroke-width="2"> -<path d="m2 1045.4v5h12v-4"/> -<path d="m2 1040.4 5 6 7-7"/> -<path d="m14 1043.4v-4h-4" stroke-linecap="round"/> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m10 2a1.0001 1.0001 0 1 0 0 2h1.5859l-4.5195 4.5195-4.2988-5.1582-1.5352 1.2793 5 6a1.0001 1.0001 0 0 0 1.4746 0.064453l5.293-5.293v1.5879a1.0001 1.0001 0 1 0 2 0v-4a1.0001 1.0001 0 0 0 -1 -1h-4zm-9 7v5a1.0001 1.0001 0 0 0 1 1h12a1.0001 1.0001 0 0 0 1 -1v-4h-2v3h-10v-4h-2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fc9c9c" fill-opacity=".99608" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> </g> </svg> diff --git a/editor/icons/icon_short_cut.svg b/editor/icons/icon_short_cut.svg index 736f1f3c02..8c7978e522 100644 --- a/editor/icons/icon_short_cut.svg +++ b/editor/icons/icon_short_cut.svg @@ -1,6 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)" fill-opacity=".99608"> -<path transform="translate(0 1036.4)" d="m4 2c-0.55228 0-1 0.4477-1 1v9.084c4.015e-4 0.506 0.448 0.91602 1 0.91602h8c0.552 0 0.9996-0.41002 1-0.91602v-9.084c0-0.5523-0.44772-1-1-1h-8zm-3 2v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-9h-1v9a0.99998 0.99998 0 0 1 -1 1h-10a1 1 0 0 1 -1 -1v-9h-1zm6 0h3l-1 3h2l-4 4 1-3h-2l1-4z" fill="#e0e0e0"/> -<rect x="27" y="1038.4" width="7" height="14" fill="#fff"/> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m4 2c-0.55228 0-1 0.4477-1 1v9.084c4.015e-4 0.506 0.448 0.91602 1 0.91602h8c0.552 0 0.9996-0.41002 1-0.91602v-9.084c0-0.5523-0.44772-1-1-1h-8zm-3 2v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-9h-1v9a0.99998 0.99998 0 0 1 -1 1h-10a1 1 0 0 1 -1 -1v-9h-1zm6 0h3l-1 3h2l-4 4 1-3h-2l1-4z" fill="#e0e0e0" fill-opacity=".99608"/> </g> </svg> diff --git a/editor/icons/icon_skeleton.svg b/editor/icons/icon_skeleton.svg index d5c5f301bb..ef563338c8 100644 --- a/editor/icons/icon_skeleton.svg +++ b/editor/icons/icon_skeleton.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 0.26562v0.001953h4v-0.001953a2 2 0 0 0 1 -0.26562 2 2 0 0 0 1 -1.7324v-3.5469a4 4 0 0 0 2 -3.4531 4 4 0 0 0 -4 -4h-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-4 2h2v1h-2v-1zm-2 2h1v1h1v-1h1 1v1h1v-1h1v0.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-0.86914z" fill="#fc9c9c" fill-opacity=".99608"/> -</g> +<path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 0.26562v0.001953h4v-0.001953a2 2 0 0 0 1 -0.26562 2 2 0 0 0 1 -1.7324v-3.5469a4 4 0 0 0 2 -3.4531 4 4 0 0 0 -4 -4h-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-4 2h2v1h-2v-1zm-2 2h1v1h1v-1h1 1v1h1v-1h1v0.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-0.86914z" fill="#fc9c9c" fill-opacity=".99608"/> </svg> diff --git a/editor/icons/icon_skeleton_2d.svg b/editor/icons/icon_skeleton_2d.svg new file mode 100644 index 0000000000..1ee9bde2a6 --- /dev/null +++ b/editor/icons/icon_skeleton_2d.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 0.26562v0.001953h4v-0.001953a2 2 0 0 0 1 -0.26562 2 2 0 0 0 1 -1.7324v-3.5469a4 4 0 0 0 2 -3.4531 4 4 0 0 0 -4 -4h-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-4 2h2v1h-2v-1zm-2 2h1v1h1v-1h1 1v1h1v-1h1v0.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-0.86914z" fill="#a5b7f3"/> +</svg> diff --git a/editor/icons/icon_sphere_mesh.svg b/editor/icons/icon_sphere_mesh.svg index 519b69cbd7..e298bbef3d 100644 --- a/editor/icons/icon_sphere_mesh.svg +++ b/editor/icons/icon_sphere_mesh.svg @@ -1,5 +1,3 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 3.8541 0 7-3.1458 7-7 0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-0.071342-2.6061-0.29819-3.9434-0.69141 0.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549 0.41253 3.637 2.0767 3.9414 4.1699-1.3046 0.36677-2.6158 0.60259-3.9414 0.6875v-4.8574zm3.7852 6.2812c-0.50864 1.7788-1.9499 3.1531-3.7852 3.5215v-2.9512c1.2792-0.072301 2.5419-0.26704 3.7852-0.57031zm-9.5645 0.017578c1.2733 0.31892 2.5337 0.50215 3.7793 0.5625v2.9414c-1.8291-0.36719-3.266-1.7339-3.7793-3.5039z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ffd684" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> -</g> +<path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 3.8541 0 7-3.1458 7-7 0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-0.071342-2.6061-0.29819-3.9434-0.69141 0.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549 0.41253 3.637 2.0767 3.9414 4.1699-1.3046 0.36677-2.6158 0.60259-3.9414 0.6875v-4.8574zm3.7852 6.2812c-0.50864 1.7788-1.9499 3.1531-3.7852 3.5215v-2.9512c1.2792-0.072301 2.5419-0.26704 3.7852-0.57031zm-9.5645 0.017578c1.2733 0.31892 2.5337 0.50215 3.7793 0.5625v2.9414c-1.8291-0.36719-3.266-1.7339-3.7793-3.5039z" fill="#ffd684"/> </svg> diff --git a/editor/icons/icon_timer.svg b/editor/icons/icon_timer.svg index e5907cea20..6bf4a29158 100644 --- a/editor/icons/icon_timer.svg +++ b/editor/icons/icon_timer.svg @@ -1,8 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> -<rect x="2" y="1037.4" width="12" height="2" ry="1" fill="#e0e0e0"/> -<rect x="2" y="1049.4" width="12" height="2" ry="1" fill="#e0e0e0"/> -<path d="m3 1050.4h10l-3-6h-4z" fill="#e0e0e0"/> -<path d="m3 1038.4h10c0 2-3 4-4 6 1 2 4 4 4 6h-10c0-2 3-4 4-6-1-2-4-4-4-6z" fill="none" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2"/> +<path transform="translate(0 1036.4)" d="m3 1a1.0001 1.0001 0 0 0 -0.38672 0.078125 1.0001 1.0001 0 0 0 -0.0019531 0c-0.0022762 9.545e-4 -0.0035918 0.0029354-0.0058593 0.0039062a1.0001 1.0001 0 0 0 -0.31055 0.20898c-0.0012857 0.0012787-0.0026276 0.0026206-0.0039063 0.0039063a1.0001 1.0001 0 0 0 -0.20508 0.30469c-0.0029915 0.0068502-0.0069239 0.012601-0.0097656 0.019531a1.0001 1.0001 0 0 0 -0.076172 0.38086c0 1.5 0.96697 2.6247 1.873 3.6602 0.76081 0.8695 1.4161 1.6425 1.875 2.3398-0.45889 0.6974-1.1141 1.4723-1.875 2.3418-0.90608 1.0355-1.873 2.1582-1.873 3.6582a1.0001 1.0001 0 0 0 0.078125 0.38867v0.001953c9.292e-4 0.002204 0.0029617 0.003663 0.0039062 0.005859a1.0001 1.0001 0 0 0 0.20898 0.30664c0.0010185 0.001027 0.0028834 0.004836 0.0039063 0.005859a1.0001 1.0001 0 0 0 0.30078 0.20312c0.0093182 0.004119 0.017877 0.007879 0.027344 0.011719a1.0001 1.0001 0 0 0 0.37695 0.076172h10a1.0001 1.0001 0 0 0 0.375 -0.074219c0.010174-0.0041 0.019294-0.009251 0.029297-0.013672a1.0001 1.0001 0 0 0 0.29297 -0.19922c0.004786-0.004679 0.00898-0.008899 0.013672-0.013672a1.0001 1.0001 0 0 0 0.20117 -0.29492c0.004119-0.009318 0.007879-0.017877 0.011719-0.027344a1.0001 1.0001 0 0 0 0.076172 -0.37695c0-1.5-0.96697-2.6227-1.873-3.6582-0.76087-0.8695-1.4161-1.6444-1.875-2.3418 0.4589-0.6973 1.1142-1.4703 1.875-2.3398 0.90608-1.0355 1.873-2.1602 1.873-3.6602a1.0001 1.0001 0 0 0 -0.078125 -0.39062 1.0001 1.0001 0 0 0 -0.21484 -0.31641 1.0001 1.0001 0 0 0 -0.31055 -0.21094 1.0001 1.0001 0 0 0 -0.011718 -0.0058593 1.0001 1.0001 0 0 0 -0.38477 -0.076172h-10zm1.5879 2h6.8242c-0.2378 0.4408-0.3055 0.7892-0.78906 1.3418-0.84392 0.9645-1.8983 1.9723-2.5176 3.2109a1.0001 1.0001 0 0 0 -0.10547 0.44727 1.0001 1.0001 0 0 0 -0.10547 -0.44727c-0.61926-1.2386-1.6737-2.2464-2.5176-3.2109-0.48356-0.5526-0.55126-0.901-0.78906-1.3418z" fill="#e0e0e0"/> </g> </svg> diff --git a/editor/icons/icon_tree.svg b/editor/icons/icon_tree.svg index 62efb9f94f..15be220451 100644 --- a/editor/icons/icon_tree.svg +++ b/editor/icons/icon_tree.svg @@ -1,6 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> -<rect x="29" y="1042.4" width="1" height="1" fill="#fefeff"/> <path transform="translate(0 1036.4)" d="m1 1v13c5.52e-5 0.55226 0.44774 0.99994 1 1h13v-2h-12v-6h2v3c5.52e-5 0.55226 0.44774 0.99994 1 1h9v-2h-8v-2h8v-2h-12v-2h12v-2z" fill="#a5efac"/> </g> </svg> diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp index 3f5dc7c9f4..c1c1183692 100644 --- a/editor/import/editor_import_plugin.cpp +++ b/editor/import/editor_import_plugin.cpp @@ -74,14 +74,14 @@ String EditorImportPlugin::get_resource_type() const { float EditorImportPlugin::get_priority() const { if (!(get_script_instance() && get_script_instance()->has_method("get_priority"))) { - return EditorImportPlugin::get_priority(); + return ResourceImporter::get_priority(); } return get_script_instance()->call("get_priority"); } int EditorImportPlugin::get_import_order() const { if (!(get_script_instance() && get_script_instance()->has_method("get_import_order"))) { - return EditorImportPlugin::get_import_order(); + return ResourceImporter::get_import_order(); } return get_script_instance()->call("get_import_order"); } diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index 1c4617c353..321d29f2f6 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -762,14 +762,22 @@ PoolVector<Color> EditorSceneImporterGLTF::_decode_accessor_as_color(GLTFState & PoolVector<Color> ret; if (attribs.size() == 0) return ret; - ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret); + int type = state.accessors[p_accessor].type; + ERR_FAIL_COND_V(!(type == TYPE_VEC3 || type == TYPE_VEC4), ret); + int components; + if (type == TYPE_VEC3) { + components = 3; + } else { // TYPE_VEC4 + components = 4; + } + ERR_FAIL_COND_V(attribs.size() % components != 0, ret); const double *attribs_ptr = attribs.ptr(); - int ret_size = attribs.size() / 4; + int ret_size = attribs.size() / components; ret.resize(ret_size); { PoolVector<Color>::Write w = ret.write(); for (int i = 0; i < ret_size; i++) { - w[i] = Color(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]); + w[i] = Color(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], components == 4 ? attribs_ptr[i * 4 + 3] : 1.0); } } return ret; @@ -1108,7 +1116,8 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b if (d.has("uri")) { String uri = d["uri"]; - if (uri.findn("data:application/octet-stream;base64") == 0) { + if (uri.findn("data:application/octet-stream;base64") == 0 || + uri.findn("data:" + mimetype + ";base64") == 0) { //embedded data data = _parse_base64_uri(uri); data_ptr = data.ptr(); @@ -1874,6 +1883,8 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye animation.instance(); animation->set_name(name); + float length = 0; + for (Map<int, GLTFAnimation::Track>::Element *E = anim.tracks.front(); E; E = E->next()) { const GLTFAnimation::Track &track = E->get(); @@ -1892,8 +1903,6 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye node_path = ap->get_parent()->get_path_to(node->godot_nodes[i]); } - float length = 0; - for (int i = 0; i < track.rotation_track.times.size(); i++) { length = MAX(length, track.rotation_track.times[i]); } @@ -1910,8 +1919,6 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye } } - animation->set_length(length); - if (track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) { //make transform track int track_idx = animation->get_track_count(); @@ -2029,6 +2036,7 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye } } } + animation->set_length(length); ap->add_animation(name, animation); } diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index 22c32f5fc9..ec0500361d 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -50,7 +50,7 @@ void ResourceImporterCSVTranslation::get_recognized_extensions(List<String> *p_e } String ResourceImporterCSVTranslation::get_save_extension() const { - return ""; //does not save a single resoure + return ""; //does not save a single resource } String ResourceImporterCSVTranslation::get_resource_type() const { diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 78fc9ec9bd..21803a2184 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -188,7 +188,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Spati return OK; } -static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p_single_mesh, bool p_generate_tangents, List<String> *r_missing_deps) { +static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p_single_mesh, bool p_generate_tangents, Vector3 p_scale_mesh, List<String> *r_missing_deps) { FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); @@ -198,6 +198,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p mesh.instance(); bool generate_tangents = p_generate_tangents; + Vector3 scale_mesh = p_scale_mesh; bool flip_faces = false; //bool flip_faces = p_options["force/flip_faces"]; //bool force_smooth = p_options["force/smooth_shading"]; @@ -227,9 +228,9 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p Vector<String> v = l.split(" ", false); ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT); Vector3 vtx; - vtx.x = v[1].to_float(); - vtx.y = v[2].to_float(); - vtx.z = v[3].to_float(); + vtx.x = v[1].to_float() * scale_mesh.x; + vtx.y = v[2].to_float() * scale_mesh.y; + vtx.z = v[3].to_float() * scale_mesh.z; vertices.push_back(vtx); } else if (l.begins_with("vt ")) { //uv @@ -401,7 +402,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in List<Ref<Mesh> > meshes; - Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, r_missing_deps); + Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, Vector3(1, 1, 1), r_missing_deps); if (err != OK) { if (r_err) { @@ -468,6 +469,7 @@ String ResourceImporterOBJ::get_preset_name(int p_idx) const { void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_tangents"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "scale_mesh"), Vector3(1, 1, 1))); } bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { @@ -478,7 +480,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s List<Ref<Mesh> > meshes; - Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], NULL); + Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["scale_mesh"], NULL); ERR_FAIL_COND_V(err != OK, err); ERR_FAIL_COND_V(meshes.size() != 1, ERR_BUG); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index c22e1cd88b..04c9246aed 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -1011,6 +1011,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set) { player->seek_delta(pos, pos - cpos); } else { + player->stop(true); player->seek(pos, true); } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index b8bf2b97f6..c203b4b81e 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -30,11 +30,10 @@ #include "asset_library_editor_plugin.h" +#include "core/io/json.h" +#include "core/version.h" #include "editor_node.h" #include "editor_settings.h" -#include "io/json.h" - -#include "version_generated.gen.h" void EditorAssetLibraryItem::configure(const String &p_title, int p_asset_id, const String &p_category, int p_category_id, const String &p_author, int p_author_id, int p_rating, const String &p_cost) { @@ -308,7 +307,7 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() { preview_hb->set_v_size_flags(SIZE_EXPAND_FILL); previews->add_child(preview_hb); - get_ok()->set_text(TTR("Install")); + get_ok()->set_text(TTR("Download")); get_cancel()->set_text(TTR("Close")); } /////////////////////////////////////////////////////////////////////////////////// @@ -515,6 +514,7 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { download = memnew(HTTPRequest); add_child(download); download->connect("request_completed", this, "_http_download_completed"); + download->set_use_threads(EDITOR_DEF("asset_library/use_threads", true)); download_error = memnew(AcceptDialog); add_child(download_error); @@ -534,11 +534,9 @@ void EditorAssetLibrary::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - TextureRect *tf = memnew(TextureRect); - tf->set_texture(get_icon("Error", "EditorIcons")); + error_tr->set_texture(get_icon("Error", "EditorIcons")); reverse->set_icon(get_icon("Sort", "EditorIcons")); - error_hb->add_child(tf); error_label->raise(); } break; @@ -586,6 +584,8 @@ void EditorAssetLibrary::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { library_scroll_bg->add_style_override("panel", get_stylebox("bg", "Tree")); + error_tr->set_texture(get_icon("Error", "EditorIcons")); + reverse->set_icon(get_icon("Sort", "EditorIcons")); } break; } } @@ -833,6 +833,7 @@ void EditorAssetLibrary::_request_image(ObjectID p_for, String p_image_url, Imag iq.image_index = p_image_index; iq.image_type = p_type; iq.request = memnew(HTTPRequest); + iq.request->set_use_threads(EDITOR_DEF("asset_library/use_threads", true)); iq.target = p_for; iq.queue_id = ++last_queue_id; @@ -877,7 +878,8 @@ void EditorAssetLibrary::_search(int p_page) { } args += String() + "sort=" + sort_key[sort->get_selected()]; - args += "&godot_version=" + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR); + // We use the "branch" version, i.e. major.minor, as patch releases should be compatible + args += "&godot_version=" + String(VERSION_BRANCH); String support_list; for (int i = 0; i < SUPPORT_MAX; i++) { @@ -1452,6 +1454,8 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { error_label = memnew(Label); error_label->add_color_override("color", get_color("error_color", "Editor")); error_hb->add_child(error_label); + error_tr = memnew(TextureRect); + error_hb->add_child(error_tr); description = NULL; diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index b344716c1d..89b79d7cfb 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -194,6 +194,7 @@ class EditorAssetLibrary : public PanelContainer { Button *search; ProgressBar *load_status; HBoxContainer *error_hb; + TextureRect *error_tr; Label *error_label; MenuButton *support; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 4a05d401cb..67323fa753 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -169,64 +169,10 @@ public: } }; -void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) { - List<Node *> &selection = editor_selection->get_selected_node_list(); - - undo_redo->create_action(TTR("Move Pivot")); - - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - - Node2D *n2d = Object::cast_to<Node2D>(E->get()); - if (n2d && n2d->_edit_use_pivot()) { - - Vector2 offset = n2d->_edit_get_pivot(); - Vector2 gpos = n2d->get_global_position(); - - Vector2 local_mouse_pos = n2d->get_canvas_transform().affine_inverse().xform(mouse_pos); - - Vector2 motion_ofs = gpos - local_mouse_pos; - - undo_redo->add_do_method(n2d, "set_global_position", local_mouse_pos); - undo_redo->add_do_method(n2d, "_edit_set_pivot", offset + n2d->get_global_transform().affine_inverse().basis_xform(motion_ofs)); - undo_redo->add_undo_method(n2d, "set_global_position", gpos); - undo_redo->add_undo_method(n2d, "_edit_set_pivot", offset); - for (int i = 0; i < n2d->get_child_count(); i++) { - Node2D *n2dc = Object::cast_to<Node2D>(n2d->get_child(i)); - if (!n2dc) - continue; - - undo_redo->add_do_method(n2dc, "set_global_position", n2dc->get_global_position()); - undo_redo->add_undo_method(n2dc, "set_global_position", n2dc->get_global_position()); - } - } - - Control *cnt = Object::cast_to<Control>(E->get()); - if (cnt) { - - Vector2 old_pivot = cnt->get_pivot_offset(); - Vector2 new_pivot = cnt->get_global_transform_with_canvas().affine_inverse().xform(mouse_pos); - Vector2 old_pos = cnt->get_position(); - - Vector2 top_pos = cnt->get_transform().get_origin(); //remember where top pos was - cnt->set_pivot_offset(new_pivot); - Vector2 new_top_pos = cnt->get_transform().get_origin(); //check where it is now - - Vector2 new_pos = old_pos - (new_top_pos - top_pos); //offset it back - - undo_redo->add_do_method(cnt, "set_pivot_offset", new_pivot); - undo_redo->add_do_method(cnt, "set_position", new_pos); - undo_redo->add_undo_method(cnt, "set_pivot_offset", old_pivot); - undo_redo->add_undo_method(cnt, "set_position", old_pos); - } - } - - undo_redo->commit_action(); -} - void CanvasItemEditor::_snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius) { float radius = p_radius / zoom; float dist = Math::abs(p_value - p_target_snap); - if (p_radius < 0 || dist < radius && (!r_snapped || dist < Math::abs(r_current_snap - p_value))) { + if ((p_radius < 0 || dist < radius) && (!r_snapped || dist < Math::abs(r_current_snap - p_value))) { r_current_snap = p_target_snap; r_snapped = true; } @@ -263,7 +209,6 @@ void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, } Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const CanvasItem *p_canvas_item, unsigned int p_forced_modes) { - Point2 dist[2]; bool snapped[2] = { false, false }; // Smart snap using the canvas position @@ -271,12 +216,12 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const real_t rotation = 0.0; if (p_canvas_item) { - Point2 begin; - Point2 end; rotation = p_canvas_item->get_global_transform_with_canvas().get_rotation(); + // Parent sides and center if ((snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) { - // Parent sides and center + Point2 begin; + Point2 end; bool can_snap = false; if (const Control *c = Object::cast_to<Control>(p_canvas_item)) { begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0))); @@ -295,23 +240,29 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const } } - // Self anchors (for sides) + // Self anchors if ((snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) { if (const Control *c = Object::cast_to<Control>(p_canvas_item)) { - begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP)))); - end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM)))); + Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP)))); + Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM)))); _snap_if_closer_point(p_target, begin, output, snapped, rotation); _snap_if_closer_point(p_target, end, output, snapped, rotation); } } - // Self sides (for anchors) + // Self sides if ((snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) { - begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position()); - end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size()); + Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position()); + Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size()); _snap_if_closer_point(p_target, begin, output, snapped, rotation); _snap_if_closer_point(p_target, end, output, snapped, rotation); } + + // Self center + if ((snap_active && snap_node_center && (p_modes & SNAP_NODE_CENTER)) || (p_forced_modes & SNAP_NODE_CENTER)) { + Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0); + _snap_if_closer_point(p_target, center, output, snapped, rotation); + } } // Other nodes sides @@ -340,11 +291,11 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const // Grid Point2 offset = grid_offset; if (snap_relative) { - List<Node *> selection = editor_selection->get_selected_node_list(); + List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) { offset = Object::cast_to<Node2D>(selection[0])->get_global_position(); - } else { - offset = _find_topleftmost_point(); + } else if (selection.size() > 0) { + offset = _get_encompassing_rect_from_list(selection).position; } } Point2 grid_output; @@ -362,7 +313,6 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const } float CanvasItemEditor::snap_angle(float p_target, float p_start) const { - float offset = snap_relative ? p_start : p_target; return (snap_rotation && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target; } @@ -377,48 +327,20 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { return; if (k->is_pressed() && !k->is_echo()) { - if (drag_pivot_shortcut.is_valid() && drag_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) { - //move drag pivot - drag = DRAG_PIVOT; - } else if (set_pivot_shortcut.is_valid() && set_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) { - if (!Input::get_singleton()->is_mouse_button_pressed(0)) { - List<Node *> selection = editor_selection->get_selected_node_list(); - Vector2 mouse_pos = viewport->get_local_mouse_position(); - if (selection.size() && viewport->get_rect().has_point(mouse_pos)) { - //just in case, make it work if over viewport - mouse_pos = transform.affine_inverse().xform(mouse_pos); - mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item()); - - _edit_set_pivot(mouse_pos); - } - } - } else if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) { + if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) { // Multiply the grid size grid_step_multiplier = MIN(grid_step_multiplier + 1, 12); - viewport_base->update(); viewport->update(); } else if ((snap_grid || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) { // Divide the grid size Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1); if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0) grid_step_multiplier--; - viewport_base->update(); viewport->update(); } } } -void CanvasItemEditor::_tool_select(int p_index) { - - ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, rotate_button, pivot_button, pan_button }; - for (int i = 0; i < TOOL_MAX; i++) { - tb[i]->set_pressed(i == p_index); - } - - viewport->update(); - tool = (Tool)p_index; -} - Object *CanvasItemEditor::_get_editor_data(Object *p_what) { CanvasItem *ci = Object::cast_to<CanvasItem>(p_what); @@ -428,220 +350,109 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) { return memnew(CanvasItemEditorSelectedItem); } -Dictionary CanvasItemEditor::get_state() const { +void CanvasItemEditor::_keying_changed() { - Dictionary state; - state["zoom"] = zoom; - state["ofs"] = Point2(h_scroll->get_value(), v_scroll->get_value()); - //state["ofs"]=-transform.get_origin(); - state["grid_offset"] = grid_offset; - state["grid_step"] = grid_step; - state["snap_rotation_offset"] = snap_rotation_offset; - state["snap_rotation_step"] = snap_rotation_step; - state["snap_active"] = snap_active; - state["snap_node_parent"] = snap_node_parent; - state["snap_node_anchors"] = snap_node_anchors; - state["snap_node_sides"] = snap_node_sides; - state["snap_other_nodes"] = snap_other_nodes; - state["snap_grid"] = snap_grid; - state["snap_guides"] = snap_guides; - state["show_grid"] = show_grid; - state["show_rulers"] = show_rulers; - state["show_guides"] = show_guides; - state["show_helpers"] = show_helpers; - state["snap_rotation"] = snap_rotation; - state["snap_relative"] = snap_relative; - state["snap_pixel"] = snap_pixel; - state["skeleton_show_bones"] = skeleton_show_bones; - return state; + if (AnimationPlayerEditor::singleton->get_key_editor()->is_visible_in_tree()) + animation_hb->show(); + else + animation_hb->hide(); } -void CanvasItemEditor::set_state(const Dictionary &p_state) { - - Dictionary state = p_state; - if (state.has("zoom")) { - zoom = p_state["zoom"]; - } - - if (state.has("ofs")) { - _update_scrollbars(); // i wonder how safe is calling this here.. - Point2 ofs = p_state["ofs"]; - h_scroll->set_value(ofs.x); - v_scroll->set_value(ofs.y); - } - - if (state.has("grid_offset")) { - grid_offset = state["grid_offset"]; - } - - if (state.has("grid_step")) { - grid_step = state["grid_step"]; - } - - if (state.has("snap_rotation_step")) { - snap_rotation_step = state["snap_rotation_step"]; - } - - if (state.has("snap_rotation_offset")) { - snap_rotation_offset = state["snap_rotation_offset"]; - } - - if (state.has("snap_active")) { - snap_active = state["snap_active"]; - snap_button->set_pressed(snap_active); - } - - if (state.has("snap_node_parent")) { - snap_node_parent = state["snap_node_parent"]; - int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); - smartsnap_config_popup->set_item_checked(idx, snap_node_parent); - } - - if (state.has("snap_node_anchors")) { - snap_node_anchors = state["snap_node_anchors"]; - int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS); - smartsnap_config_popup->set_item_checked(idx, snap_node_anchors); - } - if (state.has("snap_node_sides")) { - snap_node_sides = state["snap_node_sides"]; - int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES); - smartsnap_config_popup->set_item_checked(idx, snap_node_sides); - } +Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_list) { + ERR_FAIL_COND_V(p_list.empty(), Rect2()); - if (state.has("snap_other_nodes")) { - snap_other_nodes = state["snap_other_nodes"]; - int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES); - smartsnap_config_popup->set_item_checked(idx, snap_other_nodes); - } + // Handles the first element + CanvasItem *canvas_item = p_list.front()->get(); + Rect2 rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2()); - if (state.has("snap_guides")) { - snap_guides = state["snap_guides"]; - int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES); - smartsnap_config_popup->set_item_checked(idx, snap_guides); - } - - if (state.has("snap_grid")) { - snap_grid = state["snap_grid"]; - int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID); - snap_config_menu->get_popup()->set_item_checked(idx, snap_grid); - } - - if (state.has("show_grid")) { - show_grid = state["show_grid"]; - int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); - view_menu->get_popup()->set_item_checked(idx, show_grid); - } - - if (state.has("show_rulers")) { - show_rulers = state["show_rulers"]; - int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS); - view_menu->get_popup()->set_item_checked(idx, show_rulers); + // Handles the other ones + for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + Rect2 current_rect = canvas_item->_edit_get_rect(); + Transform2D xform = canvas_item->get_global_transform_with_canvas(); + 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)); + rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y))); } - if (state.has("show_guides")) { - show_guides = state["show_guides"]; - int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES); - view_menu->get_popup()->set_item_checked(idx, show_guides); - } + return rect; +} - if (state.has("show_helpers")) { - show_helpers = state["show_helpers"]; - int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS); - view_menu->get_popup()->set_item_checked(idx, show_helpers); - } +void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { + if (!p_node) + return; + if (Object::cast_to<Viewport>(p_node)) + return; - if (state.has("snap_rotation")) { - snap_rotation = state["snap_rotation"]; - int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); - snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation); - } + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); - if (state.has("snap_relative")) { - snap_relative = state["snap_relative"]; - int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE); - snap_config_menu->get_popup()->set_item_checked(idx, snap_relative); - } + bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; + bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); + bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_"); - if (state.has("snap_pixel")) { - snap_pixel = state["snap_pixel"]; - int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); - snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel); + if (!lock_children && (!inherited || editable)) { + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); + _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); + } + } } - if (state.has("skeleton_show_bones")) { - skeleton_show_bones = state["skeleton_show_bones"]; - int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES); - skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones); + if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { + Rect2 rect = canvas_item->_edit_get_rect(); + Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); + if (r_first) { + r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2()); + r_first = false; + } + r_rect.expand_to(xform.xform(rect.position)); + r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); + r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); + r_rect.expand_to(xform.xform(rect.position + rect.size)); } - - viewport->update(); -} - -void CanvasItemEditor::_add_canvas_item(CanvasItem *p_canvas_item) { - - editor_selection->add_node(p_canvas_item); } -void CanvasItemEditor::_remove_canvas_item(CanvasItem *p_canvas_item) { - - editor_selection->remove_node(p_canvas_item); -} -void CanvasItemEditor::_clear_canvas_items() { - - editor_selection->clear(); -} - -void CanvasItemEditor::_keying_changed() { - - if (AnimationPlayerEditor::singleton->get_key_editor()->is_visible_in_tree()) - animation_hb->show(); - else - animation_hb->hide(); -} - -bool CanvasItemEditor::_is_part_of_subscene(CanvasItem *p_item) { - - Node *scene_node = get_tree()->get_edited_scene_root(); - Node *item_owner = p_item->get_owner(); - - return item_owner && item_owner != scene_node && p_item != scene_node && item_owner->get_filename() != ""; +Rect2 CanvasItemEditor::_get_scene_encompassing_rect() { + Rect2 rect; + bool first = true; + _expand_encompassing_rect_using_children(rect, editor->get_edited_scene(), first); + return rect; } -void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, Vector<_SelectResult> &r_items, int limit) { +void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int limit, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { if (!p_node) return; if (Object::cast_to<Viewport>(p_node)) return; const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - CanvasItem *c = Object::cast_to<CanvasItem>(p_node); + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - - if (c && !c->is_set_as_toplevel()) - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), p_parent_xform * c->get_transform(), p_canvas_xform, r_items); + if (canvas_item && !canvas_item->is_set_as_toplevel()) + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); else { CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), transform, cl ? cl->get_transform() : p_canvas_xform, r_items); //use base transform + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); //use base transform } - if (limit != 0 && r_items.size() >= limit) return; } - if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !Object::cast_to<CanvasLayer>(c)) { + if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { - Rect2 rect = c->_edit_get_rect(); - Transform2D to_local = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse(); - Point2 local_pos = to_local.xform(p_pos); - const real_t local_grab_distance = (to_local.xform(p_pos + Vector2(grab_distance, 0)) - local_pos).length(); - Rect2 local_pos_rect = Rect2(local_pos, Vector2(0, 0)).grow(local_grab_distance); + Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse(); + const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length(); - if (rect.intersects(local_pos_rect) && c->_edit_is_selected_on_click(local_pos, local_grab_distance)) { - Node2D *node = Object::cast_to<Node2D>(c); + if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) { + Node2D *node = Object::cast_to<Node2D>(canvas_item); _SelectResult res; - res.item = c; + res.item = canvas_item; res.z_index = node ? node->get_z_index() : 0; res.has_z = node; r_items.push_back(res); @@ -651,64 +462,45 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no return; } -void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, List<CanvasItem *> *r_items) { - +void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { if (!p_node) return; if (Object::cast_to<Viewport>(p_node)) return; - CanvasItem *c = Object::cast_to<CanvasItem>(p_node); + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; - bool editable = false; - if (inherited) { - editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); - } + bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_"); + if (!lock_children && (!inherited || editable)) { for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - - if (c && !c->is_set_as_toplevel()) - _find_canvas_items_at_rect(p_rect, p_node->get_child(i), p_parent_xform * c->get_transform(), p_canvas_xform, r_items); - else { - CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); - _find_canvas_items_at_rect(p_rect, p_node->get_child(i), transform, cl ? cl->get_transform() : p_canvas_xform, r_items); + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); + _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); } } } - if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !Object::cast_to<CanvasLayer>(c)) { + if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { - Rect2 rect = c->_edit_get_rect(); - Transform2D xform = p_parent_xform * p_canvas_xform * c->get_transform(); + Rect2 rect = canvas_item->_edit_get_rect(); + Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); if (p_rect.has_point(xform.xform(rect.position)) && p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) && p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) && p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) { - r_items->push_back(c); + r_items->push_back(canvas_item); } } } -void CanvasItemEditor::_select_click_on_empty_area(Point2 p_click_pos, bool p_append, bool p_box_selection) { - if (!p_append) { - editor_selection->clear(); - viewport->update(); - viewport_base->update(); - }; - - if (p_box_selection) { - // Start a box selection - drag_from = transform.affine_inverse().xform(p_click_pos); - box_selecting = true; - box_selecting_to = drag_from; - } -} - -bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag) { +bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append) { bool still_selected = true; if (p_append) { if (editor_selection->is_selected(item)) { @@ -717,7 +509,7 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po still_selected = false; } else { // Add the item to the selection - _append_canvas_item(item); + editor_selection->add_node(item); } } else { if (!editor_selection->is_selected(item)) { @@ -730,216 +522,33 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po } } } - - if (still_selected && p_drag) { - // Drag the node(s) if requested - _prepare_drag(p_click_pos); - } - viewport->update(); - viewport_base->update(); return still_selected; } -void CanvasItemEditor::_key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE p_move_mode) { - - if (drag != DRAG_NONE) - return; - - if (editor_selection->get_selected_node_list().empty()) - return; - - undo_redo->create_action(TTR("Move Action"), UndoRedo::MERGE_ENDS); - - List<Node *> selection = editor_selection->get_selected_node_list(); - - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - - CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - if (!se) - continue; - - if (canvas_item->has_meta("_edit_lock_")) - continue; - - Vector2 drag = p_dir; - if (p_snap) - drag *= grid_step * Math::pow(2.0, grid_step_multiplier); - - undo_redo->add_undo_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state()); - - if (p_move_mode == MOVE_VIEW_BASE) { - - // drag = transform.affine_inverse().basis_xform(p_dir); // zoom sensitive - drag = canvas_item->get_global_transform_with_canvas().affine_inverse().basis_xform(drag); - Rect2 local_rect = canvas_item->_edit_get_rect(); - local_rect.position += drag; - undo_redo->add_do_method(canvas_item, "_edit_set_rect", local_rect); - - } else { // p_move_mode==MOVE_LOCAL_BASE || p_move_mode==MOVE_LOCAL_WITH_ROT - - Node2D *node_2d = Object::cast_to<Node2D>(canvas_item); - if (node_2d) { - - if (p_move_mode == MOVE_LOCAL_WITH_ROT) { - Transform2D m; - m.rotate(node_2d->get_rotation()); - drag = m.xform(drag); - } - node_2d->set_position(node_2d->get_position() + drag); - - } else { - Control *control = Object::cast_to<Control>(canvas_item); - if (control) - control->set_position(control->get_position() + drag); +List<CanvasItem *> CanvasItemEditor::_get_edited_canvas_items(bool retreive_locked, bool remove_canvas_item_if_parent_in_selection) { + List<CanvasItem *> selection; + for (Map<Node *, Object *>::Element *E = editor_selection->get_selection().front(); E; E = E->next()) { + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); + if (canvas_item && canvas_item->is_visible_in_tree() && canvas_item->get_viewport() == EditorNode::get_singleton()->get_scene_root() && (!retreive_locked || !canvas_item->has_meta("_edit_lock_"))) { + CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); + if (se) { + selection.push_back(canvas_item); } } } - undo_redo->commit_action(); -} - -Point2 CanvasItemEditor::_find_topleftmost_point() { - - Vector2 tl = Point2(1e10, 1e10); - Rect2 r2; - r2.position = tl; - - List<Node *> selection = editor_selection->get_selected_node_list(); - - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - - Rect2 rect = canvas_item->_edit_get_rect(); - Transform2D xform = canvas_item->get_global_transform_with_canvas(); - - r2.expand_to(xform.xform(rect.position)); - r2.expand_to(xform.xform(rect.position + Vector2(rect.size.x, 0))); - r2.expand_to(xform.xform(rect.position + rect.size)); - r2.expand_to(xform.xform(rect.position + Vector2(0, rect.size.y))); - } - - return r2.position; -} - -int CanvasItemEditor::get_item_count() { - - List<Node *> selection = editor_selection->get_selected_node_list(); - - int ic = 0; - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - - ic++; - }; - - return ic; -} - -CanvasItem *CanvasItemEditor::_get_single_item() { - - Map<Node *, Object *> &selection = editor_selection->get_selection(); - - CanvasItem *single_item = NULL; - - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { - - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - - if (single_item) - return NULL; //morethan one - - single_item = canvas_item; - }; - - return single_item; -} - -CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point) { - // Returns a drag type if a resize handle is clicked - CanvasItem *canvas_item = _get_single_item(); - - ERR_FAIL_COND_V(!canvas_item, DRAG_NONE); - - Rect2 rect = canvas_item->_edit_get_rect(); - Transform2D xforml = canvas_item->get_global_transform_with_canvas(); - Transform2D xform = transform * xforml; - - Vector2 endpoints[4] = { - - xform.xform(rect.position), - xform.xform(rect.position + Vector2(rect.size.x, 0)), - xform.xform(rect.position + rect.size), - xform.xform(rect.position + Vector2(0, rect.size.y)) - }; - - Vector2 endpointsl[4] = { - - xforml.xform(rect.position), - xforml.xform(rect.position + Vector2(rect.size.x, 0)), - xforml.xform(rect.position + rect.size), - xforml.xform(rect.position + Vector2(0, rect.size.y)) - }; - - DragType dragger[] = { - DRAG_TOP_LEFT, - DRAG_TOP, - DRAG_TOP_RIGHT, - DRAG_RIGHT, - DRAG_BOTTOM_RIGHT, - DRAG_BOTTOM, - DRAG_BOTTOM_LEFT, - DRAG_LEFT - }; - - float radius = (select_handle->get_size().width / 2) * 1.5; - - for (int i = 0; i < 4; i++) { - - int prev = (i + 3) % 4; - int next = (i + 1) % 4; - - r_point = endpointsl[i]; - - Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized(); - ofs *= 1.4144 * (select_handle->get_size().width / 2); - - ofs += endpoints[i]; - - if (ofs.distance_to(p_click) < radius) - return dragger[i * 2]; - - ofs = (endpoints[i] + endpoints[next]) / 2; - ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2); - - r_point = (endpointsl[i] + endpointsl[next]) / 2; - - if (ofs.distance_to(p_click) < radius) - return dragger[i * 2 + 1]; + if (remove_canvas_item_if_parent_in_selection) { + List<CanvasItem *> filtered_selection; + for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) { + if (!selection.find(E->get()->get_parent())) { + filtered_selection.push_back(E->get()); + } + } + return filtered_selection; + } else { + return selection; } - - return DRAG_NONE; } Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2 anchor) { @@ -958,148 +567,90 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 return p_control->get_transform().xform(position) / parent_size; } -CanvasItemEditor::DragType CanvasItemEditor::_get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point) { - // Returns a drag type if an anchor handle is clicked - CanvasItem *canvas_item = _get_single_item(); - ERR_FAIL_COND_V(!canvas_item, DRAG_NONE); - - Control *control = Object::cast_to<Control>(canvas_item); - ERR_FAIL_COND_V(!control, DRAG_NONE); - - Vector2 anchor_pos[4]; - anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP)); - anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP)); - anchor_pos[2] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_BOTTOM)); - anchor_pos[3] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_BOTTOM)); - - Rect2 anchor_rects[4]; - for (int i = 0; i < 4; i++) { - anchor_pos[i] = (transform * control->get_global_transform_with_canvas()).xform(_anchor_to_position(control, anchor_pos[i])); - anchor_rects[i] = Rect2(anchor_pos[i], anchor_handle->get_size()); - anchor_rects[i].position -= anchor_handle->get_size() * Vector2(i == 0 || i == 3, i <= 1); - } - - DragType dragger[] = { - DRAG_ANCHOR_TOP_LEFT, - DRAG_ANCHOR_TOP_RIGHT, - DRAG_ANCHOR_BOTTOM_RIGHT, - DRAG_ANCHOR_BOTTOM_LEFT, - }; +void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) { + for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); + if (se) { + se->undo_state = canvas_item->_edit_get_state(); + se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); + se->pre_drag_rect = canvas_item->_edit_get_rect(); + + se->pre_drag_bones_length = List<float>(); + se->pre_drag_bones_undo_state = List<Dictionary>(); + + // If we have a bone, save the state of all nodes in the IK chain + Node2D *bone = Object::cast_to<Node2D>(canvas_item); + if (bone && bone->has_meta("_edit_bone_")) { + // Check if we have an IK chain + List<Node2D *> bone_ik_list; + bool ik_found; + bone = Object::cast_to<Node2D>(bone->get_parent()); + while (bone) { + bone_ik_list.push_back(bone); + if (bone->has_meta("_edit_ik_")) { + ik_found = true; + break; + } else if (!bone->has_meta("_edit_bone_")) { + break; + } + bone = Object::cast_to<Node2D>(bone->get_parent()); + } - for (int i = 0; i < 4; i++) { - if (anchor_rects[i].has_point(p_click)) { - r_point = transform.affine_inverse().xform(anchor_pos[i]); - if ((anchor_pos[0] == anchor_pos[2]) && (anchor_pos[0].distance_to(p_click) < anchor_handle->get_size().length() / 3.0)) { - return DRAG_ANCHOR_ALL; - } else { - return dragger[i]; + //Save the bone state and length if we have an IK chain + if (ik_found) { + bone = Object::cast_to<Node2D>(canvas_item); + Transform2D bone_xform = bone->get_global_transform(); + for (List<Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) { + bone_xform = bone_xform * bone->get_transform().affine_inverse(); + Node2D *parent_bone = bone_E->get(); + se->pre_drag_bones_length.push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position())); + se->pre_drag_bones_undo_state.push_back(parent_bone->_edit_get_state()); + bone = parent_bone; + } + } } } } - - return DRAG_NONE; } -void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) { - - List<Node *> selection = editor_selection->get_selected_node_list(); - - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - +void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) { + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - if (!se) - continue; - - se->undo_state = canvas_item->_edit_get_state(); - if (Object::cast_to<Node2D>(canvas_item)) - se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot(); - if (Object::cast_to<Control>(canvas_item)) - se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset(); - - se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); - se->pre_drag_rect = canvas_item->_edit_get_rect(); - } - - if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0]) && bone_ik_list.size() == 0) { - drag = DRAG_NODE_2D; - drag_point_from = Object::cast_to<Node2D>(selection[0])->get_global_position(); - } else { - drag = DRAG_ALL; - drag_point_from = _find_topleftmost_point(); - } - drag_from = transform.affine_inverse().xform(p_click_pos); -} - -void CanvasItemEditor::incbeg(float &beg, float &end, float inc, float minsize, bool p_symmetric) { - - if (minsize < 0) { - - beg += inc; - if (p_symmetric) - end -= inc; - } else { - - if (p_symmetric) { - beg += inc; - end -= inc; - if (end - beg < minsize) { - float center = (beg + end) / 2.0; - beg = center - minsize / 2.0; - end = center + minsize / 2.0; + canvas_item->_edit_set_state(se->undo_state); + if (restore_bones) { + for (List<Dictionary>::Element *E = se->pre_drag_bones_undo_state.front(); E; E = E->next()) { + canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent()); + canvas_item->_edit_set_state(E->get()); } - - } else { - if (end - (beg + inc) < minsize) - beg = end - minsize; - else - beg += inc; } } } -void CanvasItemEditor::incend(float &beg, float &end, float inc, float minsize, bool p_symmetric) { - - if (minsize < 0) { - - end += inc; - if (p_symmetric) - beg -= inc; - } else { - - if (p_symmetric) { - - end += inc; - beg -= inc; - if (end - beg < minsize) { - float center = (beg + end) / 2.0; - beg = center - minsize / 2.0; - end = center + minsize / 2.0; +void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones) { + undo_redo->create_action(action_name); + for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); + 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()) { + 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()); } - - } else { - if ((end + inc) - beg < minsize) - end = beg + minsize; - else - end += inc; } } -} - -void CanvasItemEditor::_append_canvas_item(CanvasItem *p_item) { - - editor_selection->add_node(p_item); + undo_redo->add_do_method(viewport, "update"); + undo_redo->add_undo_method(viewport, "update"); + undo_redo->commit_action(); } void CanvasItemEditor::_snap_changed() { ((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step); grid_step_multiplier = 0; - viewport_base->update(); viewport->update(); } @@ -1111,7 +662,7 @@ void CanvasItemEditor::_selection_result_pressed(int p_result) { CanvasItem *item = selection_results[p_result].item; if (item) - _select_click_on_item(item, Point2(), additive_selection, false); + _select_click_on_item(item, Point2(), selection_menu_additive_selection); } void CanvasItemEditor::_selection_menu_hide() { @@ -1121,121 +672,13 @@ void CanvasItemEditor::_selection_menu_hide() { selection_menu->set_size(Vector2(0, 0)); } -void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) { - - Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); - - Node *scene = editor->get_edited_scene(); - if (!scene) - return; - - _find_canvas_items_at_pos(click, scene, transform, Transform2D(), selection_results); - - for (int i = 0; i < selection_results.size(); i++) { - CanvasItem *item = selection_results[i].item; - if (item != scene && item->get_owner() != scene && !scene->is_editable_instance(item->get_owner())) { - //invalid result - selection_results.remove(i); - i--; - } - } - - if (selection_results.size() == 1) { - - CanvasItem *item = selection_results[0].item; - selection_results.clear(); - - additive_selection = b->get_shift(); - - if (!_select_click_on_item(item, click, additive_selection, false)) - return; - - } else if (!selection_results.empty()) { - - selection_results.sort(); - - NodePath root_path = get_tree()->get_edited_scene_root()->get_path(); - StringName root_name = root_path.get_name(root_path.get_name_count() - 1); - - for (int i = 0; i < selection_results.size(); i++) { - - CanvasItem *item = selection_results[i].item; - - Ref<Texture> icon; - if (item->has_meta("_editor_icon")) - icon = item->get_meta("_editor_icon"); - else - icon = get_icon(has_icon(item->get_class(), "EditorIcons") ? item->get_class() : String("Object"), "EditorIcons"); - - String node_path = "/" + root_name + "/" + root_path.rel_path_to(item->get_path()); - - selection_menu->add_item(item->get_name()); - selection_menu->set_item_icon(i, icon); - selection_menu->set_item_metadata(i, node_path); - selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path); - } - - additive_selection = b->get_shift(); - - selection_menu->set_global_position(b->get_global_position()); - selection_menu->popup(); - selection_menu->call_deferred("grab_click_focus"); - selection_menu->set_invalidate_click_until_motion(); - - return; - } -} - -void CanvasItemEditor::_update_cursor() { - - CursorShape c = CURSOR_ARROW; - switch (drag) { - case DRAG_NONE: - if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { - c = CURSOR_DRAG; - } else { - switch (tool) { - case TOOL_MOVE: - c = CURSOR_MOVE; - break; - case TOOL_EDIT_PIVOT: - c = CURSOR_CROSS; - break; - case TOOL_PAN: - c = CURSOR_DRAG; - break; - } - } - break; - case DRAG_LEFT: - case DRAG_RIGHT: - c = CURSOR_HSIZE; - break; - case DRAG_TOP: - case DRAG_BOTTOM: - c = CURSOR_VSIZE; - break; - case DRAG_TOP_LEFT: - case DRAG_BOTTOM_RIGHT: - c = CURSOR_FDIAGSIZE; - break; - case DRAG_TOP_RIGHT: - case DRAG_BOTTOM_LEFT: - c = CURSOR_BDIAGSIZE; - break; - case DRAG_ALL: - case DRAG_NODE_2D: - c = CURSOR_MOVE; - break; - } - viewport->set_default_cursor_shape(c); -} - -void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event) { - +bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> b = p_event; - if (b.is_valid()) { - if (b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { + Ref<InputEventMouseMotion> m = p_event; + + // Start dragging a guide + if (drag_type == DRAG_NONE) { + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { if (show_guides && show_rulers && EditorNode::get_singleton()->get_edited_scene()) { Transform2D xform = viewport_scrollable->get_transform() * transform; // Retrieve the guide lists @@ -1251,48 +694,64 @@ void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event) // Press button if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) { // Drag a new double guide - drag = DRAG_DOUBLE_GUIDE; - edited_guide_index = -1; + drag_type = DRAG_DOUBLE_GUIDE; + dragged_guide_index = -1; + return true; } else if (b->get_position().x < RULER_WIDTH) { // Check if we drag an existing horizontal guide float minimum = 1e20; - edited_guide_index = -1; + dragged_guide_index = -1; for (int i = 0; i < hguides.size(); i++) { if (ABS(xform.xform(Point2(0, hguides[i])).y - b->get_position().y) < MIN(minimum, 8)) { - edited_guide_index = i; + dragged_guide_index = i; } } - if (edited_guide_index >= 0) { + if (dragged_guide_index >= 0) { // Drag an existing horizontal guide - drag = DRAG_H_GUIDE; + drag_type = DRAG_H_GUIDE; } else { // Drag a new vertical guide - drag = DRAG_V_GUIDE; + drag_type = DRAG_V_GUIDE; } + return true; } else if (b->get_position().y < RULER_WIDTH) { // Check if we drag an existing vertical guide float minimum = 1e20; - edited_guide_index = -1; + dragged_guide_index = -1; for (int i = 0; i < vguides.size(); i++) { if (ABS(xform.xform(Point2(vguides[i], 0)).x - b->get_position().x) < MIN(minimum, 8)) { - edited_guide_index = i; + dragged_guide_index = i; } } - if (edited_guide_index >= 0) { + if (dragged_guide_index >= 0) { // Drag an existing vertical guide - drag = DRAG_V_GUIDE; + drag_type = DRAG_V_GUIDE; } else { // Drag a new vertical guide - drag = DRAG_H_GUIDE; + drag_type = DRAG_H_GUIDE; } + drag_from = xform.affine_inverse().xform(b->get_position()); + return true; } } } + } + + if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE || drag_type == DRAG_H_GUIDE) { + // Move the guide + if (m.is_valid()) { + Transform2D xform = viewport_scrollable->get_transform() * transform; + drag_to = xform.affine_inverse().xform(m->get_position()); + + dragged_guide_pos = xform.xform(snap_point(drag_to, SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES)); + viewport->update(); + return true; + } - if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { - // Release button + // Release confirms the guide move + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { if (show_guides && EditorNode::get_singleton()->get_edited_scene()) { Transform2D xform = viewport_scrollable->get_transform() * transform; @@ -1307,65 +766,65 @@ void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event) } Point2 edited = snap_point(xform.affine_inverse().xform(b->get_position()), SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES); - if (drag == DRAG_V_GUIDE) { + if (drag_type == DRAG_V_GUIDE) { Array prev_vguides = vguides.duplicate(); if (b->get_position().x > RULER_WIDTH) { // Adds a new vertical guide - if (edited_guide_index >= 0) { - vguides[edited_guide_index] = edited.x; + if (dragged_guide_index >= 0) { + vguides[dragged_guide_index] = edited.x; undo_redo->create_action(TTR("Move vertical guide")); undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); - undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } else { vguides.push_back(edited.x); undo_redo->create_action(TTR("Create new vertical guide")); undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); - undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } } else { - if (edited_guide_index >= 0) { - vguides.remove(edited_guide_index); + if (dragged_guide_index >= 0) { + vguides.remove(dragged_guide_index); undo_redo->create_action(TTR("Remove vertical guide")); undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); - undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } } - } else if (drag == DRAG_H_GUIDE) { + } else if (drag_type == DRAG_H_GUIDE) { Array prev_hguides = hguides.duplicate(); if (b->get_position().y > RULER_WIDTH) { // Adds a new horizontal guide - if (edited_guide_index >= 0) { - hguides[edited_guide_index] = edited.y; + if (dragged_guide_index >= 0) { + hguides[dragged_guide_index] = edited.y; undo_redo->create_action(TTR("Move horizontal guide")); undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); - undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } else { hguides.push_back(edited.y); undo_redo->create_action(TTR("Create new horizontal guide")); undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); - undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } } else { - if (edited_guide_index >= 0) { - hguides.remove(edited_guide_index); + if (dragged_guide_index >= 0) { + hguides.remove(dragged_guide_index); undo_redo->create_action(TTR("Remove horizontal guide")); undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); - undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } } - } else if (drag == DRAG_DOUBLE_GUIDE) { + } else if (drag_type == DRAG_DOUBLE_GUIDE) { Array prev_hguides = hguides.duplicate(); Array prev_vguides = vguides.duplicate(); if (b->get_position().x > RULER_WIDTH && b->get_position().y > RULER_WIDTH) { @@ -1377,880 +836,1047 @@ void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event) undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); - undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } } } - if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_V_GUIDE || drag == DRAG_H_GUIDE) { - drag = DRAG_NONE; - viewport_base->update(); - } - } - } - - Ref<InputEventMouseMotion> m = p_event; - if (m.is_valid()) { - if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) { - viewport_base->call_deferred("grab_focus"); - } - if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_H_GUIDE || drag == DRAG_V_GUIDE) { - Transform2D xform = viewport_scrollable->get_transform() * transform; - Point2 mouse_pos = m->get_position(); - mouse_pos = xform.affine_inverse().xform(mouse_pos); - mouse_pos = xform.xform(snap_point(mouse_pos, SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES)); - - edited_guide_pos = mouse_pos; - viewport_base->update(); - } - } - - Ref<InputEventKey> k = p_event; - if (k.is_valid()) { - if (k->is_pressed() && drag == DRAG_NONE) { - // Move the object with the arrow keys - KeyMoveMODE move_mode = MOVE_VIEW_BASE; - if (k->get_alt()) move_mode = MOVE_LOCAL_BASE; - if (k->get_control() || k->get_metakey()) move_mode = MOVE_LOCAL_WITH_ROT; - - if (k->get_scancode() == KEY_UP) - _key_move(Vector2(0, -1), k->get_shift(), move_mode); - else if (k->get_scancode() == KEY_DOWN) - _key_move(Vector2(0, 1), k->get_shift(), move_mode); - else if (k->get_scancode() == KEY_LEFT) - _key_move(Vector2(-1, 0), k->get_shift(), move_mode); - else if (k->get_scancode() == KEY_RIGHT) - _key_move(Vector2(1, 0), k->get_shift(), move_mode); - else if (k->get_scancode() == KEY_ESCAPE) { - editor_selection->clear(); - viewport->update(); - } else - return; - - accept_event(); + drag_type = DRAG_NONE; + viewport->update(); + return true; } } + return false; } -void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { - - { - EditorNode *en = editor; - EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); - - if (!over_plugin_list->empty()) { - bool discard = over_plugin_list->forward_gui_input(p_event); - if (discard) { - accept_event(); - return; - } - } - } - - Ref<InputEventMagnifyGesture> magnify_gesture = p_event; - if (magnify_gesture.is_valid()) { - - _zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position()); - return; - } - - Ref<InputEventPanGesture> pan_gesture = p_event; - if (pan_gesture.is_valid()) { - - const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta(); - h_scroll->set_value(h_scroll->get_value() + delta.x); - v_scroll->set_value(v_scroll->get_value() + delta.y); - return; - } - +bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { - // Button event - if (b->get_button_index() == BUTTON_WHEEL_DOWN) { // Scroll or pan down if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) { - v_scroll->set_value(v_scroll->get_value() + int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor()); - _update_scroll(0); + view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); + _update_scrollbars(); viewport->update(); } else { _zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), b->get_position()); } - - return; + return true; } if (b->get_button_index() == BUTTON_WHEEL_UP) { // Scroll or pan up if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) { - v_scroll->set_value(v_scroll->get_value() - int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor()); - _update_scroll(0); + view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); + _update_scrollbars(); viewport->update(); } else { _zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), b->get_position()); } - - return; + return true; } if (b->get_button_index() == BUTTON_WHEEL_LEFT) { // Pan left if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) { - - h_scroll->set_value(h_scroll->get_value() - int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor()); + view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); + _update_scrollbars(); + viewport->update(); + return true; } } if (b->get_button_index() == BUTTON_WHEEL_RIGHT) { // Pan right if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) { + view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); + _update_scrollbars(); + viewport->update(); + return true; + } + } + } - h_scroll->set_value(h_scroll->get_value() + int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor()); + Ref<InputEventMouseMotion> m = p_event; + if (m.is_valid()) { + if (drag_type == DRAG_NONE) { + if (((m->get_button_mask() & BUTTON_MASK_LEFT) && tool == TOOL_PAN) || + (m->get_button_mask() & BUTTON_MASK_MIDDLE) || + ((m->get_button_mask() & BUTTON_MASK_LEFT) && Input::get_singleton()->is_key_pressed(KEY_SPACE)) || + (EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning") && Input::get_singleton()->is_key_pressed(KEY_SPACE))) { + // Pan the viewport + Point2i relative; + if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) { + relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect()); + } else { + relative = m->get_relative(); + } + view_offset.x -= relative.x / zoom; + view_offset.y -= relative.y / zoom; + _update_scrollbars(); + viewport->update(); + return true; } } + } - if (b->get_button_index() == BUTTON_RIGHT) { + Ref<InputEventMagnifyGesture> magnify_gesture = p_event; + if (magnify_gesture.is_valid()) { + // Zoom gesture + _zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position()); + return true; + } - if (b->is_pressed() && (tool == TOOL_SELECT && b->get_alt())) { - // Open the selection list - _list_select(b); - return; - } + Ref<InputEventPanGesture> pan_gesture = p_event; + if (pan_gesture.is_valid()) { + // Pan gesture + const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta(); + view_offset.x += delta.x; + view_offset.y += delta.y; + _update_scrollbars(); + viewport->update(); + return true; + } - if (get_item_count() > 0 && drag != DRAG_NONE) { - // Cancel a drag - if (bone_ik_list.size()) { - for (List<BoneIK>::Element *E = bone_ik_list.back(); E; E = E->prev()) { - E->get().node->_edit_set_state(E->get().orig_state); - } + return false; +} - bone_ik_list.clear(); +bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseMotion> m = p_event; + Ref<InputEventMouseButton> b = p_event; + Ref<InputEventKey> k = p_event; - } else { - List<Node *> selection = editor_selection->get_selected_node_list(); - - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - - CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - if (!se) - continue; - - canvas_item->_edit_set_state(se->undo_state); - if (Object::cast_to<Node2D>(canvas_item)) - Object::cast_to<Node2D>(canvas_item)->_edit_set_pivot(se->undo_pivot); - if (Object::cast_to<Control>(canvas_item)) - Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot); - } + // Drag the pivot (in pivot mode / with V key) + if (drag_type == DRAG_NONE) { + if ((b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || + (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V)) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + + // Filters the selection with nodes that allow setting the pivot + drag_selection = List<CanvasItem *>(); + for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + if (canvas_item->_edit_use_pivot()) { + drag_selection.push_back(canvas_item); } + } - drag = DRAG_NONE; - viewport->update(); - can_move_pivot = false; + // Start dragging if we still have nodes + if (drag_selection.size() > 0) { + drag_from = transform.affine_inverse().xform((b.is_valid()) ? b->get_position() : viewport->get_local_mouse_position()); + Vector2 new_pos; + if (drag_selection.size() == 1) + new_pos = snap_point(drag_from, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, drag_selection[0]); + else + new_pos = snap_point(drag_from, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL); + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos)); + } - } else if (box_selecting) { - // Cancel box selection - box_selecting = false; - viewport->update(); + drag_type = DRAG_PIVOT; + _save_canvas_item_state(drag_selection); } - return; - } - - if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT) { - if (b->is_pressed()) - // Open the selection list - _list_select(b); - return; + return true; } + } - if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) { - if (b->is_pressed()) { - // Set the pivot point - Point2 mouse_pos = b->get_position(); - mouse_pos = transform.affine_inverse().xform(mouse_pos); - mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item()); - _edit_set_pivot(mouse_pos); + if (drag_type == DRAG_PIVOT) { + // Move the pivot + if (m.is_valid()) { + drag_to = transform.affine_inverse().xform(m->get_position()); + _restore_canvas_item_state(drag_selection); + Vector2 new_pos; + if (drag_selection.size() == 1) + new_pos = snap_point(drag_to, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, drag_selection[0]); + else + new_pos = snap_point(drag_to, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL); + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos)); } - return; + return true; } - if (tool == TOOL_PAN || b->get_button_index() != BUTTON_LEFT || Input::get_singleton()->is_key_pressed(KEY_SPACE)) - // Pan the view - return; - - // -- From now we consider that the button is BUTTON_LEFT -- - - if (!b->is_pressed()) { + // Confirm the pivot move + if ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || + (k.is_valid() && !k->is_pressed() && k->get_scancode() == KEY_V)) { + _commit_canvas_item_state(drag_selection, TTR("Move pivot")); + drag_type = DRAG_NONE; + return true; + } - if (drag != DRAG_NONE) { - // Stop dragging - if (undo_redo) { + // Cancel a drag + if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + _restore_canvas_item_state(drag_selection); + drag_type = DRAG_NONE; + viewport->update(); + return true; + } + } + return false; +} - if (bone_ik_list.size()) { - undo_redo->create_action(TTR("Edit IK Chain")); +void CanvasItemEditor::_solve_IK(Node2D *leaf_node, Point2 target_position) { + CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(leaf_node); + if (se && !se->pre_drag_bones_undo_state.empty()) { + + // Build the node list + Point2 leaf_pos = target_position; + + List<Node2D *> joints_list; + List<Point2> joints_pos; + Node2D *joint = leaf_node; + Transform2D joint_transform = leaf_node->get_global_transform_with_canvas(); + for (int i = 0; i < se->pre_drag_bones_undo_state.size() + 1; i++) { + joints_list.push_back(joint); + joints_pos.push_back(joint_transform.get_origin()); + joint_transform = joint_transform * joint->get_transform().affine_inverse(); + joint = Object::cast_to<Node2D>(joint->get_parent()); + } + Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin(); - for (List<BoneIK>::Element *E = bone_ik_list.back(); E; E = E->prev()) { + // Restraints the node to a maximum distance is necessary + float total_len = 0; + for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) { + total_len += E->get(); + } + if ((root_pos.distance_to(leaf_pos)) > total_len) { + Vector2 rel = leaf_pos - root_pos; + rel = rel.normalized() * total_len; + leaf_pos = root_pos + rel; + } + joints_pos[0] = leaf_pos; + + // Run the solver + int solver_iterations = 64; + float solver_k = 0.3; + + // Build the position list + for (int i = 0; i < solver_iterations; i++) { + // Handle the leaf joint + int node_id = 0; + for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) { + Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized(); + int len = E->get(); + if (E == se->pre_drag_bones_length.front()) { + joints_pos[1] = joints_pos[1].linear_interpolate(joints_pos[0] + len * direction, solver_k); + } else if (E == se->pre_drag_bones_length.back()) { + joints_pos[node_id] = joints_pos[node_id].linear_interpolate(joints_pos[node_id + 1] - len * direction, solver_k); + } else { + Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0; + joints_pos[node_id] = joints_pos[node_id].linear_interpolate(center - (direction * len) / 2.0, solver_k); + joints_pos[node_id + 1] = joints_pos[node_id + 1].linear_interpolate(center + (direction * len) / 2.0, solver_k); + } + node_id++; + } + } - undo_redo->add_do_method(E->get().node, "_edit_set_state", E->get().node->_edit_get_state()); - undo_redo->add_undo_method(E->get().node, "_edit_set_state", E->get().orig_state); - } + // Set the position + float total_rot = 0.0f; + for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) { + Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized(); + Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized(); + float rot = current.angle_to(target); + if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) { + rot = -rot; + } + joints_list[node_id]->rotate(rot); + total_rot += rot; + } - undo_redo->add_do_method(viewport, "update"); - undo_redo->add_undo_method(viewport, "update"); + joints_list[0]->rotate(-total_rot); + } +} - bone_ik_list.clear(); +bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> b = p_event; + Ref<InputEventMouseMotion> m = p_event; - undo_redo->commit_action(); - } else { - undo_redo->create_action(TTR("Edit CanvasItem")); - - List<Node *> selection = editor_selection->get_selected_node_list(); - - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - - CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - if (!se) - continue; - - Variant state = canvas_item->_edit_get_state(); - undo_redo->add_do_method(canvas_item, "_edit_set_state", state); - undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state); - { - Node2D *pvt = Object::cast_to<Node2D>(canvas_item); - if (pvt && pvt->_edit_use_pivot()) { - undo_redo->add_do_method(canvas_item, "_edit_set_pivot", pvt->_edit_get_pivot()); - undo_redo->add_undo_method(canvas_item, "_edit_set_pivot", se->undo_pivot); - } - - Control *cnt = Object::cast_to<Control>(canvas_item); - if (cnt) { - undo_redo->add_do_method(canvas_item, "set_pivot_offset", cnt->get_pivot_offset()); - undo_redo->add_undo_method(canvas_item, "set_pivot_offset", se->undo_pivot); - } - } - } - undo_redo->commit_action(); - } + // Start rotation + if (drag_type == DRAG_NONE) { + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { + drag_selection = _get_edited_canvas_items(); + if (drag_selection.size() > 0 && ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE)) { + drag_type = DRAG_ROTATE; + drag_from = transform.affine_inverse().xform(b->get_position()); + CanvasItem *canvas_item = drag_selection[0]; + if (canvas_item->_edit_use_pivot()) { + drag_rotation_center = canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_pivot()); + } else { + drag_rotation_center = canvas_item->get_global_transform_with_canvas().get_origin(); } + _save_canvas_item_state(drag_selection); + return true; + } + } + } - drag = DRAG_NONE; + if (drag_type == DRAG_ROTATE) { + // Rotate the node + if (m.is_valid()) { + _restore_canvas_item_state(drag_selection); + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + drag_to = transform.affine_inverse().xform(m->get_position()); + canvas_item->_edit_set_rotation(snap_angle(canvas_item->_edit_get_rotation() + (drag_from - drag_rotation_center).angle_to(drag_to - drag_rotation_center), canvas_item->_edit_get_rotation())); viewport->update(); - can_move_pivot = false; } + return true; + } - if (box_selecting) { - // Stop box selection - Node *scene = editor->get_edited_scene(); - if (scene) { - - List<CanvasItem *> selitems; - - Point2 bsfrom = transform.xform(drag_from); - Point2 bsto = transform.xform(box_selecting_to); - if (bsfrom.x > bsto.x) - SWAP(bsfrom.x, bsto.x); - if (bsfrom.y > bsto.y) - SWAP(bsfrom.y, bsto.y); - - _find_canvas_items_at_rect(Rect2(bsfrom, bsto - bsfrom), scene, transform, Transform2D(), &selitems); + // Confirms the node rotation + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + _commit_canvas_item_state(drag_selection, TTR("Rotate CanvasItem")); + drag_type = DRAG_NONE; + return true; + } - for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) { + // Cancel a drag + if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + _restore_canvas_item_state(drag_selection); + drag_type = DRAG_NONE; + viewport->update(); + return true; + } + } + return false; +} - _append_canvas_item(E->get()); - } - } +bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> b = p_event; - box_selecting = false; - viewport->update(); + // Open a sub-scene on double-click + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && b->is_doubleclick() && tool == TOOL_SELECT) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + if (selection.size() == 1) { + CanvasItem *canvas_item = selection[0]; + if (canvas_item->get_filename() != "" && canvas_item != editor->get_edited_scene()) { + editor->open_request(canvas_item->get_filename()); + return true; } - return; } + } + return false; +} - // -- From now we consider that the button is BUTTON_LEFT and that it is pressed -- +bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> b = p_event; + Ref<InputEventMouseMotion> m = p_event; - Map<ObjectID, BoneList>::Element *Cbone = NULL; //closest + // Starts anchor dragging if needed + if (drag_type == DRAG_NONE) { + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT && show_helpers) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + if (selection.size() == 1) { + Control *control = Object::cast_to<Control>(selection[0]); + if (control && !Object::cast_to<Container>(control->get_parent())) { + Vector2 anchor_pos[4]; + anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP)); + anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP)); + anchor_pos[2] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_BOTTOM)); + anchor_pos[3] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_BOTTOM)); - { - bone_ik_list.clear(); - float closest_dist = 1e20; - int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width"); - for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) { + Rect2 anchor_rects[4]; + for (int i = 0; i < 4; i++) { + anchor_pos[i] = (transform * control->get_global_transform_with_canvas()).xform(_anchor_to_position(control, anchor_pos[i])); + anchor_rects[i] = Rect2(anchor_pos[i], anchor_handle->get_size()); + anchor_rects[i].position -= anchor_handle->get_size() * Vector2(i == 0 || i == 3, i <= 1); + } - if (E->get().from == E->get().to) - continue; - Vector2 s[2] = { - E->get().from, - E->get().to - }; + DragType dragger[] = { + DRAG_ANCHOR_TOP_LEFT, + DRAG_ANCHOR_TOP_RIGHT, + DRAG_ANCHOR_BOTTOM_RIGHT, + DRAG_ANCHOR_BOTTOM_LEFT, + }; - Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_position(), s); - float d = p.distance_to(b->get_position()); - if (d < bone_width && d < closest_dist) { - Cbone = E; - closest_dist = d; + for (int i = 0; i < 4; i++) { + if (anchor_rects[i].has_point(b->get_position())) { + if ((anchor_pos[0] == anchor_pos[2]) && (anchor_pos[0].distance_to(b->get_position()) < anchor_handle->get_size().length() / 3.0)) { + drag_type = DRAG_ANCHOR_ALL; + } else { + drag_type = dragger[i]; + } + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = List<CanvasItem *>(); + drag_selection.push_back(control); + _save_canvas_item_state(drag_selection); + return true; + } + } } } + } + } - if (Cbone) { - Node2D *b = Object::cast_to<Node2D>(ObjectDB::get_instance(Cbone->get().bone)); + if (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT || drag_type == DRAG_ANCHOR_BOTTOM_RIGHT || drag_type == DRAG_ANCHOR_BOTTOM_LEFT || drag_type == DRAG_ANCHOR_ALL) { + // Drag the anchor + if (m.is_valid()) { + _restore_canvas_item_state(drag_selection); + Control *control = Object::cast_to<Control>(drag_selection[0]); - if (b) { + drag_to = transform.affine_inverse().xform(m->get_position()); - bool ik_found = false; + Transform2D xform = control->get_global_transform_with_canvas().affine_inverse(); - bool first = true; + Point2 previous_anchor; + previous_anchor.x = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_BOTTOM_LEFT) ? control->get_anchor(MARGIN_LEFT) : control->get_anchor(MARGIN_RIGHT); + previous_anchor.y = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT) ? control->get_anchor(MARGIN_TOP) : control->get_anchor(MARGIN_BOTTOM); + previous_anchor = xform.affine_inverse().xform(_anchor_to_position(control, previous_anchor)); - while (b) { + Vector2 new_anchor = xform.xform(snap_point(previous_anchor + (drag_to - drag_from), SNAP_GRID | SNAP_OTHER_NODES, control, SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER)); + new_anchor = _position_to_anchor(control, new_anchor).snapped(Vector2(0.001, 0.001)); - CanvasItem *pi = b->get_parent_item(); - if (!pi) - break; + bool use_single_axis = m->get_shift(); + Vector2 drag_vector = xform.xform(drag_to) - xform.xform(drag_from); + bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x); - float len = pi->get_global_transform().get_origin().distance_to(b->get_global_position()); - b = Object::cast_to<Node2D>(pi); - if (!b) - break; + switch (drag_type) { + case DRAG_ANCHOR_TOP_LEFT: + if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false); + if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_TOP, new_anchor.y, false, false); + break; + case DRAG_ANCHOR_TOP_RIGHT: + if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false); + if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_TOP, new_anchor.y, false, false); + break; + case DRAG_ANCHOR_BOTTOM_RIGHT: + if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false); + if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false); + break; + case DRAG_ANCHOR_BOTTOM_LEFT: + if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false); + if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false); + break; + case DRAG_ANCHOR_ALL: + if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true); + if (!use_single_axis || (use_single_axis && !use_y)) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true); + if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_TOP, new_anchor.y, false, true); + if (!use_single_axis || (use_single_axis && use_y)) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true); + break; + default: + break; + } + return true; + } - if (first) { + // Confirms new anchor position + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + _commit_canvas_item_state(drag_selection, TTR("Move anchor")); + drag_type = DRAG_NONE; + return true; + } - bone_orig_xform = b->get_global_transform(); - first = false; - } + // Cancel a drag + if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + _restore_canvas_item_state(drag_selection); + drag_type = DRAG_NONE; + viewport->update(); + return true; + } + } + return false; +} - BoneIK bik; - bik.node = b; - bik.len = len; - bik.orig_state = b->_edit_get_state(); +bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> b = p_event; + Ref<InputEventMouseMotion> m = p_event; - bone_ik_list.push_back(bik); + // Drag resize handles + if (drag_type == DRAG_NONE) { + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + if (selection.size() == 1) { + CanvasItem *canvas_item = selection[0]; + + Rect2 rect = canvas_item->_edit_get_rect(); + Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); + + Vector2 endpoints[4] = { + xform.xform(rect.position), + xform.xform(rect.position + Vector2(rect.size.x, 0)), + xform.xform(rect.position + rect.size), + xform.xform(rect.position + Vector2(0, rect.size.y)) + }; - if (b->has_meta("_edit_ik_")) { + DragType dragger[] = { + DRAG_TOP_LEFT, + DRAG_TOP, + DRAG_TOP_RIGHT, + DRAG_RIGHT, + DRAG_BOTTOM_RIGHT, + DRAG_BOTTOM, + DRAG_BOTTOM_LEFT, + DRAG_LEFT + }; - ik_found = bone_ik_list.size() > 1; - break; - } + DragType resize_drag = DRAG_NONE; + float radius = (select_handle->get_size().width / 2) * 1.5; - if (!pi->has_meta("_edit_bone_")) - break; - } + for (int i = 0; i < 4; i++) { + int prev = (i + 3) % 4; + int next = (i + 1) % 4; + + Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized(); + ofs *= (select_handle->get_size().width / 2); + ofs += endpoints[i]; + if (ofs.distance_to(b->get_position()) < radius) + resize_drag = dragger[i * 2]; + + ofs = (endpoints[i] + endpoints[next]) / 2; + ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2); + if (ofs.distance_to(b->get_position()) < radius) + resize_drag = dragger[i * 2 + 1]; + } - if (!ik_found) - bone_ik_list.clear(); + if (resize_drag != DRAG_NONE) { + drag_type = resize_drag; + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = List<CanvasItem *>(); + drag_selection.push_back(canvas_item); + _save_canvas_item_state(drag_selection); + return true; } } } + } - // Single selected item - CanvasItem *canvas_item = _get_single_item(); - if (canvas_item) { + if (drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM || + drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) { + // Resize the node + if (m.is_valid()) { + CanvasItem *canvas_item = drag_selection[0]; CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - ERR_FAIL_COND(!se); - - Point2 click = b->get_position(); - - // Rotation - if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { - drag = DRAG_ROTATE; - drag_from = transform.affine_inverse().xform(click); - se->undo_state = canvas_item->_edit_get_state(); - if (Object::cast_to<Node2D>(canvas_item)) - se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot(); - if (Object::cast_to<Control>(canvas_item)) - se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset(); - se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); - se->pre_drag_rect = canvas_item->_edit_get_rect(); - return; - } + //Reset state + canvas_item->_edit_set_state(se->undo_state); - if (tool == TOOL_SELECT) { - // Open a sub-scene on double-click - if (b->is_doubleclick()) { - if (canvas_item->get_filename() != "" && canvas_item != editor->get_edited_scene()) { - editor->open_request(canvas_item->get_filename()); - return; - } - } + bool uniform = m->get_shift(); + bool symmetric = m->get_alt(); - // Drag resize handles - drag = _get_resize_handle_drag_type(click, drag_point_from); - if (drag != DRAG_NONE) { - drag_from = transform.affine_inverse().xform(click); - se->undo_state = canvas_item->_edit_get_state(); - if (Object::cast_to<Node2D>(canvas_item)) - se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->_edit_get_pivot(); - if (Object::cast_to<Control>(canvas_item)) - se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset(); - se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); - se->pre_drag_rect = canvas_item->_edit_get_rect(); - return; - } + Rect2 local_rect = canvas_item->_edit_get_rect(); + float aspect = local_rect.get_size().y / local_rect.get_size().x; + Point2 current_begin = local_rect.get_position(); + Point2 current_end = local_rect.get_position() + local_rect.get_size(); + Point2 max_begin = (symmetric) ? (current_begin + current_end - canvas_item->_edit_get_minimum_size()) / 2.0 : current_end - canvas_item->_edit_get_minimum_size(); + Point2 min_end = (symmetric) ? (current_begin + current_end + canvas_item->_edit_get_minimum_size()) / 2.0 : current_begin + canvas_item->_edit_get_minimum_size(); + Point2 center = (current_begin + current_end) / 2.0; + + drag_to = transform.affine_inverse().xform(m->get_position()); + + Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse(); + + Point2 drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, canvas_item); + Point2 drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, canvas_item); + Point2 drag_begin = xform.xform(drag_to_snapped_begin); + Point2 drag_end = xform.xform(drag_to_snapped_end); + + // Horizontal resize + if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) { + current_begin.x = MIN(drag_begin.x, max_begin.x); + } else if (drag_type == DRAG_RIGHT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_RIGHT) { + current_end.x = MAX(drag_end.x, min_end.x); + } + + // Vertical resize + if (drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) { + current_begin.y = MIN(drag_begin.y, max_begin.y); + } else if (drag_type == DRAG_BOTTOM || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) { + current_end.y = MAX(drag_end.y, min_end.y); + } - // Drag anchor handles - Control *control = Object::cast_to<Control>(canvas_item); - if (control && show_helpers && !Object::cast_to<Container>(control->get_parent())) { - drag = _get_anchor_handle_drag_type(click, drag_point_from); - if (drag != DRAG_NONE) { - drag_from = transform.affine_inverse().xform(click); - se->undo_state = canvas_item->_edit_get_state(); - se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); - se->pre_drag_rect = canvas_item->_edit_get_rect(); - return; + // Uniform resize + if (uniform) { + if (drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT) { + current_end.y = current_begin.y + aspect * (current_end.x - current_begin.x); + } else if (drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM) { + current_end.x = current_begin.x + (current_end.y - current_begin.y) / aspect; + } else { + if (aspect >= 1.0) { + if (drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) { + current_begin.y = current_end.y - aspect * (current_end.x - current_begin.x); + } else { + current_end.y = current_begin.y + aspect * (current_end.x - current_begin.x); + } + } else { + if (drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) { + current_begin.x = current_end.x - (current_end.y - current_begin.y) / aspect; + } else { + current_end.x = current_begin.x + (current_end.y - current_begin.y) / aspect; + } } } } - } - - // Multiple selected items - Point2 click = b->get_position(); - - if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) { - // Drag the nodes - _prepare_drag(click); - viewport->update(); - return; - } - - CanvasItem *c = NULL; - if (Cbone) { - c = Object::cast_to<CanvasItem>(ObjectDB::get_instance(Cbone->get().bone)); - if (c) - c = c->get_parent_item(); - } - - Node *scene = editor->get_edited_scene(); - if (!scene) - return; - // Find the item to select - if (!c) { - Vector<_SelectResult> selection; - _find_canvas_items_at_pos(click, scene, transform, Transform2D(), selection, 1); - if (!selection.empty()) - c = selection[0].item; - CanvasItem *cn = c; - while (cn) { - if (cn->has_meta("_edit_group_")) { - c = cn; + // Symmetric resize + if (symmetric) { + if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) { + current_end.x = 2.0 * center.x - current_begin.x; + } else if (drag_type == DRAG_RIGHT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_RIGHT) { + current_begin.x = 2.0 * center.x - current_end.x; + } + if (drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) { + current_end.y = 2.0 * center.y - current_begin.y; + } else if (drag_type == DRAG_BOTTOM || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) { + current_begin.y = 2.0 * center.y - current_end.y; } - cn = cn->get_parent_item(); } + canvas_item->_edit_set_rect(Rect2(current_begin, current_end - current_begin)); + return true; } - Node *n = c; - while ((n && n != scene && n->get_owner() != scene) || (n && !n->is_class("CanvasItem"))) { - n = n->get_parent(); - }; - - if (n) { - c = Object::cast_to<CanvasItem>(n); - } else { - c = NULL; + // Confirm resize + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + _commit_canvas_item_state(drag_selection, TTR("Resize CanvasItem")); + drag_type = DRAG_NONE; + viewport->update(); + return true; } - // Select the item - additive_selection = b->get_shift(); - if (!c) { - _select_click_on_empty_area(click, additive_selection, true); - } else if (!_select_click_on_item(c, click, additive_selection, true)) { - return; + // Cancel a drag + if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + _restore_canvas_item_state(drag_selection); + drag_type = DRAG_NONE; + viewport->update(); + return true; } } + return false; +} +bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> b = p_event; Ref<InputEventMouseMotion> m = p_event; - if (m.is_valid()) { - // Mouse motion event - _update_cursor(); - - if (box_selecting) { - // Update box selection - box_selecting_to = transform.affine_inverse().xform(m->get_position()); - viewport->update(); - return; - } - - if (drag == DRAG_NONE) { - bool space_pressed = Input::get_singleton()->is_key_pressed(KEY_SPACE); - bool simple_panning = EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning"); - int button = m->get_button_mask(); - - // Check if any of the panning triggers are activated - bool panning_tool = (button & BUTTON_MASK_LEFT) && tool == TOOL_PAN; - bool panning_middle_button = button & BUTTON_MASK_MIDDLE; - bool panning_spacebar = (button & BUTTON_MASK_LEFT) && space_pressed; - bool panning_spacebar_simple = space_pressed && simple_panning; - - if (panning_tool || panning_middle_button || panning_spacebar || panning_spacebar_simple) { - // Pan the viewport - Point2i relative; - if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) { - relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect()); - } else { - relative = m->get_relative(); - } + Ref<InputEventKey> k = p_event; - h_scroll->set_value(h_scroll->get_value() - relative.x / zoom); - v_scroll->set_value(v_scroll->get_value() - relative.y / zoom); + if (drag_type == DRAG_NONE) { + //Start moving the nodes + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + if ((b->get_alt() || tool == TOOL_MOVE) && selection.size() > 0) { + drag_type = DRAG_ALL; + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = selection; + _save_canvas_item_state(drag_selection); + return true; } - - return; } + } - List<Node *> selection = editor_selection->get_selected_node_list(); - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - - CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - if (!se) - continue; - - bool dragging_bone = drag == DRAG_ALL && selection.size() == 1 && bone_ik_list.size(); + if (drag_type == DRAG_ALL) { + // Move the nodes + if (m.is_valid()) { + _restore_canvas_item_state(drag_selection, true); - if (!dragging_bone) { - canvas_item->_edit_set_state(se->undo_state); //reset state and reapply - if (Object::cast_to<Node2D>(canvas_item)) - Object::cast_to<Node2D>(canvas_item)->_edit_set_pivot(se->undo_pivot); - if (Object::cast_to<Control>(canvas_item)) - Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot); + drag_to = transform.affine_inverse().xform(m->get_position()); + Point2 previous_pos; + if (drag_selection.size() == 1) { + Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse(); + previous_pos = xform.xform(drag_selection[0]->_edit_get_position()); + } else { + previous_pos = _get_encompassing_rect_from_list(drag_selection).position; } - - Vector2 dfrom = drag_from; - Vector2 dto = transform.affine_inverse().xform(m->get_position()); - if (canvas_item->has_meta("_edit_lock_")) - continue; - - if (drag == DRAG_ROTATE) { - // Rotate the node - Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin(); - { - Node2D *node = Object::cast_to<Node2D>(canvas_item); - - if (node) { - real_t angle = node->get_rotation(); - node->set_rotation(snap_angle(angle + (dfrom - center).angle_to(dto - center), angle)); - display_rotate_to = dto; - display_rotate_from = center; - viewport->update(); - } + Point2 new_pos = snap_point(previous_pos + (drag_to - drag_from), SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL | SNAP_NODE_PARENT | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES); + bool single_axis = m->get_shift(); + if (single_axis) { + if (ABS(new_pos.x - previous_pos.x) > ABS(new_pos.y - previous_pos.y)) { + new_pos.y = previous_pos.y; + } else { + new_pos.x = previous_pos.x; } + } - { - Control *node = Object::cast_to<Control>(canvas_item); + bool force_no_IK = m->get_alt(); + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); + Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); - if (node) { - real_t angle = node->get_rotation(); - display_rotate_to = dto; - display_rotate_from = center + node->get_pivot_offset().rotated(angle); - node->set_rotation(snap_angle(angle + (dfrom - display_rotate_from).angle_to(display_rotate_to - display_rotate_from), angle)); - viewport->update(); - } + Node2D *node2d = Object::cast_to<Node2D>(canvas_item); + if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) { + _solve_IK(node2d, new_pos); + } else { + canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); } - - continue; } + return true; + } - bool uniform = m->get_shift(); - bool symmetric = m->get_alt(); - - Vector2 drag_vector = - canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) - - canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom); - - switch (drag) { - case DRAG_ALL: - case DRAG_NODE_2D: - dto -= drag_from - drag_point_from; - if (uniform) { - if (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) { - dto.y = drag_point_from.y; - } else { - dto.x = drag_point_from.x; - } - } - break; + // Confirm the move (only if it was moved) + if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && (drag_type == DRAG_ALL)) { + if (transform.affine_inverse().xform(b->get_position()) != drag_from) { + _commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true); } - Control *control = Object::cast_to<Control>(canvas_item); - if (control) { - // Drag and snap the anchor - Transform2D c_trans_rev = canvas_item->get_global_transform_with_canvas().affine_inverse(); + drag_type = DRAG_NONE; + viewport->update(); + return true; + } - Vector2 anchor = c_trans_rev.xform(dto - drag_from + drag_point_from); - anchor = _position_to_anchor(control, anchor); + // Cancel a drag + if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + _restore_canvas_item_state(drag_selection, true); + drag_type = DRAG_NONE; + viewport->update(); + return true; + } + } - Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | SNAP_GUIDES | SNAP_OTHER_NODES, _get_single_item(), SNAP_NODE_PARENT | SNAP_NODE_SIDES)); - anchor_snapped = _position_to_anchor(control, anchor_snapped).snapped(Vector2(0.00001, 0.00001)); + // Move the canvas items with the arrow keys + if (k.is_valid() && k->is_pressed() && tool == TOOL_SELECT && + (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) { + if (!k->is_echo()) { + // Start moving the canvas items with the keyboard + drag_selection = _get_edited_canvas_items(); + drag_type = DRAG_KEY_MOVE; + drag_from = Vector2(); + drag_to = Vector2(); + _save_canvas_item_state(drag_selection, true); + } - bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x); + _restore_canvas_item_state(drag_selection, true); + + bool move_local_base = k->get_alt(); + bool move_local_base_rotated = k->get_control() || k->get_metakey(); + + Vector2 dir; + if (k->get_scancode() == KEY_UP) + dir += Vector2(0, -1); + else if (k->get_scancode() == KEY_DOWN) + dir += Vector2(0, 1); + else if (k->get_scancode() == KEY_LEFT) + dir += Vector2(-1, 0); + else if (k->get_scancode() == KEY_RIGHT) + dir += Vector2(1, 0); + if (k->get_shift()) + dir *= grid_step * Math::pow(2.0, grid_step_multiplier); + + drag_to += dir; + if (k->get_shift()) + drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier)); + + Point2 previous_pos; + if (drag_selection.size() == 1) { + Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse(); + previous_pos = xform.xform(drag_selection[0]->_edit_get_position()); + } else { + previous_pos = _get_encompassing_rect_from_list(drag_selection).position; + } - switch (drag) { - case DRAG_ANCHOR_TOP_LEFT: - if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x, false); - if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y, false); - continue; - break; - case DRAG_ANCHOR_TOP_RIGHT: - if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x, false); - if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y, false); - continue; - break; - case DRAG_ANCHOR_BOTTOM_RIGHT: - if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x, false); - if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y, false); - break; - case DRAG_ANCHOR_BOTTOM_LEFT: - if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x, false); - if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y, false); - continue; - break; - case DRAG_ANCHOR_ALL: - if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x, false); - if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x, false); - if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y, false); - if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y, false); - continue; - break; - } + Point2 new_pos; + 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); + } else if (move_local_base) { + new_pos += drag_to; + } else { + new_pos = previous_pos + (drag_to - drag_from); } + } else { + new_pos = previous_pos + (drag_to - drag_from); + } - dfrom = drag_point_from; - dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL, _get_single_item()); - - drag_vector = - canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) - - canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom); - - Rect2 local_rect = canvas_item->_edit_get_rect(); - Vector2 begin = local_rect.position; - Vector2 end = local_rect.position + local_rect.size; - Vector2 minsize = canvas_item->_edit_get_minimum_size(); + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); + Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); - if (uniform) { - // Keep the height/width ratio of the item - float aspect = local_rect.size.aspect(); - switch (drag) { - case DRAG_LEFT: - drag_vector.y = -drag_vector.x / aspect; - break; - case DRAG_RIGHT: - drag_vector.y = drag_vector.x / aspect; - break; - case DRAG_TOP: - drag_vector.x = -drag_vector.y * aspect; - break; - case DRAG_BOTTOM: - drag_vector.x = drag_vector.y * aspect; - break; - case DRAG_BOTTOM_LEFT: - case DRAG_TOP_RIGHT: - if (aspect > 1.0) { // width > height, take x as reference - drag_vector.y = -drag_vector.x / aspect; - } else { // height > width, take y as reference - drag_vector.x = -drag_vector.y * aspect; - } - break; - case DRAG_BOTTOM_RIGHT: - case DRAG_TOP_LEFT: - if (aspect > 1.0) { // width > height, take x as reference - drag_vector.y = drag_vector.x / aspect; - } else { // height > width, take y as reference - drag_vector.x = drag_vector.y * aspect; - } - break; - } + Node2D *node2d = Object::cast_to<Node2D>(canvas_item); + if (node2d && se->pre_drag_bones_undo_state.size() > 0) { + _solve_IK(node2d, new_pos); } else { - switch (drag) { - case DRAG_RIGHT: - case DRAG_LEFT: - drag_vector.y = 0; - break; - case DRAG_TOP: - case DRAG_BOTTOM: - drag_vector.x = 0; - break; - } + canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); } + } + return true; + } - switch (drag) { - case DRAG_ALL: - begin += drag_vector; - end += drag_vector; - break; - case DRAG_RIGHT: - case DRAG_BOTTOM: - case DRAG_BOTTOM_RIGHT: - incend(begin.x, end.x, drag_vector.x, minsize.x, symmetric); - incend(begin.y, end.y, drag_vector.y, minsize.y, symmetric); - break; - case DRAG_TOP_LEFT: - incbeg(begin.x, end.x, drag_vector.x, minsize.x, symmetric); - incbeg(begin.y, end.y, drag_vector.y, minsize.y, symmetric); - break; - case DRAG_TOP: - case DRAG_TOP_RIGHT: - incbeg(begin.y, end.y, drag_vector.y, minsize.y, symmetric); - incend(begin.x, end.x, drag_vector.x, minsize.x, symmetric); - break; - case DRAG_LEFT: - case DRAG_BOTTOM_LEFT: - incbeg(begin.x, end.x, drag_vector.x, minsize.x, symmetric); - incend(begin.y, end.y, drag_vector.y, minsize.y, symmetric); - break; + if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && tool == TOOL_SELECT && + (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) { + // Confirm canvas items move by arrow keys + if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) && + (!Input::get_singleton()->is_key_pressed(KEY_DOWN)) && + (!Input::get_singleton()->is_key_pressed(KEY_LEFT)) && + (!Input::get_singleton()->is_key_pressed(KEY_RIGHT))) { + _commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true); + drag_type = DRAG_NONE; + } + viewport->update(); + return true; + } - case DRAG_PIVOT: + if (k.is_valid() && (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) { + // Accept the key event in any case + return true; + } + return false; +} - if (Object::cast_to<Node2D>(canvas_item)) { - Node2D *n2d = Object::cast_to<Node2D>(canvas_item); - n2d->_edit_set_pivot(se->undo_pivot + drag_vector); - } - if (Object::cast_to<Control>(canvas_item)) { - Object::cast_to<Control>(canvas_item)->set_pivot_offset(se->undo_pivot + drag_vector); - } - continue; - break; - case DRAG_NODE_2D: +bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> b = p_event; + Ref<InputEventMouseMotion> m = p_event; + Ref<InputEventKey> k = p_event; - ERR_FAIL_COND(!Object::cast_to<Node2D>(canvas_item)); - Object::cast_to<Node2D>(canvas_item)->set_global_position(dto); - continue; - break; + if (drag_type == DRAG_NONE) { + if (b.is_valid() && + ((b->get_button_index() == BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) || + (b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT))) { + // Popup the selection menu list + Point2 click = transform.affine_inverse().xform(b->get_position()); + + Node *scene = editor->get_edited_scene(); + + _find_canvas_items_at_pos(click, scene, selection_results); + for (int i = 0; i < selection_results.size(); i++) { + CanvasItem *item = selection_results[i].item; + if (item != scene && item->get_owner() != scene && !scene->is_editable_instance(item->get_owner())) { + //invalid result + selection_results.remove(i); + i--; + } } - if (!dragging_bone) { - - local_rect.position = begin; - local_rect.size = end - begin; - canvas_item->_edit_set_rect(local_rect); - - } else { - //ok, all that had to be done was done, now solve IK + if (selection_results.size() == 1) { + CanvasItem *item = selection_results[0].item; + selection_results.clear(); - Node2D *n2d = Object::cast_to<Node2D>(canvas_item); - Transform2D final_xform = bone_orig_xform; + _select_click_on_item(item, click, b->get_shift()); - if (n2d) { + return true; + } else if (!selection_results.empty()) { + selection_results.sort(); - float total_len = 0; - for (List<BoneIK>::Element *E = bone_ik_list.front(); E; E = E->next()) { - if (E->prev()) - total_len += E->get().len; - E->get().pos = E->get().node->get_global_transform().get_origin(); - } + NodePath root_path = get_tree()->get_edited_scene_root()->get_path(); + StringName root_name = root_path.get_name(root_path.get_name_count() - 1); - { + for (int i = 0; i < selection_results.size(); i++) { + CanvasItem *item = selection_results[i].item; - final_xform.elements[2] += dto - dfrom; //final_xform.affine_inverse().basis_xform_inv(drag_vector); - //n2d->set_global_transform(final_xform); - } + Ref<Texture> icon; + if (item->has_meta("_editor_icon")) + icon = item->get_meta("_editor_icon"); + else + icon = get_icon(has_icon(item->get_class(), "EditorIcons") ? item->get_class() : String("Object"), "EditorIcons"); + String node_path = "/" + root_name + "/" + root_path.rel_path_to(item->get_path()); - CanvasItem *last = bone_ik_list.back()->get().node; - if (!last) - break; + selection_menu->add_item(item->get_name()); + selection_menu->set_item_icon(i, icon); + selection_menu->set_item_metadata(i, node_path); + selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path); + } - Vector2 root_pos = last->get_global_transform().get_origin(); - Vector2 leaf_pos = final_xform.get_origin(); + selection_menu_additive_selection = b->get_shift(); + selection_menu->set_global_position(b->get_global_position()); + selection_menu->popup(); + selection_menu->call_deferred("grab_click_focus"); + selection_menu->set_invalidate_click_until_motion(); + return true; + } + } - if ((leaf_pos.distance_to(root_pos)) > total_len) { - //oops dude you went too far - //print_line("TOO FAR!"); - Vector2 rel = leaf_pos - root_pos; - rel = rel.normalized() * total_len; - leaf_pos = root_pos + rel; - } + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { + // Single item selection + Point2 click = transform.affine_inverse().xform(b->get_position()); - bone_ik_list.front()->get().pos = leaf_pos; + Node *scene = editor->get_edited_scene(); + if (!scene) + return true; - //print_line("BONE IK LIST "+itos(bone_ik_list.size())); + // Find the item to select + CanvasItem *canvas_item = NULL; + Vector<_SelectResult> selection; + _find_canvas_items_at_pos(click, scene, selection, editor_selection->get_selection().empty() ? 1 : 0); - if (bone_ik_list.size() > 2) { - int solver_iterations = 64; - float solver_k = 0.3; + for (int i = 0; i < selection.size(); i++) { + if (editor_selection->is_selected(selection[i].item)) { + // Drag the node(s) if requested + List<CanvasItem *> selection = _get_edited_canvas_items(); - for (int i = 0; i < solver_iterations; i++) { + drag_type = DRAG_ALL; + drag_selection = selection; + drag_from = click; + _save_canvas_item_state(drag_selection); - for (List<BoneIK>::Element *E = bone_ik_list.front(); E; E = E->next()) { + return true; + } + } - if (E == bone_ik_list.back()) { + if (!selection.empty()) + canvas_item = selection[0].item; - break; - } + // Check if the canvas item is in a group, and select the group instead if it is the case + CanvasItem *canvas_item_tmp = canvas_item; + while (canvas_item_tmp) { + if (canvas_item->has_meta("_edit_group_")) { + canvas_item = canvas_item_tmp; + } + canvas_item_tmp = canvas_item_tmp->get_parent_item(); + } - float len = E->next()->get().len; + // Make sure the selected node is in the current scene + Node *node = canvas_item; + while (node && ((node != scene && node->get_owner() != scene) || !node->is_class("CanvasItem"))) { + node = node->get_parent(); + }; + canvas_item = Object::cast_to<CanvasItem>(node); - if (E->next() == bone_ik_list.back()) { + if (!canvas_item) { + // Start a box selection + if (!b->get_shift()) { + // Clear the selection if not additive + editor_selection->clear(); + viewport->update(); + }; - //print_line("back"); + drag_from = click; + drag_type = DRAG_BOX_SELECTION; + box_selecting_to = drag_from; + return true; + } else { + bool still_selected = _select_click_on_item(canvas_item, click, b->get_shift()); + // Start dragging + if (still_selected) { + // Drag the node(s) if requested + List<CanvasItem *> selection = _get_edited_canvas_items(); + + drag_type = DRAG_ALL; + drag_selection = selection; + drag_from = click; + _save_canvas_item_state(drag_selection); + } + // Select the item + return true; + } + } + } - Vector2 rel = E->get().pos - E->next()->get().pos; - //print_line("PREV "+E->get().pos); - Vector2 desired = E->next()->get().pos + rel.normalized() * len; - //print_line("DESIRED "+desired); - E->get().pos = E->get().pos.linear_interpolate(desired, solver_k); - //print_line("POST "+E->get().pos); + if (drag_type == DRAG_BOX_SELECTION) { + if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) { + // Confirms box selection + Node *scene = editor->get_edited_scene(); + if (scene) { + List<CanvasItem *> selitems; - } else if (E == bone_ik_list.front()) { - //only adjust parent - //print_line("front"); - Vector2 rel = E->next()->get().pos - E->get().pos; - //print_line("PREV "+E->next()->get().pos); - Vector2 desired = E->get().pos + rel.normalized() * len; - //print_line("DESIRED "+desired); - E->next()->get().pos = E->next()->get().pos.linear_interpolate(desired, solver_k); - //print_line("POST "+E->next()->get().pos); - } else { + Point2 bsfrom = drag_from; + Point2 bsto = box_selecting_to; + if (bsfrom.x > bsto.x) + SWAP(bsfrom.x, bsto.x); + if (bsfrom.y > bsto.y) + SWAP(bsfrom.y, bsto.y); - Vector2 rel = E->next()->get().pos - E->get().pos; - Vector2 cen = (E->next()->get().pos + E->get().pos) * 0.5; - rel = rel.linear_interpolate(rel.normalized() * len, solver_k); - rel *= 0.5; - E->next()->get().pos = cen + rel; - E->get().pos = cen - rel; - //print_line("mid"); - } - } - } - } + _find_canvas_items_at_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems); + for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) { + editor_selection->add_node(E->get()); } + } - for (List<BoneIK>::Element *E = bone_ik_list.back(); E; E = E->prev()) { + drag_type = DRAG_NONE; + viewport->update(); + return true; + } - Node2D *n = E->get().node; + if (b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) { + // Cancel box selection + drag_type = DRAG_NONE; + viewport->update(); + return true; + } - if (!E->prev()) { - //last goes to what it was - final_xform.set_origin(n->get_global_position()); - n->set_global_transform(final_xform); + if (m.is_valid()) { + // Update box selection + box_selecting_to = transform.affine_inverse().xform(m->get_position()); + viewport->update(); + return true; + } + } - } else { - Vector2 rel = (E->prev()->get().node->get_global_position() - n->get_global_position()).normalized(); - Vector2 rel2 = (E->prev()->get().pos - E->get().pos).normalized(); - float rot = rel.angle_to(rel2); - if (n->get_global_transform().basis_determinant() < 0) { - //mirrored, rotate the other way - rot = -rot; - } + if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) { + // Unselect everything + editor_selection->clear(); + viewport->update(); + } + return false; +} - n->rotate(rot); - } +void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { + bool accepted = false; + if ((accepted = _gui_input_rulers_and_guides(p_event))) { + //printf("Rulers and guides\n"); + } else if ((accepted = editor->get_editor_plugins_over()->forward_gui_input(p_event))) { + //printf("Plugin\n"); + } else if ((accepted = _gui_input_open_scene_on_double_click(p_event))) { + //printf("Open scene on double click\n"); + } else if ((accepted = _gui_input_anchors(p_event))) { + //printf("Anchors\n"); + } else if ((accepted = _gui_input_pivot(p_event))) { + //printf("Set pivot\n"); + } else if ((accepted = _gui_input_resize(p_event))) { + //printf("Resize\n"); + } else if ((accepted = _gui_input_rotate(p_event))) { + //printf("Rotate\n"); + } else if ((accepted = _gui_input_move(p_event))) { + //printf("Move\n"); + } else if ((accepted = _gui_input_select(p_event))) { + //printf("Selection\n"); + } else if ((accepted = _gui_input_zoom_or_pan(p_event))) { + //printf("Zoom or pan\n"); + } + + if (accepted) + accept_event(); + + // Change the cursor + CursorShape c = CURSOR_ARROW; + switch (drag_type) { + case DRAG_NONE: + if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + c = CURSOR_DRAG; + } else { + switch (tool) { + case TOOL_MOVE: + c = CURSOR_MOVE; + break; + case TOOL_EDIT_PIVOT: + c = CURSOR_CROSS; + break; + case TOOL_PAN: + c = CURSOR_DRAG; + break; + default: + break; } - - break; } - } + break; + case DRAG_LEFT: + case DRAG_RIGHT: + c = CURSOR_HSIZE; + break; + case DRAG_TOP: + case DRAG_BOTTOM: + c = CURSOR_VSIZE; + break; + case DRAG_TOP_LEFT: + case DRAG_BOTTOM_RIGHT: + c = CURSOR_FDIAGSIZE; + break; + case DRAG_TOP_RIGHT: + case DRAG_BOTTOM_LEFT: + c = CURSOR_BDIAGSIZE; + break; + case DRAG_ALL: + c = CURSOR_MOVE; + break; + default: + break; + } + viewport->set_default_cursor_shape(c); + + // Grab focus + if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) { + viewport->call_deferred("grab_focus"); } } @@ -2292,8 +1918,8 @@ void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_posi void CanvasItemEditor::_draw_focus() { // Draw the focus around the base viewport - if (viewport_base->has_focus()) { - get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size())); + if (viewport->has_focus()) { + get_stylebox("Focus", "EditorStyles")->draw(viewport->get_canvas_item(), Rect2(Point2(), viewport->get_size())); } } @@ -2306,63 +1932,61 @@ void CanvasItemEditor::_draw_guides() { if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_"); for (int i = 0; i < vguides.size(); i++) { - if (drag == DRAG_V_GUIDE && i == edited_guide_index) + if (drag_type == DRAG_V_GUIDE && i == dragged_guide_index) continue; float x = xform.xform(Point2(vguides[i], 0)).x; - viewport_base->draw_line(Point2(x, 0), Point2(x, viewport_base->get_size().y), guide_color); + viewport->draw_line(Point2(x, 0), Point2(x, viewport->get_size().y), guide_color); } } if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) { Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_"); for (int i = 0; i < hguides.size(); i++) { - if (drag == DRAG_H_GUIDE && i == edited_guide_index) + if (drag_type == DRAG_H_GUIDE && i == dragged_guide_index) continue; float y = xform.xform(Point2(0, hguides[i])).y; - viewport_base->draw_line(Point2(0, y), Point2(viewport_base->get_size().x, y), guide_color); + viewport->draw_line(Point2(0, y), Point2(viewport->get_size().x, y), guide_color); } } // Dragged guide Color text_color = get_color("font_color", "Editor"); text_color.a = 0.5; - if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_V_GUIDE) { - String str = vformat("%d px", xform.affine_inverse().xform(edited_guide_pos).x); + if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) { + String str = vformat("%d px", xform.affine_inverse().xform(dragged_guide_pos).x); Ref<Font> font = get_font("font", "Label"); Size2 text_size = font->get_string_size(str); - viewport_base->draw_string(font, Point2(edited_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color); - viewport_base->draw_line(Point2(edited_guide_pos.x, 0), Point2(edited_guide_pos.x, viewport_base->get_size().y), guide_color); + viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color); + viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color); } - if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_H_GUIDE) { - String str = vformat("%d px", xform.affine_inverse().xform(edited_guide_pos).y); + if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) { + String str = vformat("%d px", xform.affine_inverse().xform(dragged_guide_pos).y); Ref<Font> font = get_font("font", "Label"); Size2 text_size = font->get_string_size(str); - viewport_base->draw_string(font, Point2(RULER_WIDTH + 10, edited_guide_pos.y + text_size.y / 2 + 10), str, text_color); - viewport_base->draw_line(Point2(0, edited_guide_pos.y), Point2(viewport_base->get_size().x, edited_guide_pos.y), guide_color); + viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, text_color); + viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color); } } void CanvasItemEditor::_draw_rulers() { - Color graduation_color = get_color("font_color", "Editor"); - graduation_color.a = 0.5; Color bg_color = get_color("dark_color_2", "Editor"); + Color graduation_color = get_color("font_color", "Editor").linear_interpolate(bg_color, 0.5); Color font_color = get_color("font_color", "Editor"); font_color.a = 0.8; Ref<Font> font = get_font("rulers", "EditorFonts"); // The rule transform - Transform2D ruler_transform; - if (show_grid || snap_grid) { - ruler_transform = Transform2D(); - if (snap_relative && get_item_count() > 0) { - ruler_transform.translate(_find_topleftmost_point()); + Transform2D ruler_transform = Transform2D(); + if (show_grid || (snap_active && snap_grid)) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + if (snap_relative && selection.size() > 0) { + ruler_transform.translate(_get_encompassing_rect_from_list(selection).position); ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); } else { ruler_transform.translate(grid_offset); ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); } while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) { - ruler_transform.scale_basis(Point2(2, 2)); } } else { @@ -2373,7 +1997,6 @@ void CanvasItemEditor::_draw_rulers() { for (int i = 0; basic_rule * zoom < 100; i++) { basic_rule *= (i % 2) ? 2.0 : 5.0; } - ruler_transform = Transform2D(); ruler_transform.scale(Size2(basic_rule, basic_rule)); } @@ -2387,43 +2010,43 @@ void CanvasItemEditor::_draw_rulers() { minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision)); // First and last graduations to draw (in the ruler space) - Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2()); + Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2(RULER_WIDTH, RULER_WIDTH)); Point2 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size()); // Draw top ruler - viewport_base->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color); + viewport->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color); for (int i = Math::ceil(first.x); i < last.x; i++) { Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)); if (i % (major_subdivision * minor_subdivision) == 0) { - viewport_base->draw_line(Point2(position.x + RULER_WIDTH, 0), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + viewport->draw_line(Point2(position.x, 0), Point2(position.x, RULER_WIDTH), graduation_color); float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x; - viewport_base->draw_string(font, Point2(position.x + RULER_WIDTH + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + viewport->draw_string(font, Point2(position.x + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); } else { if (i % minor_subdivision == 0) { - viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.33), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.33), Point2(position.x, RULER_WIDTH), graduation_color); } else { - viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.66), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.66), Point2(position.x, RULER_WIDTH), graduation_color); } } } // Draw left ruler - viewport_base->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color); + viewport->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color); for (int i = Math::ceil(first.y); i < last.y; i++) { Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)); if (i % (major_subdivision * minor_subdivision) == 0) { - viewport_base->draw_line(Point2(0, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color); float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y; - viewport_base->draw_string(font, Point2(2, position.y + RULER_WIDTH + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + viewport->draw_string(font, Point2(2, position.y + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); } else { if (i % minor_subdivision == 0) { - viewport_base->draw_line(Point2(RULER_WIDTH * 0.33, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + viewport->draw_line(Point2(RULER_WIDTH * 0.33, position.y), Point2(RULER_WIDTH, position.y), graduation_color); } else { - viewport_base->draw_line(Point2(RULER_WIDTH * 0.66, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + viewport->draw_line(Point2(RULER_WIDTH * 0.66, position.y), Point2(RULER_WIDTH, position.y), graduation_color); } } } - viewport_base->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color); + viewport->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color); } void CanvasItemEditor::_draw_grid() { @@ -2434,8 +2057,9 @@ void CanvasItemEditor::_draw_grid() { Transform2D xform = transform.affine_inverse(); Vector2 real_grid_offset; - if (snap_relative && get_item_count() > 0) { - Vector2 topleft = _find_topleftmost_point(); + List<CanvasItem *> selection = _get_edited_canvas_items(); + if (snap_relative && selection.size() > 0) { + Vector2 topleft = _get_encompassing_rect_from_list(selection).position; real_grid_offset.x = fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier)); real_grid_offset.y = fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier)); } else { @@ -2468,26 +2092,23 @@ void CanvasItemEditor::_draw_grid() { } void CanvasItemEditor::_draw_selection() { - bool pivot_found = false; Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons"); - bool single = _get_single_item() != NULL; RID ci = viewport->get_canvas_item(); - Map<Node *, Object *> &selection = editor_selection->get_selection(); - for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { + List<CanvasItem *> selection = _get_edited_canvas_items(false, false); - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; + bool single = selection.size() == 1; + for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - if (!se) - continue; Rect2 rect = canvas_item->_edit_get_rect(); - if (show_helpers && drag != DRAG_NONE && drag != DRAG_PIVOT) { + // Draw the previous position if we are dragging the node + if (show_helpers && + (drag_type == DRAG_ALL || drag_type == DRAG_ROTATE || + drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM || + drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT)) { const Transform2D pre_drag_xform = transform * se->pre_drag_xform; const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7); @@ -2507,8 +2128,8 @@ void CanvasItemEditor::_draw_selection() { Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); VisualServer::get_singleton()->canvas_item_add_set_transform(ci, xform); + // Draw the selected items surrounding boxes Vector2 endpoints[4] = { - xform.xform(rect.position), xform.xform(rect.position + Vector2(rect.size.x, 0)), xform.xform(rect.position + rect.size), @@ -2524,25 +2145,13 @@ void CanvasItemEditor::_draw_selection() { } if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks - - Node2D *node2d = Object::cast_to<Node2D>(canvas_item); - if (node2d) { - if (node2d->_edit_use_pivot()) { - viewport->draw_texture(pivot_icon, xform.get_origin() + (-pivot_icon->get_size() / 2).floor()); - can_move_pivot = true; - pivot_found = true; - } + // Draw the pivot + if (canvas_item->_edit_get_pivot() != Vector2() || drag_type == DRAG_PIVOT || tool == TOOL_EDIT_PIVOT) { // This is not really clean :/ + viewport->draw_texture(pivot_icon, xform.xform(canvas_item->_edit_get_pivot()) + (-pivot_icon->get_size() / 2).floor()); } Control *control = Object::cast_to<Control>(canvas_item); if (control) { - Vector2 pivot_ofs = control->get_pivot_offset(); - if (pivot_ofs != Vector2()) { - viewport->draw_texture(pivot_icon, xform.xform(pivot_ofs) + (-pivot_icon->get_size() / 2).floor()); - } - can_move_pivot = true; - pivot_found = true; - if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) { // Draw the helpers Color color_base = Color(0.8, 0.8, 0.8, 0.5); @@ -2561,10 +2170,9 @@ void CanvasItemEditor::_draw_selection() { anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i])); } - Map<Node *, Object *> &selection = editor_selection->get_selection(); // Get which anchor is dragged int dragged_anchor = -1; - switch (drag) { + switch (drag_type) { case DRAG_ANCHOR_ALL: case DRAG_ANCHOR_TOP_LEFT: dragged_anchor = 0; @@ -2578,6 +2186,8 @@ void CanvasItemEditor::_draw_selection() { case DRAG_ANCHOR_BOTTOM_LEFT: dragged_anchor = 3; break; + default: + break; } if (dragged_anchor >= 0) { @@ -2639,56 +2249,65 @@ void CanvasItemEditor::_draw_selection() { node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * control->get_parent_area_size().width + control->get_margin(MARGIN_RIGHT); node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * control->get_parent_area_size().height + control->get_margin(MARGIN_BOTTOM); - switch (drag) { + Point2 start, end; + switch (drag_type) { case DRAG_LEFT: case DRAG_TOP_LEFT: case DRAG_BOTTOM_LEFT: _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); case DRAG_ALL: - Point2 start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio)); - Point2 end = start - Vector2(control->get_margin(MARGIN_LEFT), 0); + start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio)); + end = start - Vector2(control->get_margin(MARGIN_LEFT), 0); _draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP); viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); break; + default: + break; } - switch (drag) { + switch (drag_type) { case DRAG_RIGHT: case DRAG_TOP_RIGHT: case DRAG_BOTTOM_RIGHT: _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); case DRAG_ALL: - Point2 start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio)); - Point2 end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0); + start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio)); + end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0); _draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM); viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); break; + default: + break; } - switch (drag) { + switch (drag_type) { case DRAG_TOP: case DRAG_TOP_LEFT: case DRAG_TOP_RIGHT: _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT); case DRAG_ALL: - Point2 start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]); - Point2 end = start - Vector2(0, control->get_margin(MARGIN_TOP)); + start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]); + end = start - Vector2(0, control->get_margin(MARGIN_TOP)); _draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT); viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); break; + default: + break; } - switch (drag) { + switch (drag_type) { case DRAG_BOTTOM: case DRAG_BOTTOM_LEFT: case DRAG_BOTTOM_RIGHT: _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT); case DRAG_ALL: - Point2 start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]); - Point2 end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM)); + start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]); + end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM)); _draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT); viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); break; + default: + break; } - switch (drag) { + switch (drag_type) { //Draw the ghost rect if the node if rotated/scaled case DRAG_LEFT: case DRAG_TOP_LEFT: @@ -2704,14 +2323,15 @@ void CanvasItemEditor::_draw_selection() { viewport->draw_rect(parent_transform.xform(rect), color_base, false); } break; + default: + break; } } } if (tool == TOOL_SELECT) { - for (int i = 0; i < 4; i++) { - + // Draw the resize handles int prev = (i + 3) % 4; int next = (i + 1) % 4; @@ -2728,9 +2348,9 @@ void CanvasItemEditor::_draw_selection() { } } } - pivot_button->set_disabled(!pivot_found); - if (box_selecting) { + if (drag_type == DRAG_BOX_SELECTION) { + // Draw the dragging box Point2 bsfrom = transform.xform(drag_from); Point2 bsto = transform.xform(box_selecting_to); @@ -2738,33 +2358,82 @@ void CanvasItemEditor::_draw_selection() { } Color rotate_color(0.4, 0.7, 1.0, 0.8); - if (drag == DRAG_ROTATE) { - VisualServer::get_singleton()->canvas_item_add_line(ci, transform.xform(display_rotate_from), transform.xform(display_rotate_to), rotate_color); + if (drag_type == DRAG_ROTATE) { + // Draw the line when rotating a node + viewport->draw_line(transform.xform(drag_rotation_center), transform.xform(drag_to), rotate_color); } } -void CanvasItemEditor::_draw_axis() { +void CanvasItemEditor::_draw_straight_line(Point2 p_from, Point2 p_to, Color p_color) { + // Draw a line going through the whole screen from a vector RID ci = viewport->get_canvas_item(); + Vector<Point2> points; + Point2 from = transform.xform(p_from); + Point2 to = transform.xform(p_to); + Size2 viewport_size = viewport->get_size(); + + if (to.x == from.x) { + // Vertical line + points.push_back(Point2(to.x, 0)); + points.push_back(Point2(to.x, viewport_size.y)); + } else if (to.y == from.y) { + // Horizontal line + points.push_back(Point2(0, to.y)); + points.push_back(Point2(viewport_size.x, to.y)); + } else { + float y_for_zero_x = (to.y * from.x - from.y * to.x) / (from.x - to.x); + float x_for_zero_y = (to.x * from.y - from.x * to.y) / (from.y - to.y); + float y_for_viewport_x = ((to.y - from.y) * (viewport_size.x - from.x)) / (to.x - from.x) + from.y; + float x_for_viewport_y = ((to.x - from.x) * (viewport_size.y - from.y)) / (to.y - from.y) + from.x; // faux + + //bool start_set = false; + if (y_for_zero_x >= 0 && y_for_zero_x <= viewport_size.y) { + points.push_back(Point2(0, y_for_zero_x)); + } + if (x_for_zero_y >= 0 && x_for_zero_y <= viewport_size.x) { + points.push_back(Point2(x_for_zero_y, 0)); + } + if (y_for_viewport_x >= 0 && y_for_viewport_x <= viewport_size.y) { + points.push_back(Point2(viewport_size.x, y_for_viewport_x)); + } + if (x_for_viewport_y >= 0 && x_for_viewport_y <= viewport_size.x) { + points.push_back(Point2(x_for_viewport_y, viewport_size.y)); + } + } + if (points.size() >= 2) { + VisualServer::get_singleton()->canvas_item_add_line(ci, points[0], points[1], p_color); + } +} - Color x_axis_color(1.0, 0.4, 0.4, 0.6); - Color y_axis_color(0.4, 1.0, 0.4, 0.6); - Color area_axis_color(0.4, 0.4, 1.0, 0.4); +void CanvasItemEditor::_draw_axis() { - Point2 origin = transform.get_origin(); - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(0, origin.y), Point2(viewport->get_size().x, origin.y), x_axis_color); - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(origin.x, 0), Point2(origin.x, viewport->get_size().y), y_axis_color); + if (show_origin) { - Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); + Color x_axis_color(1.0, 0.4, 0.4, 0.6); + Color y_axis_color(0.4, 1.0, 0.4, 0.6); - Vector2 screen_endpoints[4] = { - transform.xform(Vector2(0, 0)), - transform.xform(Vector2(screen_size.width, 0)), - transform.xform(Vector2(screen_size.width, screen_size.height)), - transform.xform(Vector2(0, screen_size.height)) - }; + _draw_straight_line(Point2(), Point2(1, 0), x_axis_color); + _draw_straight_line(Point2(), Point2(0, 1), y_axis_color); + } + + if (show_viewport) { + + RID ci = viewport->get_canvas_item(); + + Color area_axis_color(0.4, 0.4, 1.0, 0.4); + + Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); - for (int i = 0; i < 4; i++) { - VisualServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color); + Vector2 screen_endpoints[4] = { + transform.xform(Vector2(0, 0)), + transform.xform(Vector2(screen_size.width, 0)), + transform.xform(Vector2(screen_size.width, screen_size.height)), + transform.xform(Vector2(0, screen_size.height)) + }; + + for (int i = 0; i < 4; i++) { + VisualServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color); + } } } @@ -2783,7 +2452,7 @@ void CanvasItemEditor::_draw_bones() { E->get().from = Vector2(); E->get().to = Vector2(); - Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->get().bone)); + Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key())); if (!n2d) continue; @@ -2881,7 +2550,6 @@ void CanvasItemEditor::_build_bones_list(Node *p_node) { ObjectID id = c->get_instance_id(); if (!bone_list.has(id)) { BoneList bone; - bone.bone = id; bone_list[id] = bone; } @@ -2890,33 +2558,12 @@ void CanvasItemEditor::_build_bones_list(Node *p_node) { } } -void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) { - ERR_FAIL_COND(!p_node); - - for (int i = 0; i < p_node->get_child_count(); i++) { - _get_encompassing_rect(p_node->get_child(i), r_rect, p_xform); - } - - CanvasItem *c = Object::cast_to<CanvasItem>(p_node); - if (c && c->is_visible_in_tree()) { - Rect2 rect = c->_edit_get_rect(); - Transform2D xform = p_xform * c->get_transform(); - r_rect.expand_to(xform.xform(rect.position)); - r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); - r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); - r_rect.expand_to(xform.xform(rect.position + rect.size)); - } -} - -void CanvasItemEditor::_draw_viewport_base() { - if (show_rulers) - _draw_rulers(); - if (show_guides) - _draw_guides(); - _draw_focus(); -} - void CanvasItemEditor::_draw_viewport() { + // Update the transform + transform = Transform2D(); + transform.scale_basis(Size2(zoom, zoom)); + transform.elements[2] = -view_offset * zoom; + editor->get_scene_root()->set_global_canvas_transform(transform); // hide/show buttons depending on the selection bool all_locked = true; @@ -2947,8 +2594,6 @@ void CanvasItemEditor::_draw_viewport() { group_button->set_disabled(selection.empty()); ungroup_button->set_visible(all_group); - _update_scrollbars(); - _draw_grid(); _draw_selection(); _draw_axis(); @@ -2968,36 +2613,25 @@ void CanvasItemEditor::_draw_viewport() { } _draw_bones(); + if (show_rulers) + _draw_rulers(); + if (show_guides) + _draw_guides(); + _draw_focus(); } void CanvasItemEditor::_notification(int p_what) { if (p_what == NOTIFICATION_PHYSICS_PROCESS) { - EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels")); - List<Node *> selection = editor_selection->get_selected_node_list(); - - bool all_control = true; - bool has_control = false; - - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) - continue; - - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) - continue; - - if (Object::cast_to<Control>(canvas_item)) - has_control = true; - else - all_control = false; + int nb_control = 0; + int nb_having_pivot = 0; + List<CanvasItem *> selection = _get_edited_canvas_items(); + for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - if (!se) - continue; Rect2 r = canvas_item->_edit_get_rect(); Transform2D xform = canvas_item->get_transform(); @@ -3008,36 +2642,41 @@ void CanvasItemEditor::_notification(int p_what) { se->prev_xform = xform; } - if (Object::cast_to<Control>(canvas_item)) { + Control *control = Object::cast_to<Control>(canvas_item); + if (control) { float anchors[4]; Vector2 pivot; - pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset(); - anchors[MARGIN_LEFT] = Object::cast_to<Control>(canvas_item)->get_anchor(MARGIN_LEFT); - anchors[MARGIN_RIGHT] = Object::cast_to<Control>(canvas_item)->get_anchor(MARGIN_RIGHT); - anchors[MARGIN_TOP] = Object::cast_to<Control>(canvas_item)->get_anchor(MARGIN_TOP); - anchors[MARGIN_BOTTOM] = Object::cast_to<Control>(canvas_item)->get_anchor(MARGIN_BOTTOM); + pivot = control->get_pivot_offset(); + anchors[MARGIN_LEFT] = control->get_anchor(MARGIN_LEFT); + anchors[MARGIN_RIGHT] = control->get_anchor(MARGIN_RIGHT); + anchors[MARGIN_TOP] = control->get_anchor(MARGIN_TOP); + anchors[MARGIN_BOTTOM] = control->get_anchor(MARGIN_BOTTOM); if (pivot != se->prev_pivot || anchors[MARGIN_LEFT] != se->prev_anchors[MARGIN_LEFT] || anchors[MARGIN_RIGHT] != se->prev_anchors[MARGIN_RIGHT] || anchors[MARGIN_TOP] != se->prev_anchors[MARGIN_TOP] || anchors[MARGIN_BOTTOM] != se->prev_anchors[MARGIN_BOTTOM]) { - viewport->update(); - viewport_base->update(); se->prev_pivot = pivot; se->prev_anchors[MARGIN_LEFT] = anchors[MARGIN_LEFT]; se->prev_anchors[MARGIN_RIGHT] = anchors[MARGIN_RIGHT]; se->prev_anchors[MARGIN_TOP] = anchors[MARGIN_TOP]; se->prev_anchors[MARGIN_BOTTOM] = anchors[MARGIN_BOTTOM]; + viewport->update(); } + nb_control++; + } + + if (canvas_item->_edit_use_pivot()) { + nb_having_pivot++; } } + // Activate / Deactivate the pivot tool + pivot_button->set_disabled(nb_having_pivot == 0); - if (all_control && has_control) - presets_menu->show(); - else - presets_menu->hide(); + // Show / Hide the layout button + presets_menu->set_visible(nb_control > 0 && nb_control == selection.size()); for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) { - Object *b = ObjectDB::get_instance(E->get().bone); + Object *b = ObjectDB::get_instance(E->key()); if (!b) { viewport->update(); @@ -3150,108 +2789,114 @@ void CanvasItemEditor::_notification(int p_what) { void CanvasItemEditor::edit(CanvasItem *p_canvas_item) { - drag = DRAG_NONE; + drag_type = DRAG_NONE; // Clear the selection editor_selection->clear(); //_clear_canvas_items(); editor_selection->add_node(p_canvas_item); - //_add_canvas_item(p_canvas_item); - viewport->update(); - viewport_base->update(); } void CanvasItemEditor::_update_scrollbars() { updating_scroll = true; - if (show_rulers) - viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH)); - else - viewport_scrollable->set_begin(Point2()); + // Move the zoom buttons + Point2 zoom_hb_begin = Point2(5, 5); + zoom_hb_begin += (show_rulers) ? Point2(RULER_WIDTH, RULER_WIDTH) : Point2(); + zoom_hb->set_begin(zoom_hb_begin); + // Move and resize the scrollbars Size2 size = viewport->get_size(); Size2 hmin = h_scroll->get_minimum_size(); Size2 vmin = v_scroll->get_minimum_size(); - v_scroll->set_begin(Point2(size.width - vmin.width, 0)); + v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0)); v_scroll->set_end(Point2(size.width, size.height)); - h_scroll->set_begin(Point2(0, size.height - hmin.height)); + h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height)); h_scroll->set_end(Point2(size.width - vmin.width, size.height)); + // Get the visible frame Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); - Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height)); - Rect2 canvas_item_rect = Rect2(Point2(), screen_rect); - bone_last_frame++; if (editor->get_edited_scene()) { _build_bones_list(editor->get_edited_scene()); - _get_encompassing_rect(editor->get_edited_scene(), canvas_item_rect, Transform2D()); } List<Map<ObjectID, BoneList>::Element *> bone_to_erase; - for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) { - if (E->get().last_pass != bone_last_frame) { bone_to_erase.push_back(E); } } - while (bone_to_erase.size()) { bone_list.erase(bone_to_erase.front()->get()); bone_to_erase.pop_front(); } - //expand area so it's easier to do animations and stuff at 0,0 + // Calculate scrollable area + Rect2 canvas_item_rect = Rect2(Point2(), screen_rect); + if (editor->get_edited_scene()) { + Rect2 content_rect = _get_scene_encompassing_rect(); + canvas_item_rect.expand_to(content_rect.position); + canvas_item_rect.expand_to(content_rect.position + content_rect.size); + } canvas_item_rect.size += screen_rect * 2; canvas_item_rect.position -= screen_rect; - Point2 ofs; + // Constraints the view offset and updates the scrollbars + Point2 begin = canvas_item_rect.position; + Point2 end = canvas_item_rect.position + canvas_item_rect.size - local_rect.size / zoom; if (canvas_item_rect.size.height <= (local_rect.size.y / zoom)) { + if (ABS(begin.y - previous_update_view_offset.y) < ABS(begin.y - view_offset.y)) { + view_offset.y = previous_update_view_offset.y; + } + v_scroll->hide(); - ofs.y = canvas_item_rect.position.y; } else { - - v_scroll->show(); - v_scroll->set_min(canvas_item_rect.position.y); - v_scroll->set_max(canvas_item_rect.position.y + canvas_item_rect.size.y); - v_scroll->set_page(local_rect.size.y / zoom); - if (first_update) { - //so 0,0 is visible - v_scroll->set_value(-10); - h_scroll->set_value(-10); - first_update = false; + if (view_offset.y > end.y && view_offset.y > previous_update_view_offset.y) { + view_offset.y = MAX(end.y, previous_update_view_offset.y); + } + if (view_offset.y < begin.y && view_offset.y < previous_update_view_offset.y) { + view_offset.y = MIN(begin.y, previous_update_view_offset.y); } - ofs.y = v_scroll->get_value(); + v_scroll->show(); + v_scroll->set_min(MIN(view_offset.y, begin.y)); + v_scroll->set_max(MAX(view_offset.y, end.y) + screen_rect.y); + v_scroll->set_page(screen_rect.y); } if (canvas_item_rect.size.width <= (local_rect.size.x / zoom)) { + if (ABS(begin.x - previous_update_view_offset.x) < ABS(begin.x - view_offset.x)) { + view_offset.x = previous_update_view_offset.x; + } h_scroll->hide(); - ofs.x = canvas_item_rect.position.x; } else { + if (view_offset.x > end.x && view_offset.x > previous_update_view_offset.x) { + view_offset.x = MAX(end.x, previous_update_view_offset.x); + } + if (view_offset.x < begin.x && view_offset.x < previous_update_view_offset.x) { + view_offset.x = MIN(begin.x, previous_update_view_offset.x); + } h_scroll->show(); - h_scroll->set_min(canvas_item_rect.position.x); - h_scroll->set_max(canvas_item_rect.position.x + canvas_item_rect.size.x); - h_scroll->set_page(local_rect.size.x / zoom); - ofs.x = h_scroll->get_value(); + h_scroll->set_min(MIN(view_offset.x, begin.x)); + h_scroll->set_max(MAX(view_offset.x, end.x) + screen_rect.x); + h_scroll->set_page(screen_rect.x); } - //transform=Matrix32(); - transform.elements[2] = -ofs * zoom; - - editor->get_scene_root()->set_global_canvas_transform(transform); + // Calculate scrollable area + v_scroll->set_value(view_offset.y); + h_scroll->set_value(view_offset.x); + previous_update_view_offset = view_offset; updating_scroll = false; - - //transform.scale_basis(Vector2(zoom,zoom)); } void CanvasItemEditor::_update_scroll(float) { @@ -3259,62 +2904,45 @@ void CanvasItemEditor::_update_scroll(float) { if (updating_scroll) return; - Point2 ofs; - ofs.x = h_scroll->get_value(); - ofs.y = v_scroll->get_value(); - - //current_window->set_scroll(-ofs); - - transform = Transform2D(); - - transform.scale_basis(Size2(zoom, zoom)); - transform.elements[2] = -ofs; - - editor->get_scene_root()->set_global_canvas_transform(transform); - + view_offset.x = h_scroll->get_value(); + view_offset.y = v_scroll->get_value(); viewport->update(); - viewport_base->update(); } void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_preset) { List<Node *> selection = editor_selection->get_selected_node_list(); undo_redo->create_action(TTR("Change Anchors and Margins")); + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - Control *c = Object::cast_to<Control>(E->get()); - - undo_redo->add_do_method(c, "set_anchors_preset", p_preset); - switch (p_preset) { - case PRESET_TOP_LEFT: - case PRESET_TOP_RIGHT: - case PRESET_BOTTOM_LEFT: - case PRESET_BOTTOM_RIGHT: - case PRESET_CENTER_LEFT: - case PRESET_CENTER_TOP: - case PRESET_CENTER_RIGHT: - case PRESET_CENTER_BOTTOM: - case PRESET_CENTER: - undo_redo->add_do_method(c, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE); - break; - case PRESET_LEFT_WIDE: - case PRESET_TOP_WIDE: - case PRESET_RIGHT_WIDE: - case PRESET_BOTTOM_WIDE: - case PRESET_VCENTER_WIDE: - case PRESET_HCENTER_WIDE: - case PRESET_WIDE: - undo_redo->add_do_method(c, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE); - break; + Control *control = Object::cast_to<Control>(E->get()); + if (control) { + undo_redo->add_do_method(control, "set_anchors_preset", p_preset); + switch (p_preset) { + case PRESET_TOP_LEFT: + case PRESET_TOP_RIGHT: + case PRESET_BOTTOM_LEFT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_LEFT: + case PRESET_CENTER_TOP: + case PRESET_CENTER_RIGHT: + case PRESET_CENTER_BOTTOM: + case PRESET_CENTER: + undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE); + break; + case PRESET_LEFT_WIDE: + case PRESET_TOP_WIDE: + case PRESET_RIGHT_WIDE: + case PRESET_BOTTOM_WIDE: + case PRESET_VCENTER_WIDE: + case PRESET_HCENTER_WIDE: + case PRESET_WIDE: + undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE); + break; + } + undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state()); } - undo_redo->add_undo_method(c, "set_anchor", MARGIN_LEFT, c->get_anchor(MARGIN_LEFT)); - undo_redo->add_undo_method(c, "set_anchor", MARGIN_TOP, c->get_anchor(MARGIN_TOP)); - undo_redo->add_undo_method(c, "set_anchor", MARGIN_RIGHT, c->get_anchor(MARGIN_RIGHT)); - undo_redo->add_undo_method(c, "set_anchor", MARGIN_BOTTOM, c->get_anchor(MARGIN_BOTTOM)); - undo_redo->add_undo_method(c, "set_margin", MARGIN_LEFT, c->get_margin(MARGIN_LEFT)); - undo_redo->add_undo_method(c, "set_margin", MARGIN_TOP, c->get_margin(MARGIN_TOP)); - undo_redo->add_undo_method(c, "set_margin", MARGIN_RIGHT, c->get_margin(MARGIN_RIGHT)); - undo_redo->add_undo_method(c, "set_margin", MARGIN_BOTTOM, c->get_margin(MARGIN_BOTTOM)); } undo_redo->commit_action(); @@ -3326,13 +2954,11 @@ void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) { undo_redo->create_action(TTR("Change Anchors")); for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - Control *c = Object::cast_to<Control>(E->get()); - - undo_redo->add_do_method(c, "set_anchors_preset", p_preset); - undo_redo->add_undo_method(c, "set_anchor", MARGIN_LEFT, c->get_anchor(MARGIN_LEFT)); - undo_redo->add_undo_method(c, "set_anchor", MARGIN_TOP, c->get_anchor(MARGIN_TOP)); - undo_redo->add_undo_method(c, "set_anchor", MARGIN_RIGHT, c->get_anchor(MARGIN_RIGHT)); - undo_redo->add_undo_method(c, "set_anchor", MARGIN_BOTTOM, c->get_anchor(MARGIN_BOTTOM)); + Control *control = Object::cast_to<Control>(E->get()); + if (control) { + undo_redo->add_do_method(control, "set_anchors_preset", p_preset); + undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state()); + } } undo_redo->commit_action(); @@ -3346,30 +2972,39 @@ void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) { zoom = p_zoom; Point2 ofs = p_position; ofs = ofs / prev_zoom - ofs / zoom; - h_scroll->set_value(Math::round(h_scroll->get_value() + ofs.x)); - v_scroll->set_value(Math::round(v_scroll->get_value() + ofs.y)); + view_offset.x = Math::round(view_offset.x + ofs.x); + view_offset.y = Math::round(view_offset.y + ofs.y); - _update_scroll(0); + _update_scrollbars(); viewport->update(); - viewport_base->update(); } -void CanvasItemEditor::_zoom_minus() { +void CanvasItemEditor::_button_zoom_minus() { _zoom_on_position(zoom / 2.0, viewport_scrollable->get_size() / 2.0); } -void CanvasItemEditor::_zoom_reset() { +void CanvasItemEditor::_button_zoom_reset() { _zoom_on_position(1.0, viewport_scrollable->get_size() / 2.0); } -void CanvasItemEditor::_zoom_plus() { +void CanvasItemEditor::_button_zoom_plus() { _zoom_on_position(zoom * 2.0, viewport_scrollable->get_size() / 2.0); } -void CanvasItemEditor::_toggle_snap(bool p_status) { +void CanvasItemEditor::_button_toggle_snap(bool p_status) { snap_active = p_status; viewport->update(); - viewport_base->update(); +} + +void CanvasItemEditor::_button_tool_select(int p_index) { + + ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, rotate_button, pivot_button, pan_button }; + for (int i = 0; i < TOOL_MAX; i++) { + tb[i]->set_pressed(i == p_index); + } + + viewport->update(); + tool = (Tool)p_index; } void CanvasItemEditor::_popup_callback(int p_op) { @@ -3382,7 +3017,18 @@ void CanvasItemEditor::_popup_callback(int p_op) { int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); view_menu->get_popup()->set_item_checked(idx, show_grid); viewport->update(); - viewport_base->update(); + } break; + case SHOW_ORIGIN: { + show_origin = !show_origin; + int idx = view_menu->get_popup()->get_item_index(SHOW_ORIGIN); + view_menu->get_popup()->set_item_checked(idx, show_origin); + viewport->update(); + } break; + case SHOW_VIEWPORT: { + show_viewport = !show_viewport; + int idx = view_menu->get_popup()->get_item_index(SHOW_VIEWPORT); + view_menu->get_popup()->set_item_checked(idx, show_viewport); + viewport->update(); } break; case SNAP_USE_NODE_PARENT: { snap_node_parent = !snap_node_parent; @@ -3399,6 +3045,11 @@ void CanvasItemEditor::_popup_callback(int p_op) { int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES); smartsnap_config_popup->set_item_checked(idx, snap_node_sides); } break; + case SNAP_USE_NODE_CENTER: { + snap_node_center = !snap_node_center; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_CENTER); + smartsnap_config_popup->set_item_checked(idx, snap_node_center); + } break; case SNAP_USE_OTHER_NODES: { snap_other_nodes = !snap_other_nodes; int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES); @@ -3424,7 +3075,6 @@ void CanvasItemEditor::_popup_callback(int p_op) { int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE); snap_config_menu->get_popup()->set_item_checked(idx, snap_relative); viewport->update(); - viewport_base->update(); } break; case SNAP_USE_PIXEL: { snap_pixel = !snap_pixel; @@ -3452,26 +3102,19 @@ void CanvasItemEditor::_popup_callback(int p_op) { int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS); view_menu->get_popup()->set_item_checked(idx, show_rulers); viewport->update(); - viewport_base->update(); } break; case SHOW_GUIDES: { show_guides = !show_guides; int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES); view_menu->get_popup()->set_item_checked(idx, show_guides); viewport->update(); - viewport_base->update(); } break; - case LOCK_SELECTED: { - List<Node *> selection = editor_selection->get_selected_node_list(); - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); if (!canvas_item || !canvas_item->is_inside_tree()) continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) continue; @@ -3481,35 +3124,25 @@ void CanvasItemEditor::_popup_callback(int p_op) { viewport->update(); } break; case UNLOCK_SELECTED: { - List<Node *> selection = editor_selection->get_selected_node_list(); - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); if (!canvas_item || !canvas_item->is_inside_tree()) continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) continue; canvas_item->set_meta("_edit_lock_", Variant()); emit_signal("item_lock_status_changed"); } - viewport->update(); - } break; case GROUP_SELECTED: { - List<Node *> selection = editor_selection->get_selected_node_list(); - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); if (!canvas_item || !canvas_item->is_inside_tree()) continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) continue; @@ -3519,26 +3152,19 @@ void CanvasItemEditor::_popup_callback(int p_op) { viewport->update(); } break; case UNGROUP_SELECTED: { - List<Node *> selection = editor_selection->get_selected_node_list(); - for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); if (!canvas_item || !canvas_item->is_inside_tree()) continue; - if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) continue; canvas_item->set_meta("_edit_group_", Variant()); emit_signal("item_group_status_changed"); } - viewport->update(); - } break; - case ANCHORS_AND_MARGINS_PRESET_TOP_LEFT: { _set_anchors_and_margins_preset(PRESET_TOP_LEFT); } break; @@ -3723,28 +3349,6 @@ void CanvasItemEditor::_popup_callback(int p_op) { key_scale = key_scale_button->is_pressed(); } break; - /* - case ANIM_INSERT_POS_ROT - case ANIM_INSERT_POS_SCALE: - case ANIM_INSERT_ROT_SCALE: - case ANIM_INSERT_POS_ROT_SCALE: { - static const bool key_toggles[7][3]={ - {true,false,false}, - {false,true,false}, - {false,false,true}, - {true,true,false}, - {true,false,true}, - {false,true,true}, - {true,true,true} - }; - key_pos=key_toggles[p_op-ANIM_INSERT_POS][0]; - key_rot=key_toggles[p_op-ANIM_INSERT_POS][1]; - key_scale=key_toggles[p_op-ANIM_INSERT_POS][2]; - for(int i=ANIM_INSERT_POS;i<=ANIM_INSERT_POS_ROT_SCALE;i++) { - int idx = animation_menu->get_popup()->get_item_index(i); - animation_menu->get_popup()->set_item_checked(idx,i==p_op); - } - } break;*/ case ANIM_COPY_POSE: { pose_clipboard.clear(); @@ -3823,9 +3427,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (key_pos) ctrl->set_position(Point2()); /* - if (key_scale) - AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size()); - */ + if (key_scale) + AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size()); + */ } } @@ -3956,8 +3560,10 @@ void CanvasItemEditor::_focus_selection(int p_op) { center = rect.position + rect.size / 2; Vector2 offset = viewport->get_size() / 2 - editor->get_scene_root()->get_global_canvas_transform().xform(center); - h_scroll->set_value(h_scroll->get_value() - offset.x / zoom); - v_scroll->set_value(v_scroll->get_value() - offset.y / zoom); + view_offset.x -= offset.x / zoom; + view_offset.y -= offset.y / zoom; + _update_scrollbars(); + viewport->update(); } else { // VIEW_FRAME_TO_SELECTION @@ -3966,7 +3572,7 @@ void CanvasItemEditor::_focus_selection(int p_op) { float scale_y = viewport->get_size().y / rect.size.y; zoom = scale_x < scale_y ? scale_x : scale_y; zoom *= 0.90; - _update_scroll(0); + viewport->update(); call_deferred("_popup_callback", VIEW_CENTER_TO_SELECTION); } } @@ -3974,20 +3580,19 @@ void CanvasItemEditor::_focus_selection(int p_op) { void CanvasItemEditor::_bind_methods() { - ClassDB::bind_method("_zoom_minus", &CanvasItemEditor::_zoom_minus); - ClassDB::bind_method("_zoom_reset", &CanvasItemEditor::_zoom_reset); - ClassDB::bind_method("_zoom_plus", &CanvasItemEditor::_zoom_plus); - ClassDB::bind_method("_toggle_snap", &CanvasItemEditor::_toggle_snap); + ClassDB::bind_method("_button_zoom_minus", &CanvasItemEditor::_button_zoom_minus); + ClassDB::bind_method("_button_zoom_reset", &CanvasItemEditor::_button_zoom_reset); + ClassDB::bind_method("_button_zoom_plus", &CanvasItemEditor::_button_zoom_plus); + ClassDB::bind_method("_button_toggle_snap", &CanvasItemEditor::_button_toggle_snap); ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll); + ClassDB::bind_method("_update_scrollbars", &CanvasItemEditor::_update_scrollbars); ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback); ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data); - ClassDB::bind_method("_tool_select", &CanvasItemEditor::_tool_select); + ClassDB::bind_method("_button_tool_select", &CanvasItemEditor::_button_tool_select); ClassDB::bind_method("_keying_changed", &CanvasItemEditor::_keying_changed); ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input); ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport); - ClassDB::bind_method("_draw_viewport_base", &CanvasItemEditor::_draw_viewport_base); ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport); - ClassDB::bind_method("_gui_input_viewport_base", &CanvasItemEditor::_gui_input_viewport_base); ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed); ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed); ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide); @@ -3997,6 +3602,175 @@ void CanvasItemEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("item_group_status_changed")); } +Dictionary CanvasItemEditor::get_state() const { + + Dictionary state; + state["zoom"] = zoom; + state["ofs"] = view_offset; + state["grid_offset"] = grid_offset; + state["grid_step"] = grid_step; + state["snap_rotation_offset"] = snap_rotation_offset; + state["snap_rotation_step"] = snap_rotation_step; + state["snap_active"] = snap_active; + state["snap_node_parent"] = snap_node_parent; + state["snap_node_anchors"] = snap_node_anchors; + state["snap_node_sides"] = snap_node_sides; + state["snap_node_center"] = snap_node_center; + state["snap_other_nodes"] = snap_other_nodes; + state["snap_grid"] = snap_grid; + state["snap_guides"] = snap_guides; + state["show_grid"] = show_grid; + state["show_origin"] = show_origin; + state["show_viewport"] = show_viewport; + state["show_rulers"] = show_rulers; + state["show_guides"] = show_guides; + state["show_helpers"] = show_helpers; + state["snap_rotation"] = snap_rotation; + state["snap_relative"] = snap_relative; + state["snap_pixel"] = snap_pixel; + state["skeleton_show_bones"] = skeleton_show_bones; + return state; +} + +void CanvasItemEditor::set_state(const Dictionary &p_state) { + + Dictionary state = p_state; + if (state.has("zoom")) { + zoom = p_state["zoom"]; + } + + if (state.has("ofs")) { + view_offset = p_state["ofs"]; + previous_update_view_offset = view_offset; + _update_scrollbars(); + } + + if (state.has("grid_offset")) { + grid_offset = state["grid_offset"]; + } + + if (state.has("grid_step")) { + grid_step = state["grid_step"]; + } + + if (state.has("snap_rotation_step")) { + snap_rotation_step = state["snap_rotation_step"]; + } + + if (state.has("snap_rotation_offset")) { + snap_rotation_offset = state["snap_rotation_offset"]; + } + + if (state.has("snap_active")) { + snap_active = state["snap_active"]; + snap_button->set_pressed(snap_active); + } + + if (state.has("snap_node_parent")) { + snap_node_parent = state["snap_node_parent"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); + smartsnap_config_popup->set_item_checked(idx, snap_node_parent); + } + + if (state.has("snap_node_anchors")) { + snap_node_anchors = state["snap_node_anchors"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS); + smartsnap_config_popup->set_item_checked(idx, snap_node_anchors); + } + + if (state.has("snap_node_sides")) { + snap_node_sides = state["snap_node_sides"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES); + smartsnap_config_popup->set_item_checked(idx, snap_node_sides); + } + + if (state.has("snap_node_center")) { + snap_node_center = state["snap_node_center"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_CENTER); + smartsnap_config_popup->set_item_checked(idx, snap_node_center); + } + + if (state.has("snap_other_nodes")) { + snap_other_nodes = state["snap_other_nodes"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES); + smartsnap_config_popup->set_item_checked(idx, snap_other_nodes); + } + + if (state.has("snap_guides")) { + snap_guides = state["snap_guides"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES); + smartsnap_config_popup->set_item_checked(idx, snap_guides); + } + + if (state.has("snap_grid")) { + snap_grid = state["snap_grid"]; + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID); + snap_config_menu->get_popup()->set_item_checked(idx, snap_grid); + } + + if (state.has("show_grid")) { + show_grid = state["show_grid"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); + view_menu->get_popup()->set_item_checked(idx, show_grid); + } + + if (state.has("show_origin")) { + show_origin = state["show_origin"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_ORIGIN); + view_menu->get_popup()->set_item_checked(idx, show_origin); + } + + if (state.has("show_viewport")) { + show_viewport = state["show_viewport"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_VIEWPORT); + view_menu->get_popup()->set_item_checked(idx, show_viewport); + } + + if (state.has("show_rulers")) { + show_rulers = state["show_rulers"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS); + view_menu->get_popup()->set_item_checked(idx, show_rulers); + } + + if (state.has("show_guides")) { + show_guides = state["show_guides"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES); + view_menu->get_popup()->set_item_checked(idx, show_guides); + } + + if (state.has("show_helpers")) { + show_helpers = state["show_helpers"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS); + view_menu->get_popup()->set_item_checked(idx, show_helpers); + } + + if (state.has("snap_rotation")) { + snap_rotation = state["snap_rotation"]; + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); + snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation); + } + + if (state.has("snap_relative")) { + snap_relative = state["snap_relative"]; + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE); + snap_config_menu->get_popup()->set_item_checked(idx, snap_relative); + } + + if (state.has("snap_pixel")) { + snap_pixel = state["snap_pixel"]; + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); + snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel); + } + + if (state.has("skeleton_show_bones")) { + skeleton_show_bones = state["skeleton_show_bones"]; + int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES); + skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones); + } + + viewport->update(); +} + void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) { hb->add_child(p_control); @@ -4042,21 +3816,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { bottom_split->add_child(palette_split); palette_split->set_v_size_flags(SIZE_EXPAND_FILL); - viewport_base = memnew(Control); - palette_split->add_child(viewport_base); - viewport_base->set_clip_contents(true); - viewport_base->connect("draw", this, "_draw_viewport_base"); - viewport_base->connect("gui_input", this, "_gui_input_viewport_base"); - viewport_base->set_focus_mode(FOCUS_ALL); - viewport_base->set_v_size_flags(SIZE_EXPAND_FILL); - viewport_base->set_h_size_flags(SIZE_EXPAND_FILL); - viewport_scrollable = memnew(Control); - viewport_base->add_child(viewport_scrollable); + palette_split->add_child(viewport_scrollable); viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS); - viewport_scrollable->set_draw_behind_parent(true); - viewport_scrollable->set_anchors_and_margins_preset(Control::PRESET_WIDE); - viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH)); + viewport_scrollable->set_clip_contents(true); + viewport_scrollable->set_v_size_flags(SIZE_EXPAND_FILL); + viewport_scrollable->set_h_size_flags(SIZE_EXPAND_FILL); + viewport_scrollable->connect("draw", this, "_update_scrollbars"); ViewportContainer *scene_tree = memnew(ViewportContainer); viewport_scrollable->add_child(scene_tree); @@ -4069,46 +3835,45 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { viewport->set_mouse_filter(MOUSE_FILTER_PASS); viewport->set_anchors_and_margins_preset(Control::PRESET_WIDE); viewport->set_clip_contents(true); + viewport->set_focus_mode(FOCUS_ALL); viewport->connect("draw", this, "_draw_viewport"); viewport->connect("gui_input", this, "_gui_input_viewport"); h_scroll = memnew(HScrollBar); viewport->add_child(h_scroll); - h_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED); + h_scroll->connect("value_changed", this, "_update_scroll"); h_scroll->hide(); v_scroll = memnew(VScrollBar); viewport->add_child(v_scroll); - v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED); + v_scroll->connect("value_changed", this, "_update_scroll"); v_scroll->hide(); - HBoxContainer *zoom_hb = memnew(HBoxContainer); + zoom_hb = memnew(HBoxContainer); viewport->add_child(zoom_hb); zoom_hb->set_begin(Point2(5, 5)); zoom_minus = memnew(ToolButton); zoom_hb->add_child(zoom_minus); - zoom_minus->connect("pressed", this, "_zoom_minus"); + zoom_minus->connect("pressed", this, "_button_zoom_minus"); zoom_minus->set_focus_mode(FOCUS_NONE); zoom_reset = memnew(ToolButton); zoom_hb->add_child(zoom_reset); - zoom_reset->connect("pressed", this, "_zoom_reset"); + zoom_reset->connect("pressed", this, "_button_zoom_reset"); zoom_reset->set_focus_mode(FOCUS_NONE); zoom_plus = memnew(ToolButton); zoom_hb->add_child(zoom_plus); - zoom_plus->connect("pressed", this, "_zoom_plus"); + zoom_plus->connect("pressed", this, "_button_zoom_plus"); zoom_plus->set_focus_mode(FOCUS_NONE); updating_scroll = false; - handle_len = 10; - first_update = true; select_button = memnew(ToolButton); hb->add_child(select_button); select_button->set_toggle_mode(true); - select_button->connect("pressed", this, "_tool_select", make_binds(TOOL_SELECT)); + select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECT)); select_button->set_pressed(true); select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q)); select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Depth list selection")); @@ -4116,14 +3881,14 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { move_button = memnew(ToolButton); hb->add_child(move_button); move_button->set_toggle_mode(true); - move_button->connect("pressed", this, "_tool_select", make_binds(TOOL_MOVE)); + move_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_MOVE)); move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W)); move_button->set_tooltip(TTR("Move Mode")); rotate_button = memnew(ToolButton); hb->add_child(rotate_button); rotate_button->set_toggle_mode(true); - rotate_button->connect("pressed", this, "_tool_select", make_binds(TOOL_ROTATE)); + rotate_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_ROTATE)); rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E)); rotate_button->set_tooltip(TTR("Rotate Mode")); @@ -4132,19 +3897,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { list_select_button = memnew(ToolButton); hb->add_child(list_select_button); list_select_button->set_toggle_mode(true); - list_select_button->connect("pressed", this, "_tool_select", make_binds(TOOL_LIST_SELECT)); + list_select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_LIST_SELECT)); list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); pivot_button = memnew(ToolButton); hb->add_child(pivot_button); pivot_button->set_toggle_mode(true); - pivot_button->connect("pressed", this, "_tool_select", make_binds(TOOL_EDIT_PIVOT)); + pivot_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_EDIT_PIVOT)); pivot_button->set_tooltip(TTR("Click to change object's rotation pivot.")); pan_button = memnew(ToolButton); hb->add_child(pan_button); pan_button->set_toggle_mode(true); - pan_button->connect("pressed", this, "_tool_select", make_binds(TOOL_PAN)); + pan_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PAN)); pan_button->set_tooltip(TTR("Pan Mode")); hb->add_child(memnew(VSeparator)); @@ -4152,7 +3917,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_button = memnew(ToolButton); hb->add_child(snap_button); snap_button->set_toggle_mode(true); - snap_button->connect("toggled", this, "_toggle_snap"); + snap_button->connect("toggled", this, "_button_toggle_snap"); snap_button->set_tooltip(TTR("Toggles snapping")); snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap"), KEY_S)); @@ -4179,6 +3944,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_parent", TTR("Snap to parent")), SNAP_USE_NODE_PARENT); smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_anchors", TTR("Snap to node anchor")), SNAP_USE_NODE_ANCHORS); smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_sides", TTR("Snap to node sides")), SNAP_USE_NODE_SIDES); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_center", TTR("Snap to node center")), SNAP_USE_NODE_CENTER); smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to other nodes")), SNAP_USE_OTHER_NODES); smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to guides")), SNAP_USE_GUIDES); @@ -4233,6 +3999,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers"), KEY_R), SHOW_RULERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION); @@ -4310,9 +4078,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { selection_menu->connect("id_pressed", this, "_selection_result_pressed"); selection_menu->connect("popup_hide", this, "_selection_menu_hide"); - drag_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/drag_pivot", TTR("Drag pivot from mouse position"), KEY_MASK_SHIFT | KEY_V); - set_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/set_pivot", TTR("Set pivot at mouse position"), KEY_V); - multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY); divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE); @@ -4320,14 +4085,15 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { key_rot = true; key_scale = false; - edited_guide_pos = Point2(); - edited_guide_index = -1; - show_grid = false; + show_origin = true; + show_viewport = true; show_helpers = false; show_rulers = true; show_guides = true; zoom = 1; + view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH); + previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen grid_offset = Point2(); grid_step = Point2(10, 10); grid_step_multiplier = 0; @@ -4337,6 +4103,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_node_parent = true; snap_node_anchors = true; snap_node_sides = true; + snap_node_center = true; snap_other_nodes = true; snap_grid = true; snap_guides = true; @@ -4344,17 +4111,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_pixel = false; skeleton_show_bones = true; skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); - box_selecting = false; - //zoom=0.5; singleton = this; set_process_unhandled_key_input(true); - can_move_pivot = false; - drag = DRAG_NONE; + + drag_type = DRAG_NONE; + drag_from = Vector2(); + drag_to = Vector2(); + dragged_guide_pos = Point2(); + dragged_guide_index = -1; + bone_last_frame = 0; - additive_selection = false; - // Update the menus checkboxes + // Update the menus' checkboxes call_deferred("set_state", get_state()); } @@ -4377,7 +4146,7 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) { canvas_item_editor->show(); canvas_item_editor->set_physics_process(true); VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false); - canvas_item_editor->viewport_base->grab_focus(); + canvas_item_editor->viewport->grab_focus(); } else { diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index ee9be86cce..da7ce9172a 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -50,9 +50,6 @@ class CanvasItemEditorSelectedItem : public Object { GDCLASS(CanvasItemEditorSelectedItem, Object); public: - Variant undo_state; - Vector2 undo_pivot; - Transform2D prev_xform; float prev_rot; Rect2 prev_rect; @@ -62,6 +59,11 @@ public: Transform2D pre_drag_xform; Rect2 pre_drag_rect; + List<float> pre_drag_bones_length; + List<Dictionary> pre_drag_bones_undo_state; + + Dictionary undo_state; + CanvasItemEditorSelectedItem() { prev_rot = 0; } }; @@ -86,6 +88,7 @@ class CanvasItemEditor : public VBoxContainer { SNAP_USE_NODE_PARENT, SNAP_USE_NODE_ANCHORS, SNAP_USE_NODE_SIDES, + SNAP_USE_NODE_CENTER, SNAP_USE_OTHER_NODES, SNAP_USE_GRID, SNAP_USE_GUIDES, @@ -97,6 +100,8 @@ class CanvasItemEditor : public VBoxContainer { SHOW_HELPERS, SHOW_RULERS, SHOW_GUIDES, + SHOW_ORIGIN, + SHOW_VIEWPORT, LOCK_SELECTED, UNLOCK_SELECTED, GROUP_SELECTED, @@ -169,6 +174,7 @@ class CanvasItemEditor : public VBoxContainer { enum DragType { DRAG_NONE, + DRAG_BOX_SELECTION, DRAG_LEFT, DRAG_TOP_LEFT, DRAG_TOP, @@ -185,29 +191,19 @@ class CanvasItemEditor : public VBoxContainer { DRAG_ALL, DRAG_ROTATE, DRAG_PIVOT, - DRAG_NODE_2D, DRAG_V_GUIDE, DRAG_H_GUIDE, DRAG_DOUBLE_GUIDE, - }; - - enum KeyMoveMODE { - MOVE_VIEW_BASE, - MOVE_LOCAL_BASE, - MOVE_LOCAL_WITH_ROT + DRAG_KEY_MOVE }; EditorSelection *editor_selection; - bool additive_selection; + bool selection_menu_additive_selection; Tool tool; - bool first_update; Control *viewport; - Control *viewport_base; Control *viewport_scrollable; - bool can_move_pivot; - HScrollBar *h_scroll; VScrollBar *v_scroll; HBoxContainer *hb; @@ -220,8 +216,12 @@ class CanvasItemEditor : public VBoxContainer { bool show_grid; bool show_rulers; bool show_guides; + bool show_origin; + bool show_viewport; bool show_helpers; float zoom; + Point2 view_offset; + Point2 previous_update_view_offset; Point2 grid_offset; Point2 grid_step; @@ -233,6 +233,7 @@ class CanvasItemEditor : public VBoxContainer { bool snap_node_parent; bool snap_node_anchors; bool snap_node_sides; + bool snap_node_center; bool snap_other_nodes; bool snap_grid; bool snap_guides; @@ -240,14 +241,10 @@ class CanvasItemEditor : public VBoxContainer { bool snap_relative; bool snap_pixel; bool skeleton_show_bones; - bool box_selecting; - Point2 box_selecting_to; bool key_pos; bool key_rot; bool key_scale; - void _tool_select(int p_index); - MenuOption last_option; struct _SelectResult { @@ -267,33 +264,17 @@ class CanvasItemEditor : public VBoxContainer { Transform2D xform; Vector2 from; Vector2 to; - ObjectID bone; uint64_t last_pass; }; - uint64_t bone_last_frame; Map<ObjectID, BoneList> bone_list; - Transform2D bone_orig_xform; - - struct BoneIK { - - Variant orig_state; - Vector2 pos; - float len; - Node2D *node; - }; - - List<BoneIK> bone_ik_list; - struct PoseClipboard { - Vector2 pos; Vector2 scale; float rot; ObjectID id; }; - List<PoseClipboard> pose_clipboard; ToolButton *select_button; @@ -333,16 +314,17 @@ class CanvasItemEditor : public VBoxContainer { Control *top_ruler; Control *left_ruler; - //PopupMenu *popup; - DragType drag; + DragType drag_type; Point2 drag_from; - Point2 drag_point_from; + Point2 drag_to; + Point2 drag_rotation_center; + List<CanvasItem *> drag_selection; + int dragged_guide_index; + Point2 dragged_guide_pos; + bool updating_value_dialog; - Point2 display_rotate_from; - Point2 display_rotate_to; - int edited_guide_index; - Point2 edited_guide_pos; + Point2 box_selecting_to; Ref<StyleBoxTexture> select_sb; Ref<Texture> select_handle; @@ -353,28 +335,19 @@ class CanvasItemEditor : public VBoxContainer { Ref<ShortCut> multiply_grid_step_shortcut; Ref<ShortCut> divide_grid_step_shortcut; - int handle_len; - bool _is_part_of_subscene(CanvasItem *p_item); - void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, Vector<_SelectResult> &r_items, int limit = 0); - void _find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, List<CanvasItem *> *r_items); - - void _select_click_on_empty_area(Point2 p_click_pos, bool p_append, bool p_box_selection); - bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag); + void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int limit = 0, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append); ConfirmationDialog *snap_dialog; CanvasItem *ref_item; - void _edit_set_pivot(const Vector2 &mouse_pos); void _add_canvas_item(CanvasItem *p_canvas_item); - void _remove_canvas_item(CanvasItem *p_canvas_item); - void _clear_canvas_items(); - void _key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE p_move_mode); - void _list_select(const Ref<InputEventMouseButton> &b); - DragType _get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point); - void _prepare_drag(const Point2 &p_click_pos); - DragType _get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point); + void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false); + void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false); + void _commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones = false); Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor); Vector2 _position_to_anchor(const Control *p_control, Vector2 position); @@ -383,27 +356,21 @@ class CanvasItemEditor : public VBoxContainer { bool updating_scroll; void _update_scroll(float); void _update_scrollbars(); - void _update_cursor(); - void incbeg(float &beg, float &end, float inc, float minsize, bool p_symmetric); - void incend(float &beg, float &end, float inc, float minsize, bool p_symmetric); - void _append_canvas_item(CanvasItem *p_item); void _snap_changed(); void _selection_result_pressed(int); void _selection_menu_hide(); UndoRedo *undo_redo; - - Point2 _find_topleftmost_point(); - void _build_bones_list(Node *p_node); - void _get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform); + List<CanvasItem *> _get_edited_canvas_items(bool retreive_locked = false, bool remove_canvas_item_if_parent_in_selection = true); + Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list); + void _expand_encompassing_rect_using_children(Rect2 &p_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + Rect2 _get_scene_encompassing_rect(); Object *_get_editor_data(Object *p_what); - CanvasItem *_get_single_item(); - int get_item_count(); void _keying_changed(); void _unhandled_key_input(const Ref<InputEvent> &p_ev); @@ -411,6 +378,7 @@ class CanvasItemEditor : public VBoxContainer { void _draw_text_at_position(Point2 p_position, String p_string, Margin p_side); void _draw_margin_at_position(int p_value, Point2 p_position, Margin p_side); void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side); + void _draw_straight_line(Point2 p_from, Point2 p_to, Color p_color); void _draw_rulers(); void _draw_guides(); @@ -422,13 +390,23 @@ class CanvasItemEditor : public VBoxContainer { void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform); void _draw_viewport(); - void _draw_viewport_base(); + + bool _gui_input_anchors(const Ref<InputEvent> &p_event); + bool _gui_input_move(const Ref<InputEvent> &p_event); + bool _gui_input_open_scene_on_double_click(const Ref<InputEvent> &p_event); + bool _gui_input_pivot(const Ref<InputEvent> &p_event); + bool _gui_input_resize(const Ref<InputEvent> &p_event); + bool _gui_input_rotate(const Ref<InputEvent> &p_event); + bool _gui_input_select(const Ref<InputEvent> &p_event); + bool _gui_input_zoom_or_pan(const Ref<InputEvent> &p_event); + bool _gui_input_rulers_and_guides(const Ref<InputEvent> &p_event); void _gui_input_viewport(const Ref<InputEvent> &p_event); - void _gui_input_viewport_base(const Ref<InputEvent> &p_event); void _focus_selection(int p_op); + void _solve_IK(Node2D *leaf_node, Point2 target_position); + void _snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius = 10.0); void _snap_if_closer_point(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0); void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap = NULL); @@ -437,12 +415,13 @@ class CanvasItemEditor : public VBoxContainer { void _set_margins_preset(Control::LayoutPreset p_preset); void _set_anchors_and_margins_preset(Control::LayoutPreset p_preset); + HBoxContainer *zoom_hb; void _zoom_on_position(float p_zoom, Point2 p_position = Point2()); - void _zoom_minus(); - void _zoom_reset(); - void _zoom_plus(); - - void _toggle_snap(bool p_status); + void _button_zoom_minus(); + void _button_zoom_reset(); + void _button_zoom_plus(); + void _button_toggle_snap(bool p_status); + void _button_tool_select(int p_index); HSplitContainer *palette_split; VSplitContainer *bottom_split; @@ -494,9 +473,10 @@ public: SNAP_NODE_PARENT = 1 << 3, SNAP_NODE_ANCHORS = 1 << 4, SNAP_NODE_SIDES = 1 << 5, - SNAP_OTHER_NODES = 1 << 6, + SNAP_NODE_CENTER = 1 << 6, + SNAP_OTHER_NODES = 1 << 7, - SNAP_DEFAULT = 0x07, + SNAP_DEFAULT = SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL, }; Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0); diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index d8d3c0cee6..4410242d9c 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -140,7 +140,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera *p_camera, const R Vector<Vector2> poly = node->get_polygon(); //first check if a point is to be added (segment split) - real_t grab_treshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); switch (mode) { @@ -159,7 +159,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera *p_camera, const R return true; } else { - if (wip.size() > 1 && p_camera->unproject_position(gt.xform(Vector3(wip[0].x, wip[0].y, depth))).distance_to(gpoint) < grab_treshold) { + if (wip.size() > 1 && p_camera->unproject_position(gt.xform(Vector3(wip[0].x, wip[0].y, depth))).distance_to(gpoint) < grab_threshold) { //wip closed _wip_close(); @@ -213,7 +213,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera *p_camera, const R continue; //not valid to reuse point real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_treshold) { + if (d < closest_dist && d < grab_threshold) { closest_dist = d; closest_pos = cp; closest_idx = i; @@ -242,7 +242,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera *p_camera, const R Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x, poly[i].y, depth))); real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_treshold) { + if (d < closest_dist && d < grab_threshold) { closest_dist = d; closest_pos = cp; closest_idx = i; @@ -288,7 +288,7 @@ bool CollisionPolygonEditor::forward_spatial_gui_input(Camera *p_camera, const R Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x, poly[i].y, depth))); real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_treshold) { + if (d < closest_dist && d < grab_threshold) { closest_dist = d; closest_pos = cp; closest_idx = i; diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 47d730cdf1..8542296bde 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -40,7 +40,7 @@ #include "scene/resources/material.h" #include "scene/resources/mesh.h" -static void post_process_preview(Ref<Image> p_image) { +void post_process_preview(Ref<Image> p_image) { if (p_image->get_format() != Image::FORMAT_RGBA8) p_image->convert(Image::FORMAT_RGBA8); diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 2e12515e30..35b5c3a5f0 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -33,6 +33,8 @@ #include "editor/editor_resource_preview.h" +void post_process_preview(Ref<Image> p_image); + class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorTexturePreviewPlugin, EditorResourcePreviewGenerator) public: diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp index fd5a1f185f..5020f5b851 100644 --- a/editor/plugins/item_list_editor_plugin.cpp +++ b/editor/plugins/item_list_editor_plugin.cpp @@ -247,7 +247,7 @@ void ItemListEditor::_node_removed(Node *p_node) { void ItemListEditor::_notification(int p_notification) { - if (p_notification == NOTIFICATION_ENTER_TREE) { + if (p_notification == NOTIFICATION_ENTER_TREE || p_notification == NOTIFICATION_THEME_CHANGED) { add_button->set_icon(get_icon("Add", "EditorIcons")); del_button->set_icon(get_icon("Remove", "EditorIcons")); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 1db6621718..3a169bd780 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -59,10 +59,13 @@ void Polygon2DEditor::_notification(int p_what) { button_uv->set_icon(get_icon("Uv", "EditorIcons")); + uv_button[UV_MODE_CREATE]->set_icon(get_icon("Add", "EditorIcons")); uv_button[UV_MODE_EDIT_POINT]->set_icon(get_icon("ToolSelect", "EditorIcons")); uv_button[UV_MODE_MOVE]->set_icon(get_icon("ToolMove", "EditorIcons")); uv_button[UV_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons")); uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons")); + uv_button[UV_MODE_ADD_SPLIT]->set_icon(get_icon("AddSplit", "EditorIcons")); + uv_button[UV_MODE_REMOVE_SPLIT]->set_icon(get_icon("DeleteSplit", "EditorIcons")); b_snap_grid->set_icon(get_icon("Grid", "EditorIcons")); b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons")); @@ -75,6 +78,36 @@ void Polygon2DEditor::_notification(int p_what) { } } +void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { + + if (p_mode == 0) { + uv_button[UV_MODE_CREATE]->hide(); + for (int i = UV_MODE_MOVE; i <= UV_MODE_SCALE; i++) { + uv_button[i]->show(); + } + uv_button[UV_MODE_ADD_SPLIT]->hide(); + uv_button[UV_MODE_REMOVE_SPLIT]->hide(); + _uv_mode(UV_MODE_EDIT_POINT); + + } else if (p_mode == 1) { + for (int i = 0; i <= UV_MODE_SCALE; i++) { + uv_button[i]->show(); + } + uv_button[UV_MODE_ADD_SPLIT]->hide(); + uv_button[UV_MODE_REMOVE_SPLIT]->hide(); + _uv_mode(UV_MODE_EDIT_POINT); + } else { + for (int i = 0; i <= UV_MODE_SCALE; i++) { + uv_button[i]->hide(); + } + uv_button[UV_MODE_ADD_SPLIT]->show(); + uv_button[UV_MODE_REMOVE_SPLIT]->show(); + _uv_mode(UV_MODE_ADD_SPLIT); + } + + uv_edit_draw->update(); +} + void Polygon2DEditor::_menu_option(int p_option) { switch (p_option) { @@ -180,6 +213,10 @@ void Polygon2DEditor::_set_snap_step_y(float p_val) { void Polygon2DEditor::_uv_mode(int p_mode) { + split_create = false; + uv_drag = false; + uv_create = false; + uv_mode = UVMode(p_mode); for (int i = 0; i < UV_MODE_MAX; i++) { uv_button[i]->set_pressed(p_mode == i); @@ -203,7 +240,56 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_drag_from = Vector2(mb->get_position().x, mb->get_position().y); uv_drag = true; uv_prev = node->get_uv(); + + if (uv_edit_mode[0]->is_pressed()) { //edit uv + uv_prev = node->get_uv(); + } else { //edit polygon + uv_prev = node->get_polygon(); + } + uv_move_current = uv_mode; + if (uv_move_current == UV_MODE_CREATE) { + + if (!uv_create) { + uv_prev.resize(0); + Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); + uv_prev.push_back(tuv); + uv_create_to = tuv; + uv_drag_index = 0; + uv_drag_from = tuv; + uv_drag = true; + uv_create = true; + uv_create_uv_prev = node->get_uv(); + uv_create_poly_prev = node->get_polygon(); + splits_prev = node->get_splits(); + node->set_polygon(uv_prev); + node->set_uv(uv_prev); + + } else { + Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); + + if (uv_prev.size() > 3 && tuv.distance_to(uv_prev[0]) < 8) { + undo_redo->create_action(TTR("Create Polygon & UV")); + undo_redo->add_do_method(node, "set_uv", node->get_uv()); + undo_redo->add_undo_method(node, "set_uv", uv_prev); + undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); + undo_redo->add_undo_method(node, "set_polygon", uv_prev); + undo_redo->add_do_method(uv_edit_draw, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); + undo_redo->commit_action(); + uv_drag = false; + uv_create = false; + _uv_mode(UV_MODE_EDIT_POINT); + } else { + uv_prev.push_back(tuv); + uv_drag_index = uv_prev.size() - 1; + uv_drag_from = tuv; + } + node->set_polygon(uv_prev); + node->set_uv(uv_prev); + } + } + if (uv_move_current == UV_MODE_EDIT_POINT) { if (mb->get_shift() && mb->get_command()) @@ -230,11 +316,120 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_drag = false; } } - } else if (uv_drag) { + + if (uv_move_current == UV_MODE_ADD_SPLIT) { + + int drag_index = -1; + drag_index = -1; + for (int i = 0; i < uv_prev.size(); i++) { + + Vector2 tuv = mtx.xform(uv_prev[i]); + if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) { + drag_index = i; + } + } + + if (drag_index == -1) { + split_create = false; + return; + } + + if (split_create) { + + split_create = false; + if (drag_index < uv_drag_index) { + SWAP(drag_index, uv_drag_index); + } + bool valid = true; + if (drag_index == uv_drag_index) { + valid = false; + } + if (drag_index + 1 == uv_drag_index) { + //not a split,goes along the edge + valid = false; + } + if (drag_index == uv_prev.size() - 1 && uv_drag_index == 0) { + //not a split,goes along the edge + valid = false; + } + for (int i = 0; i < splits_prev.size(); i += 2) { + if (splits_prev[i] == uv_drag_index && splits_prev[i + 1] == drag_index) { + //already exists + valid = false; + } + if (splits_prev[i] > uv_drag_index && splits_prev[i + 1] > drag_index) { + //crossing + valid = false; + } + + if (splits_prev[i] < uv_drag_index && splits_prev[i + 1] < drag_index) { + //crossing opposite direction + valid = false; + } + } + + if (valid) { + + splits_prev.push_back(uv_drag_index); + splits_prev.push_back(drag_index); + + undo_redo->create_action(TTR("Add Split")); + + undo_redo->add_do_method(node, "set_splits", splits_prev); + undo_redo->add_undo_method(node, "set_splits", node->get_splits()); + undo_redo->add_do_method(uv_edit_draw, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); + undo_redo->commit_action(); + } else { + error->set_text(TTR("Invalid Split")); + error->popup_centered_minsize(); + } + + } else { + uv_drag_index = drag_index; + split_create = true; + uv_create_to = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); + } + } + + if (uv_move_current == UV_MODE_REMOVE_SPLIT) { + + for (int i = 0; i < splits_prev.size(); i += 2) { + if (splits_prev[i] < 0 || splits_prev[i] >= uv_prev.size()) + continue; + if (splits_prev[i + 1] < 0 || splits_prev[i] >= uv_prev.size()) + continue; + Vector2 e[2] = { mtx.xform(uv_prev[splits_prev[i]]), mtx.xform(uv_prev[splits_prev[i + 1]]) }; + Vector2 mp = Vector2(mb->get_position().x, mb->get_position().y); + Vector2 cp = Geometry::get_closest_point_to_segment_2d(mp, e); + if (cp.distance_to(mp) < 8) { + splits_prev.remove(i); + splits_prev.remove(i); + + undo_redo->create_action(TTR("Remove Split")); + + undo_redo->add_do_method(node, "set_splits", splits_prev); + undo_redo->add_undo_method(node, "set_splits", node->get_splits()); + undo_redo->add_do_method(uv_edit_draw, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); + undo_redo->commit_action(); + + break; + } + } + } + + } else if (uv_drag && !uv_create) { undo_redo->create_action(TTR("Transform UV Map")); - undo_redo->add_do_method(node, "set_uv", node->get_uv()); - undo_redo->add_undo_method(node, "set_uv", uv_prev); + + if (uv_edit_mode[0]->is_pressed()) { //edit uv + undo_redo->add_do_method(node, "set_uv", node->get_uv()); + undo_redo->add_undo_method(node, "set_uv", uv_prev); + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); + undo_redo->add_undo_method(node, "set_polygon", uv_prev); + } undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); @@ -244,10 +439,25 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { - if (uv_drag) { + if (uv_create) { uv_drag = false; - node->set_uv(uv_prev); + uv_create = false; + node->set_uv(uv_create_uv_prev); + node->set_polygon(uv_create_poly_prev); + node->set_splits(splits_prev); + uv_edit_draw->update(); + } else if (uv_drag) { + + uv_drag = false; + if (uv_edit_mode[0]->is_pressed()) { //edit uv + node->set_uv(uv_prev); + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + node->set_polygon(uv_prev); + } + uv_edit_draw->update(); + } else if (split_create) { + split_create = false; uv_edit_draw->update(); } @@ -277,11 +487,21 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { switch (uv_move_current) { + case UV_MODE_CREATE: { + if (uv_create) { + uv_create_to = mtx.affine_inverse().xform(Vector2(mm->get_position().x, mm->get_position().y)); + } + } break; case UV_MODE_EDIT_POINT: { PoolVector<Vector2> uv_new = uv_prev; uv_new.set(uv_drag_index, uv_new[uv_drag_index] + drag); - node->set_uv(uv_new); + + if (uv_edit_mode[0]->is_pressed()) { //edit uv + node->set_uv(uv_new); + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + node->set_polygon(uv_new); + } } break; case UV_MODE_MOVE: { @@ -289,7 +509,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { for (int i = 0; i < uv_new.size(); i++) uv_new.set(i, uv_new[i] + drag); - node->set_uv(uv_new); + if (uv_edit_mode[0]->is_pressed()) { //edit uv + node->set_uv(uv_new); + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + node->set_polygon(uv_new); + } } break; case UV_MODE_ROTATE: { @@ -309,7 +533,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_new.set(i, center + rel); } - node->set_uv(uv_new); + if (uv_edit_mode[0]->is_pressed()) { //edit uv + node->set_uv(uv_new); + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + node->set_polygon(uv_new); + } } break; case UV_MODE_SCALE: { @@ -334,10 +562,17 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_new.set(i, center + rel); } - node->set_uv(uv_new); + if (uv_edit_mode[0]->is_pressed()) { //edit uv + node->set_uv(uv_new); + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + node->set_polygon(uv_new); + } } break; } uv_edit_draw->update(); + } else if (split_create) { + uv_create_to = mtx.affine_inverse().xform(Vector2(mm->get_position().x, mm->get_position().y)); + uv_edit_draw->update(); } } @@ -407,7 +642,13 @@ void Polygon2DEditor::_uv_draw() { } } - PoolVector<Vector2> uvs = node->get_uv(); + PoolVector<Vector2> uvs; + if (uv_edit_mode[0]->is_pressed()) { //edit uv + uvs = node->get_uv(); + } else { //edit polygon + uvs = node->get_polygon(); + } + Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); Rect2 rect(Point2(), mtx.basis_xform(base_tex->get_size())); @@ -416,11 +657,31 @@ void Polygon2DEditor::_uv_draw() { for (int i = 0; i < uvs.size(); i++) { int next = (i + 1) % uvs.size(); - uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(uvs[next]), Color(0.9, 0.5, 0.5), 2); + Vector2 next_point = uvs[next]; + if (uv_create && i == uvs.size() - 1) { + next_point = uv_create_to; + } + uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), Color(0.9, 0.5, 0.5), 2); uv_edit_draw->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5); rect.expand_to(mtx.basis_xform(uvs[i])); } + if (split_create) { + Vector2 from = uvs[uv_drag_index]; + Vector2 to = uv_create_to; + uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), Color(0.9, 0.5, 0.5), 2); + } + + PoolVector<int> splits = node->get_splits(); + + for (int i = 0; i < splits.size(); i += 2) { + int idx_from = splits[i]; + int idx_to = splits[i + 1]; + if (idx_from < 0 || idx_to >= uvs.size()) + continue; + uv_edit_draw->draw_line(mtx.xform(uvs[idx_from]), mtx.xform(uvs[idx_to]), Color(0.9, 0.5, 0.5), 2); + } + rect = rect.grow(200); updating_uv_scroll = true; uv_hscroll->set_min(rect.position.x); @@ -449,6 +710,7 @@ void Polygon2DEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_snap_off_y"), &Polygon2DEditor::_set_snap_off_y); ClassDB::bind_method(D_METHOD("_set_snap_step_x"), &Polygon2DEditor::_set_snap_step_x); ClassDB::bind_method(D_METHOD("_set_snap_step_y"), &Polygon2DEditor::_set_snap_step_y); + ClassDB::bind_method(D_METHOD("_uv_edit_mode_select"), &Polygon2DEditor::_uv_edit_mode_select); } Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const { @@ -481,6 +743,34 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit->add_child(uv_main_vb); //uv_edit->set_child_rect(uv_main_vb); HBoxContainer *uv_mode_hb = memnew(HBoxContainer); + + uv_edit_group.instance(); + + uv_edit_mode[0] = memnew(ToolButton); + uv_mode_hb->add_child(uv_edit_mode[0]); + uv_edit_mode[0]->set_toggle_mode(true); + uv_edit_mode[1] = memnew(ToolButton); + uv_mode_hb->add_child(uv_edit_mode[1]); + uv_edit_mode[1]->set_toggle_mode(true); + uv_edit_mode[2] = memnew(ToolButton); + uv_mode_hb->add_child(uv_edit_mode[2]); + uv_edit_mode[2]->set_toggle_mode(true); + + uv_edit_mode[0]->set_text(TTR("UV")); + uv_edit_mode[0]->set_pressed(true); + uv_edit_mode[1]->set_text(TTR("Poly")); + uv_edit_mode[2]->set_text(TTR("Splits")); + + uv_edit_mode[0]->set_button_group(uv_edit_group); + uv_edit_mode[1]->set_button_group(uv_edit_group); + uv_edit_mode[2]->set_button_group(uv_edit_group); + + uv_edit_mode[0]->connect("pressed", this, "_uv_edit_mode_select", varray(0)); + uv_edit_mode[1]->connect("pressed", this, "_uv_edit_mode_select", varray(1)); + uv_edit_mode[2]->connect("pressed", this, "_uv_edit_mode_select", varray(2)); + + uv_mode_hb->add_child(memnew(VSeparator)); + uv_main_vb->add_child(uv_mode_hb); for (int i = 0; i < UV_MODE_MAX; i++) { @@ -491,12 +781,18 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_button[i]->set_focus_mode(FOCUS_NONE); } - uv_button[0]->set_tooltip(TTR("Move Point") + "\n" + TTR("Ctrl: Rotate") + "\n" + TTR("Shift: Move All") + "\n" + TTR("Shift+Ctrl: Scale")); - uv_button[1]->set_tooltip(TTR("Move Polygon")); - uv_button[2]->set_tooltip(TTR("Rotate Polygon")); - uv_button[3]->set_tooltip(TTR("Scale Polygon")); - - uv_button[0]->set_pressed(true); + uv_button[0]->set_tooltip(TTR("Create Polygon")); + uv_button[1]->set_tooltip(TTR("Move Point") + "\n" + TTR("Ctrl: Rotate") + "\n" + TTR("Shift: Move All") + "\n" + TTR("Shift+Ctrl: Scale")); + uv_button[2]->set_tooltip(TTR("Move Polygon")); + uv_button[3]->set_tooltip(TTR("Rotate Polygon")); + uv_button[4]->set_tooltip(TTR("Scale Polygon")); + uv_button[5]->set_tooltip(TTR("Connect two points to make a split")); + uv_button[6]->set_tooltip(TTR("Select a split to erase it")); + + uv_button[0]->hide(); + uv_button[5]->hide(); + uv_button[6]->hide(); + uv_button[1]->set_pressed(true); HBoxContainer *uv_main_hb = memnew(HBoxContainer); uv_main_vb->add_child(uv_main_hb); uv_edit_draw = memnew(Control); @@ -602,7 +898,9 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_draw_zoom = 1.0; uv_drag_index = -1; uv_drag = false; + uv_create = false; updating_uv_scroll = false; + split_create = false; error = memnew(AcceptDialog); add_child(error); diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index f1472e4522..8631ffb9a7 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -50,18 +50,24 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { }; enum UVMode { + UV_MODE_CREATE, UV_MODE_EDIT_POINT, UV_MODE_MOVE, UV_MODE_ROTATE, UV_MODE_SCALE, + UV_MODE_ADD_SPLIT, + UV_MODE_REMOVE_SPLIT, UV_MODE_MAX }; + ToolButton *uv_edit_mode[3]; + Ref<ButtonGroup> uv_edit_group; + Polygon2D *node; UVMode uv_mode; AcceptDialog *uv_edit; - ToolButton *uv_button[4]; + ToolButton *uv_button[UV_MODE_MAX]; ToolButton *b_snap_enable; ToolButton *b_snap_grid; Control *uv_edit_draw; @@ -75,8 +81,15 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { Vector2 uv_draw_ofs; float uv_draw_zoom; PoolVector<Vector2> uv_prev; + PoolVector<Vector2> uv_create_uv_prev; + PoolVector<Vector2> uv_create_poly_prev; + PoolVector<int> splits_prev; + + Vector2 uv_create_to; int uv_drag_index; bool uv_drag; + bool uv_create; + bool split_create; UVMode uv_move_current; Vector2 uv_drag_from; bool updating_uv_scroll; @@ -104,6 +117,8 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { void _set_snap_step_x(float p_val); void _set_snap_step_y(float p_val); + void _uv_edit_mode_select(int p_mode); + protected: virtual Node2D *_get_node() const; virtual void _set_node(Node *p_polygon); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index bd8c502a80..09388870f1 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -312,7 +312,7 @@ void ScriptEditor::_goto_script_line2(int p_line) { void ScriptEditor::_goto_script_line(REF p_script, int p_line) { Ref<Script> script = Object::cast_to<Script>(*p_script); - if (!script.is_null() && script->get_path().is_resource_file()) { + if (!script.is_null() && script->has_source_code()) { if (edit(p_script, p_line, 0)) { editor->push_item(p_script.ptr()); @@ -505,7 +505,7 @@ void ScriptEditor::_show_error_dialog(String p_path) { error_dialog->popup_centered_minsize(); } -void ScriptEditor::_close_tab(int p_idx, bool p_save) { +void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { int selected = p_idx; if (selected < 0 || selected >= tab_container->get_child_count()) @@ -521,7 +521,9 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save) { } // roll back to previous tab - _history_back(); + if (p_history_back) { + _history_back(); + } //remove from history history.resize(history_pos + 1); @@ -579,7 +581,7 @@ void ScriptEditor::_close_docs_tab() { EditorHelp *se = Object::cast_to<EditorHelp>(tab_container->get_child(i)); if (se) { - _close_tab(i); + _close_tab(i, true, false); } } } @@ -1576,6 +1578,9 @@ void ScriptEditor::_update_script_names() { case SORT_BY_PATH: { sd.sort_key = path; } break; + case SORT_BY_NONE: { + sd.sort_key = ""; + } break; } switch (display_as) { @@ -2572,8 +2577,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { waiting_update_names = false; pending_auto_reload = false; auto_reload_running_scripts = false; - members_overview_enabled = true; - help_overview_enabled = true; + members_overview_enabled = EditorSettings::get_singleton()->get("text_editor/open_scripts/show_members_overview"); + help_overview_enabled = EditorSettings::get_singleton()->get("text_editor/help/show_help_index"); editor = p_editor; VBoxContainer *main_container = memnew(VBoxContainer); @@ -2815,9 +2820,9 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { //debugger_gui->hide(); edit_pass = 0; - trim_trailing_whitespace_on_save = false; - convert_indent_on_save = false; - use_space_indentation = false; + trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/files/trim_trailing_whitespace_on_save"); + convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/indent/convert_indent_on_save"); + use_space_indentation = EditorSettings::get_singleton()->get("text_editor/indent/type"); ScriptServer::edit_request_func = _open_script_request; @@ -2926,7 +2931,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) { EDITOR_DEF("text_editor/open_scripts/script_temperature_history_size", 15); EDITOR_DEF("text_editor/open_scripts/current_script_background_color", Color(1, 1, 1, 0.3)); EDITOR_DEF("text_editor/open_scripts/group_help_pages", true); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/sort_scripts_by", PROPERTY_HINT_ENUM, "Name,Path")); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/sort_scripts_by", PROPERTY_HINT_ENUM, "Name,Path,None")); EDITOR_DEF("text_editor/open_scripts/sort_scripts_by", 0); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/list_script_names_as", PROPERTY_HINT_ENUM, "Name,Parent Directory And Name,Full Path")); EDITOR_DEF("text_editor/open_scripts/list_script_names_as", 0); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index e98a4c97a6..bcc604d990 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -165,6 +165,7 @@ class ScriptEditor : public PanelContainer { enum ScriptSortBy { SORT_BY_NAME, SORT_BY_PATH, + SORT_BY_NONE }; enum ScriptListName { @@ -251,7 +252,7 @@ class ScriptEditor : public PanelContainer { void _show_error_dialog(String p_path); - void _close_tab(int p_idx, bool p_save = true); + void _close_tab(int p_idx, bool p_save = true, bool p_history_back = true); void _close_current_tab(); void _close_discard_current_tab(const String &p_str); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 87e92f0807..c8ea2f79fe 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -349,7 +349,12 @@ void ScriptTextEditor::_convert_case(CaseStyle p_case) { int end_col = te->get_selection_to_column(); for (int i = begin; i <= end; i++) { - String new_line = te->get_line(i); + int len = te->get_line(i).length(); + if (i == end) + len -= len - end_col; + if (i == begin) + len -= begin_col; + String new_line = te->get_line(i).substr(i == begin ? begin_col : 0, len); switch (p_case) { case UPPER: { @@ -364,10 +369,10 @@ void ScriptTextEditor::_convert_case(CaseStyle p_case) { } if (i == begin) { - new_line = te->get_line(i).left(begin_col) + new_line.right(begin_col); + new_line = te->get_line(i).left(begin_col) + new_line; } if (i == end) { - new_line = new_line.left(end_col) + te->get_line(i).right(end_col); + new_line = new_line + te->get_line(i).right(end_col); } te->set_line(i, new_line); } @@ -935,13 +940,27 @@ void ScriptTextEditor::_edit_option(int p_op) { Ref<Script> scr = get_edited_script(); if (scr.is_null()) return; - tx->begin_complex_operation(); - int line = tx->cursor_get_line(); - tx->set_line(tx->cursor_get_line(), ""); - tx->backspace_at_cursor(); - tx->unfold_line(line); - tx->cursor_set_line(line); + if (tx->is_selection_active()) { + int to_line = tx->get_selection_to_line(); + int from_line = tx->get_selection_from_line(); + int count = Math::abs(to_line - from_line) + 1; + while (count) { + tx->set_line(tx->cursor_get_line(), ""); + tx->backspace_at_cursor(); + count--; + if (count) + tx->unfold_line(from_line); + } + tx->cursor_set_line(from_line - 1); + tx->deselect(); + } else { + int line = tx->cursor_get_line(); + tx->set_line(tx->cursor_get_line(), ""); + tx->backspace_at_cursor(); + tx->unfold_line(line); + tx->cursor_set_line(line); + } tx->end_complex_operation(); } break; case EDIT_CLONE_DOWN: { diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp new file mode 100644 index 0000000000..6bf94b95eb --- /dev/null +++ b/editor/plugins/skeleton_2d_editor_plugin.cpp @@ -0,0 +1,115 @@ +#include "skeleton_2d_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "scene/2d/mesh_instance_2d.h" +#include "scene/gui/box_container.h" +#include "thirdparty/misc/clipper.hpp" + +void Skeleton2DEditor::_node_removed(Node *p_node) { + + if (p_node == node) { + node = NULL; + options->hide(); + } +} + +void Skeleton2DEditor::edit(Skeleton2D *p_sprite) { + + node = p_sprite; +} + +void Skeleton2DEditor::_menu_option(int p_option) { + + switch (p_option) { + case MENU_OPTION_MAKE_REST: { + + if (node->get_bone_count() == 0) { + err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes.")); + err_dialog->popup_centered_minsize(); + return; + } + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("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()); + ur->add_undo_method(bone, "set_rest", bone->get_rest()); + } + ur->commit_action(); + + } break; + case MENU_OPTION_SET_REST: { + if (node->get_bone_count() == 0) { + err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes.")); + err_dialog->popup_centered_minsize(); + return; + } + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("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()); + ur->add_undo_method(bone, "set_transform", bone->get_transform()); + } + ur->commit_action(); + + } break; + } +} + +void Skeleton2DEditor::_bind_methods() { + + ClassDB::bind_method("_menu_option", &Skeleton2DEditor::_menu_option); +} + +Skeleton2DEditor::Skeleton2DEditor() { + + options = memnew(MenuButton); + + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options); + + options->set_text(TTR("Skeleton2D")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Skeleton2D", "EditorIcons")); + + options->get_popup()->add_item(TTR("Make Rest Pose (From Bones)"), MENU_OPTION_MAKE_REST); + options->get_popup()->add_separator(); + options->get_popup()->add_item(TTR("Set Bones to Rest Pose"), MENU_OPTION_SET_REST); + + options->get_popup()->connect("id_pressed", this, "_menu_option"); + + err_dialog = memnew(AcceptDialog); + add_child(err_dialog); +} + +void Skeleton2DEditorPlugin::edit(Object *p_object) { + + sprite_editor->edit(Object::cast_to<Skeleton2D>(p_object)); +} + +bool Skeleton2DEditorPlugin::handles(Object *p_object) const { + + return p_object->is_class("Skeleton2D"); +} + +void Skeleton2DEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + sprite_editor->options->show(); + } else { + + sprite_editor->options->hide(); + sprite_editor->edit(NULL); + } +} + +Skeleton2DEditorPlugin::Skeleton2DEditorPlugin(EditorNode *p_node) { + + editor = p_node; + sprite_editor = memnew(Skeleton2DEditor); + editor->get_viewport()->add_child(sprite_editor); + + //sprite_editor->options->hide(); +} + +Skeleton2DEditorPlugin::~Skeleton2DEditorPlugin() { +} diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h new file mode 100644 index 0000000000..bbe2a3a6f2 --- /dev/null +++ b/editor/plugins/skeleton_2d_editor_plugin.h @@ -0,0 +1,55 @@ +#ifndef SKELETON_2D_EDITOR_PLUGIN_H +#define SKELETON_2D_EDITOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/2d/skeleton_2d.h" +#include "scene/gui/spin_box.h" + +class Skeleton2DEditor : public Control { + + GDCLASS(Skeleton2DEditor, Control); + + enum Menu { + MENU_OPTION_MAKE_REST, + MENU_OPTION_SET_REST, + }; + + Skeleton2D *node; + + MenuButton *options; + AcceptDialog *err_dialog; + + void _menu_option(int p_option); + + //void _create_uv_lines(); + friend class Skeleton2DEditorPlugin; + +protected: + void _node_removed(Node *p_node); + static void _bind_methods(); + +public: + void edit(Skeleton2D *p_sprite); + Skeleton2DEditor(); +}; + +class Skeleton2DEditorPlugin : public EditorPlugin { + + GDCLASS(Skeleton2DEditorPlugin, EditorPlugin); + + Skeleton2DEditor *sprite_editor; + EditorNode *editor; + +public: + virtual String get_name() const { return "Skeleton2D"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_object); + virtual bool handles(Object *p_object) const; + virtual void make_visible(bool p_visible); + + Skeleton2DEditorPlugin(EditorNode *p_node); + ~Skeleton2DEditorPlugin(); +}; + +#endif // SKELETON_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 63762651d7..9e7bfd5787 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -4282,67 +4282,26 @@ void SpatialEditor::_init_indicators() { indicator_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); indicator_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - PoolVector<Color> grid_colors[3]; - PoolVector<Vector3> grid_points[3]; Vector<Color> origin_colors; Vector<Vector3> origin_points; - Color grid_color = EditorSettings::get_singleton()->get("editors/3d/grid_color"); - for (int i = 0; i < 3; i++) { Vector3 axis; axis[i] = 1; - Vector3 axis_n1; - axis_n1[(i + 1) % 3] = 1; - Vector3 axis_n2; - axis_n2[(i + 2) % 3] = 1; + + grid_enable[i] = false; + grid_visible[i] = false; origin_colors.push_back(Color(axis.x, axis.y, axis.z)); origin_colors.push_back(Color(axis.x, axis.y, axis.z)); origin_points.push_back(axis * 4096); origin_points.push_back(axis * -4096); -#define ORIGIN_GRID_SIZE 50 - - for (int j = -ORIGIN_GRID_SIZE; j <= ORIGIN_GRID_SIZE; j++) { - - Vector3 p1 = axis_n1 * j + axis_n2 * -ORIGIN_GRID_SIZE; - Vector3 p1_dest = p1 * (-axis_n2 + axis_n1); - Vector3 p2 = axis_n2 * j + axis_n1 * -ORIGIN_GRID_SIZE; - Vector3 p2_dest = p2 * (-axis_n1 + axis_n2); - - Color line_color = grid_color; - if (j == 0) { - continue; - } else if (j % 10 == 0) { - line_color *= 1.5; - } - - grid_points[i].push_back(p1); - grid_points[i].push_back(p1_dest); - grid_colors[i].push_back(line_color); - grid_colors[i].push_back(line_color); - - grid_points[i].push_back(p2); - grid_points[i].push_back(p2_dest); - grid_colors[i].push_back(line_color); - grid_colors[i].push_back(line_color); - } + } - grid[i] = VisualServer::get_singleton()->mesh_create(); - Array d; - d.resize(VS::ARRAY_MAX); - d[VisualServer::ARRAY_VERTEX] = grid_points[i]; - d[VisualServer::ARRAY_COLOR] = grid_colors[i]; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], VisualServer::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); - grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario()); + grid_enable[1] = true; + grid_visible[1] = true; - grid_visible[i] = false; - grid_enable[i] = false; - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], false); - VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << SpatialEditorViewport::GIZMO_GRID_LAYER); - } + _init_grid(); origin = VisualServer::get_singleton()->mesh_create(); Array d; @@ -4358,9 +4317,6 @@ void SpatialEditor::_init_indicators() { VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, VS::SHADOW_CASTING_SETTING_OFF); - VisualServer::get_singleton()->instance_set_visible(grid_instance[1], true); - grid_enable[1] = true; - grid_visible[1] = true; grid_enabled = true; last_grid_snap = 1; } @@ -4629,10 +4585,71 @@ void SpatialEditor::_init_indicators() { _generate_selection_box(); } +void SpatialEditor::_init_grid() { + + PoolVector<Color> grid_colors[3]; + PoolVector<Vector3> grid_points[3]; + + Color grid_color = EditorSettings::get_singleton()->get("editors/3d/grid_color"); + + for (int i = 0; i < 3; i++) { + Vector3 axis; + axis[i] = 1; + Vector3 axis_n1; + axis_n1[(i + 1) % 3] = 1; + Vector3 axis_n2; + axis_n2[(i + 2) % 3] = 1; + +#define ORIGIN_GRID_SIZE 50 + + for (int j = -ORIGIN_GRID_SIZE; j <= ORIGIN_GRID_SIZE; j++) { + Vector3 p1 = axis_n1 * j + axis_n2 * -ORIGIN_GRID_SIZE; + Vector3 p1_dest = p1 * (-axis_n2 + axis_n1); + Vector3 p2 = axis_n2 * j + axis_n1 * -ORIGIN_GRID_SIZE; + Vector3 p2_dest = p2 * (-axis_n1 + axis_n2); + + Color line_color = grid_color; + if (j == 0) { + continue; + } else if (j % 10 == 0) { + line_color *= 1.5; + } + + grid_points[i].push_back(p1); + grid_points[i].push_back(p1_dest); + grid_colors[i].push_back(line_color); + grid_colors[i].push_back(line_color); + + grid_points[i].push_back(p2); + grid_points[i].push_back(p2_dest); + grid_colors[i].push_back(line_color); + grid_colors[i].push_back(line_color); + } + + grid[i] = VisualServer::get_singleton()->mesh_create(); + Array d; + d.resize(VS::ARRAY_MAX); + d[VisualServer::ARRAY_VERTEX] = grid_points[i]; + d[VisualServer::ARRAY_COLOR] = grid_colors[i]; + VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], VisualServer::PRIMITIVE_LINES, d); + VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); + grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario()); + + VisualServer::get_singleton()->instance_set_visible(grid_instance[i], grid_visible[i]); + VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], VS::SHADOW_CASTING_SETTING_OFF); + VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << SpatialEditorViewport::GIZMO_GRID_LAYER); + } +} + void SpatialEditor::_finish_indicators() { VisualServer::get_singleton()->free(origin_instance); VisualServer::get_singleton()->free(origin); + + _finish_grid(); +} + +void SpatialEditor::_finish_grid() { for (int i = 0; i < 3; i++) { VisualServer::get_singleton()->free(grid_instance[i]); VisualServer::get_singleton()->free(grid[i]); @@ -4674,6 +4691,8 @@ void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) { if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack()) return; + snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + Ref<InputEventKey> k = p_event; if (k.is_valid()) { @@ -4770,6 +4789,10 @@ void SpatialEditor::_notification(int p_what) { view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_icon("Panels3", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_icon("Panels3Alt", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_icon("Panels4", "EditorIcons")); + + // Update grid color by rebuilding grid. + _finish_grid(); + _init_grid(); } } @@ -4941,6 +4964,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { editor_selection->add_editor_plugin(this); snap_enabled = false; + snap_key_enabled = false; tool_mode = TOOL_MODE_SELECT; hbc_menu = memnew(HBoxContainer); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 55866cac99..7736db67b1 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -505,6 +505,7 @@ private: ConfirmationDialog *settings_dialog; bool snap_enabled; + bool snap_key_enabled; LineEdit *snap_translate; LineEdit *snap_rotate; LineEdit *snap_scale; @@ -531,7 +532,9 @@ private: void _instance_scene(); void _init_indicators(); + void _init_grid(); void _finish_indicators(); + void _finish_grid(); void _toggle_maximize_view(Object *p_viewport); @@ -577,7 +580,7 @@ public: ToolMode get_tool_mode() const { return tool_mode; } bool are_local_coords_enabled() const { return tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); } - bool is_snap_enabled() const { return snap_enabled; } + bool is_snap_enabled() const { return snap_enabled ^ snap_key_enabled; } float get_translate_snap() const { return snap_translate->get_text().to_double(); } float get_rotate_snap() const { return snap_rotate->get_text().to_double(); } float get_scale_snap() const { return snap_scale->get_text().to_double(); } diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp new file mode 100644 index 0000000000..99aabcb3eb --- /dev/null +++ b/editor/plugins/sprite_editor_plugin.cpp @@ -0,0 +1,397 @@ +#include "sprite_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "scene/2d/mesh_instance_2d.h" +#include "scene/gui/box_container.h" +#include "thirdparty/misc/clipper.hpp" + +void SpriteEditor::_node_removed(Node *p_node) { + + if (p_node == node) { + node = NULL; + options->hide(); + } +} + +void SpriteEditor::edit(Sprite *p_sprite) { + + node = p_sprite; +} + +#define PRECISION 10.0 + +Vector<Vector2> expand(const Vector<Vector2> &points, const Rect2i &rect, float epsilon = 2.0) { + int size = points.size(); + ERR_FAIL_COND_V(size < 2, Vector<Vector2>()); + + ClipperLib::Path subj; + ClipperLib::PolyTree solution; + ClipperLib::PolyTree out; + + for (int i = 0; i < points.size(); i++) { + + subj << ClipperLib::IntPoint(points[i].x * PRECISION, points[i].y * PRECISION); + } + ClipperLib::ClipperOffset co; + co.AddPath(subj, ClipperLib::jtMiter, ClipperLib::etClosedPolygon); + co.Execute(solution, epsilon * PRECISION); + + ClipperLib::PolyNode *p = solution.GetFirst(); + + ERR_FAIL_COND_V(!p, points); + + while (p->IsHole()) { + p = p->GetNext(); + } + + //turn the result into simply polygon (AKA, fix overlap) + + //clamp into the specified rect + ClipperLib::Clipper cl; + cl.StrictlySimple(true); + cl.AddPath(p->Contour, ClipperLib::ptSubject, true); + //create the clipping rect + ClipperLib::Path clamp; + clamp.push_back(ClipperLib::IntPoint(0, 0)); + clamp.push_back(ClipperLib::IntPoint(rect.size.width * PRECISION, 0)); + clamp.push_back(ClipperLib::IntPoint(rect.size.width * PRECISION, rect.size.height * PRECISION)); + clamp.push_back(ClipperLib::IntPoint(0, rect.size.height * PRECISION)); + cl.AddPath(clamp, ClipperLib::ptClip, true); + cl.Execute(ClipperLib::ctIntersection, out); + + Vector<Vector2> outPoints; + ClipperLib::PolyNode *p2 = out.GetFirst(); + while (p2->IsHole()) { + p2 = p2->GetNext(); + } + + int lasti = p2->Contour.size() - 1; + Vector2 prev = Vector2(p2->Contour[lasti].X / PRECISION, p2->Contour[lasti].Y / PRECISION); + for (int i = 0; i < p2->Contour.size(); i++) { + + Vector2 cur = Vector2(p2->Contour[i].X / PRECISION, p2->Contour[i].Y / PRECISION); + if (cur.distance_to(prev) > 0.5) { + outPoints.push_back(cur); + prev = cur; + } + } + return outPoints; +} + +void SpriteEditor::_menu_option(int p_option) { + + switch (p_option) { + case MENU_OPTION_CREATE_MESH_2D: { + + _update_mesh_data(); + debug_uv_dialog->popup_centered(); + debug_uv->update(); + + } break; + } +} + +void SpriteEditor::_update_mesh_data() { + + Ref<Texture> texture = node->get_texture(); + if (texture.is_null()) { + err_dialog->set_text(TTR("Sprite is empty!")); + err_dialog->popup_centered_minsize(); + return; + } + + if (node->get_hframes() > 1 || node->get_vframes() > 1) { + err_dialog->set_text(TTR("Can't convert a sprite using animation frames to mesh.")); + err_dialog->popup_centered_minsize(); + return; + } + Ref<Image> image = texture->get_data(); + ERR_FAIL_COND(image.is_null()); + Rect2 rect; + if (node->is_region()) + rect = node->get_region_rect(); + else + rect.size = Size2(image->get_width(), image->get_height()); + + Ref<BitMap> bm; + bm.instance(); + bm->create_from_image_alpha(image); + + int grow = island_merging->get_value(); + if (grow > 0) { + bm->grow_mask(grow, rect); + } + + float epsilon = simplification->get_value(); + + Vector<Vector<Vector2> > lines = bm->clip_opaque_to_polygons(rect, epsilon); + + print_line("lines: " + itos(lines.size())); + uv_lines.clear(); + + computed_vertices.clear(); + computed_uv.clear(); + computed_indices.clear(); + + Size2 img_size = Vector2(image->get_width(), image->get_height()); + for (int j = 0; j < lines.size(); j++) { + lines[j] = expand(lines[j], rect, epsilon); + + int index_ofs = computed_vertices.size(); + + for (int i = 0; i < lines[j].size(); i++) { + Vector2 vtx = lines[j][i]; + computed_uv.push_back(vtx / img_size); + + vtx -= rect.position; //offset by rect position + + //flip if flipped + if (node->is_flipped_h()) + vtx.x = rect.size.x - vtx.x - 1.0; + if (node->is_flipped_v()) + vtx.y = rect.size.y - vtx.y - 1.0; + + if (node->is_centered()) + vtx -= rect.size / 2.0; + + computed_vertices.push_back(vtx); + } +#if 0 + Vector<Vector<Vector2> > polys = Geometry::decompose_polygon(lines[j]); + print_line("polygon: " + itos(polys.size())); + + for (int i = 0; i < polys.size(); i++) { + for (int k = 0; k < polys[i].size(); k++) { + + int idxn = (k + 1) % polys[i].size(); + uv_lines.push_back(polys[i][k]); + uv_lines.push_back(polys[i][idxn]); + } + } +#endif + +#if 1 + + Vector<int> poly = Geometry::triangulate_polygon(lines[j]); + + for (int i = 0; i < poly.size(); i += 3) { + for (int k = 0; k < 3; k++) { + int idx = i + k; + int idxn = i + (k + 1) % 3; + uv_lines.push_back(lines[j][poly[idx]]); + uv_lines.push_back(lines[j][poly[idxn]]); + + computed_indices.push_back(poly[idx] + index_ofs); + } + } +#endif + +#if 0 + for (int i = 0; i < lines[j].size() - 1; i++) { + uv_lines.push_back(lines[j][i]); + uv_lines.push_back(lines[j][i + 1]); + } +#endif + } + + debug_uv->update(); +} + +void SpriteEditor::_create_mesh_node() { + + if (computed_vertices.size() < 3) { + err_dialog->set_text(TTR("Invalid geometry, can't replace by mesh.")); + err_dialog->popup_centered_minsize(); + return; + } + + Ref<ArrayMesh> mesh; + mesh.instance(); + + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX] = computed_vertices; + a[Mesh::ARRAY_TEX_UV] = computed_uv; + a[Mesh::ARRAY_INDEX] = computed_indices; + + mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Mesh::ARRAY_FLAG_USE_2D_VERTICES); + + MeshInstance2D *mesh_instance = memnew(MeshInstance2D); + mesh_instance->set_mesh(mesh); + EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, mesh_instance); +} + +#if 0 +void SpriteEditor::_create_uv_lines() { + + Ref<Mesh> sprite = node->get_sprite(); + ERR_FAIL_COND(!sprite.is_valid()); + + Set<SpriteEditorEdgeSort> edges; + uv_lines.clear(); + for (int i = 0; i < sprite->get_surface_count(); i++) { + if (sprite->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) + continue; + Array a = sprite->surface_get_arrays(i); + + PoolVector<Vector2> uv = a[p_layer == 0 ? Mesh::ARRAY_TEX_UV : Mesh::ARRAY_TEX_UV2]; + if (uv.size() == 0) { + err_dialog->set_text(TTR("Model has no UV in this layer")); + err_dialog->popup_centered_minsize(); + return; + } + + PoolVector<Vector2>::Read r = uv.read(); + + PoolVector<int> indices = a[Mesh::ARRAY_INDEX]; + PoolVector<int>::Read ri; + + int ic; + bool use_indices; + + if (indices.size()) { + ic = indices.size(); + ri = indices.read(); + use_indices = true; + } else { + ic = uv.size(); + use_indices = false; + } + + for (int j = 0; j < ic; j += 3) { + + for (int k = 0; k < 3; k++) { + + SpriteEditorEdgeSort edge; + if (use_indices) { + edge.a = r[ri[j + k]]; + edge.b = r[ri[j + ((k + 1) % 3)]]; + } else { + edge.a = r[j + k]; + edge.b = r[j + ((k + 1) % 3)]; + } + + if (edges.has(edge)) + continue; + + uv_lines.push_back(edge.a); + uv_lines.push_back(edge.b); + edges.insert(edge); + } + } + } + + debug_uv_dialog->popup_centered_minsize(); +} +#endif +void SpriteEditor::_debug_uv_draw() { + + if (uv_lines.size() == 0) + return; + + Ref<Texture> tex = node->get_texture(); + ERR_FAIL_COND(!tex.is_valid()); + debug_uv->set_clip_contents(true); + debug_uv->draw_texture(tex, Point2()); + debug_uv->set_custom_minimum_size(tex->get_size()); + //debug_uv->draw_set_transform(Vector2(), 0, debug_uv->get_size()); + debug_uv->draw_multiline(uv_lines, Color(1.0, 0.8, 0.7)); +} + +void SpriteEditor::_bind_methods() { + + ClassDB::bind_method("_menu_option", &SpriteEditor::_menu_option); + ClassDB::bind_method("_debug_uv_draw", &SpriteEditor::_debug_uv_draw); + ClassDB::bind_method("_update_mesh_data", &SpriteEditor::_update_mesh_data); + ClassDB::bind_method("_create_mesh_node", &SpriteEditor::_create_mesh_node); +} + +SpriteEditor::SpriteEditor() { + + options = memnew(MenuButton); + + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options); + + options->set_text(TTR("Sprite")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Sprite", "EditorIcons")); + + options->get_popup()->add_item(TTR("Convert to 2D Mesh"), MENU_OPTION_CREATE_MESH_2D); + + options->get_popup()->connect("id_pressed", this, "_menu_option"); + + err_dialog = memnew(AcceptDialog); + add_child(err_dialog); + + debug_uv_dialog = memnew(ConfirmationDialog); + debug_uv_dialog->get_ok()->set_text(TTR("Create 2D Mesh")); + debug_uv_dialog->set_title("Mesh 2D Preview"); + VBoxContainer *vb = memnew(VBoxContainer); + debug_uv_dialog->add_child(vb); + ScrollContainer *scroll = memnew(ScrollContainer); + scroll->set_custom_minimum_size(Size2(800, 500) * EDSCALE); + scroll->set_enable_h_scroll(true); + scroll->set_enable_v_scroll(true); + vb->add_margin_child(TTR("Preview:"), scroll, true); + debug_uv = memnew(Control); + debug_uv->connect("draw", this, "_debug_uv_draw"); + scroll->add_child(debug_uv); + debug_uv_dialog->connect("confirmed", this, "_create_mesh_node"); + + HBoxContainer *hb = memnew(HBoxContainer); + hb->add_child(memnew(Label(TTR("Simplification: ")))); + simplification = memnew(SpinBox); + simplification->set_min(0.01); + simplification->set_max(10.00); + simplification->set_step(0.01); + simplification->set_value(2); + hb->add_child(simplification); + hb->add_spacer(); + hb->add_child(memnew(Label(TTR("Grow (Pixels): ")))); + island_merging = memnew(SpinBox); + island_merging->set_min(0); + island_merging->set_max(10); + island_merging->set_step(1); + island_merging->set_value(2); + hb->add_child(island_merging); + hb->add_spacer(); + update_preview = memnew(Button); + update_preview->set_text(TTR("Update Preview")); + update_preview->connect("pressed", this, "_update_mesh_data"); + hb->add_child(update_preview); + vb->add_margin_child(TTR("Settings:"), hb); + + add_child(debug_uv_dialog); +} + +void SpriteEditorPlugin::edit(Object *p_object) { + + sprite_editor->edit(Object::cast_to<Sprite>(p_object)); +} + +bool SpriteEditorPlugin::handles(Object *p_object) const { + + return p_object->is_class("Sprite"); +} + +void SpriteEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + sprite_editor->options->show(); + } else { + + sprite_editor->options->hide(); + sprite_editor->edit(NULL); + } +} + +SpriteEditorPlugin::SpriteEditorPlugin(EditorNode *p_node) { + + editor = p_node; + sprite_editor = memnew(SpriteEditor); + editor->get_viewport()->add_child(sprite_editor); + + //sprite_editor->options->hide(); +} + +SpriteEditorPlugin::~SpriteEditorPlugin() { +} diff --git a/editor/plugins/sprite_editor_plugin.h b/editor/plugins/sprite_editor_plugin.h new file mode 100644 index 0000000000..17aa3eb1f9 --- /dev/null +++ b/editor/plugins/sprite_editor_plugin.h @@ -0,0 +1,73 @@ +#ifndef SPRITE_EDITOR_PLUGIN_H +#define SPRITE_EDITOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/2d/sprite.h" +#include "scene/gui/spin_box.h" + +class SpriteEditor : public Control { + + GDCLASS(SpriteEditor, Control); + + enum Menu { + MENU_OPTION_CREATE_MESH_2D, + }; + + Sprite *node; + + MenuButton *options; + + ConfirmationDialog *outline_dialog; + + AcceptDialog *err_dialog; + + ConfirmationDialog *debug_uv_dialog; + Control *debug_uv; + Vector<Vector2> uv_lines; + + Vector<Vector2> computed_vertices; + Vector<Vector2> computed_uv; + Vector<int> computed_indices; + + SpinBox *simplification; + SpinBox *island_merging; + Button *update_preview; + + void _menu_option(int p_option); + + //void _create_uv_lines(); + friend class SpriteEditorPlugin; + + void _debug_uv_draw(); + void _update_mesh_data(); + void _create_mesh_node(); + +protected: + void _node_removed(Node *p_node); + static void _bind_methods(); + +public: + void edit(Sprite *p_sprite); + SpriteEditor(); +}; + +class SpriteEditorPlugin : public EditorPlugin { + + GDCLASS(SpriteEditorPlugin, EditorPlugin); + + SpriteEditor *sprite_editor; + EditorNode *editor; + +public: + virtual String get_name() const { return "Sprite"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_object); + virtual bool handles(Object *p_object) const; + virtual void make_visible(bool p_visible); + + SpriteEditorPlugin(EditorNode *p_node); + ~SpriteEditorPlugin(); +}; + +#endif // SPRITE_EDITOR_PLUGIN_H diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index e04798d6d6..4367fe8976 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -57,6 +57,9 @@ void TextureRegionEditor::_region_draw() { base_tex = obj_styleBox->get_texture(); else if (atlas_tex.is_valid()) base_tex = atlas_tex->get_atlas(); + else if (tile_set.is_valid() && selected_tile != -1 && tile_set->has_tile(selected_tile)) + base_tex = tile_set->tile_get_texture(selected_tile); + if (base_tex.is_null()) return; @@ -281,6 +284,8 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { r = obj_styleBox->get_region_rect(); else if (atlas_tex.is_valid()) r = atlas_tex->get_region(); + else if (tile_set.is_valid() && selected_tile != -1) + r = tile_set->tile_get_region(selected_tile); rect.expand_to(r.position); rect.expand_to(r.position + r.size); } @@ -297,6 +302,9 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } else if (atlas_tex.is_valid()) { undo_redo->add_do_method(atlas_tex.ptr(), "set_region", rect); undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region()); + } else if (tile_set.is_valid() && selected_tile != -1) { + undo_redo->add_do_method(tile_set.ptr(), "tile_set_region", selected_tile, rect); + undo_redo->add_undo_method(tile_set.ptr(), "tile_set_region", selected_tile, tile_set->tile_get_region(selected_tile)); } undo_redo->add_do_method(edit_draw, "update"); undo_redo->add_undo_method(edit_draw, "update"); @@ -319,6 +327,8 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { rect_prev = obj_styleBox->get_region_rect(); else if (atlas_tex.is_valid()) rect_prev = atlas_tex->get_region(); + else if (tile_set.is_valid() && selected_tile != -1) + rect_prev = tile_set->tile_get_region(selected_tile); for (int i = 0; i < 8; i++) { Vector2 tuv = endpoints[i]; @@ -362,6 +372,9 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } else if (obj_styleBox.is_valid()) { undo_redo->add_do_method(obj_styleBox.ptr(), "set_region_rect", obj_styleBox->get_region_rect()); undo_redo->add_undo_method(obj_styleBox.ptr(), "set_region_rect", rect_prev); + } else if (tile_set.is_valid()) { + undo_redo->add_do_method(tile_set.ptr(), "tile_set_region", selected_tile, tile_set->tile_get_region(selected_tile)); + undo_redo->add_undo_method(tile_set.ptr(), "tile_set_region", selected_tile, rect_prev); } drag_index = -1; } @@ -582,10 +595,13 @@ void TextureRegionEditor::apply_rect(const Rect2 &rect) { obj_styleBox->set_region_rect(rect); else if (atlas_tex.is_valid()) atlas_tex->set_region(rect); + else if (tile_set.is_valid() && selected_tile != -1) + tile_set->tile_set_region(selected_tile, rect); } void TextureRegionEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_READY: { zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons")); zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); @@ -596,11 +612,12 @@ void TextureRegionEditor::_notification(int p_what) { } void TextureRegionEditor::_node_removed(Object *p_obj) { - if (p_obj == node_sprite || p_obj == node_ninepatch || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr()) { + if (p_obj == node_sprite || p_obj == node_ninepatch || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr() || p_obj == tile_set.ptr()) { node_ninepatch = NULL; node_sprite = NULL; obj_styleBox = Ref<StyleBox>(NULL); atlas_tex = Ref<AtlasTexture>(NULL); + tile_set = Ref<TileSet>(NULL); hide(); } } @@ -632,6 +649,8 @@ void TextureRegionEditor::edit(Object *p_obj) { obj_styleBox->remove_change_receptor(this); if (atlas_tex.is_valid()) atlas_tex->remove_change_receptor(this); + if (tile_set.is_valid()) + tile_set->remove_change_receptor(this); if (p_obj) { node_sprite = Object::cast_to<Sprite>(p_obj); node_ninepatch = Object::cast_to<NinePatchRect>(p_obj); @@ -639,6 +658,8 @@ void TextureRegionEditor::edit(Object *p_obj) { obj_styleBox = Ref<StyleBoxTexture>(Object::cast_to<StyleBoxTexture>(p_obj)); if (Object::cast_to<AtlasTexture>(p_obj)) atlas_tex = Ref<AtlasTexture>(Object::cast_to<AtlasTexture>(p_obj)); + if (Object::cast_to<TileSet>(p_obj)) + tile_set = Ref<TileSet>(Object::cast_to<TileSet>(p_obj)); p_obj->add_change_receptor(this); _edit_region(); } else { @@ -646,6 +667,7 @@ void TextureRegionEditor::edit(Object *p_obj) { node_ninepatch = NULL; obj_styleBox = Ref<StyleBoxTexture>(NULL); atlas_tex = Ref<AtlasTexture>(NULL); + tile_set = Ref<TileSet>(NULL); } edit_draw->update(); } @@ -668,8 +690,11 @@ void TextureRegionEditor::_edit_region() { texture = obj_styleBox->get_texture(); else if (atlas_tex.is_valid()) texture = atlas_tex->get_atlas(); + else if (tile_set.is_valid() && selected_tile != -1 && tile_set->has_tile(selected_tile)) + texture = tile_set->tile_get_texture(selected_tile); if (texture.is_null()) { + edit_draw->update(); return; } @@ -735,6 +760,8 @@ void TextureRegionEditor::_edit_region() { rect = obj_styleBox->get_region_rect(); else if (atlas_tex.is_valid()) rect = atlas_tex->get_region(); + else if (tile_set.is_valid() && selected_tile != -1) + rect = tile_set->tile_get_region(selected_tile); edit_draw->update(); } @@ -753,11 +780,14 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { node_ninepatch = NULL; obj_styleBox = Ref<StyleBoxTexture>(NULL); atlas_tex = Ref<AtlasTexture>(NULL); + tile_set = Ref<TileSet>(NULL); editor = p_editor; undo_redo = editor->get_undo_redo(); + selected_tile = -1; snap_step = Vector2(10, 10); snap_separation = Vector2(0, 0); + snap_mode = SNAP_NONE; edited_margin = -1; drag_index = -1; drag = false; @@ -903,11 +933,11 @@ bool TextureRegionEditorPlugin::handles(Object *p_object) const { void TextureRegionEditorPlugin::make_visible(bool p_visible) { if (p_visible) { - region_button->show(); - if (region_button->is_pressed()) + texture_region_button->show(); + if (texture_region_button->is_pressed()) region_editor->show(); } else { - region_button->hide(); + texture_region_button->hide(); region_editor->edit(NULL); region_editor->hide(); } @@ -961,10 +991,10 @@ TextureRegionEditorPlugin::TextureRegionEditorPlugin(EditorNode *p_node) { editor = p_node; region_editor = memnew(TextureRegionEditor(p_node)); - region_button = p_node->add_bottom_panel_item(TTR("Texture Region"), region_editor); - region_button->set_tooltip(TTR("Texture Region Editor")); + texture_region_button = p_node->add_bottom_panel_item(TTR("Texture Region"), region_editor); + texture_region_button->set_tooltip(TTR("Texture Region Editor")); region_editor->set_custom_minimum_size(Size2(0, 200)); region_editor->hide(); - region_button->hide(); + texture_region_button->hide(); } diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index cf9396bd5b..1244953a3f 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -38,6 +38,7 @@ #include "scene/gui/nine_patch_rect.h" #include "scene/resources/style_box.h" #include "scene/resources/texture.h" +#include "scene/resources/tile_set.h" /** @author Mariano Suligoy @@ -55,6 +56,8 @@ class TextureRegionEditor : public Control { }; friend class TextureRegionEditorPlugin; + friend class TileSetEditor; + friend class TileSetEditorPlugin; MenuButton *snap_mode_button; TextureRect *icon_zoom; ToolButton *zoom_in; @@ -88,12 +91,14 @@ class TextureRegionEditor : public Control { Sprite *node_sprite; Ref<StyleBoxTexture> obj_styleBox; Ref<AtlasTexture> atlas_tex; + Ref<TileSet> tile_set; Rect2 rect; Rect2 rect_prev; float prev_margin; int edited_margin; List<Rect2> autoslice_cache; + int selected_tile; bool drag; bool creating; @@ -134,7 +139,7 @@ public: class TextureRegionEditorPlugin : public EditorPlugin { GDCLASS(TextureRegionEditorPlugin, EditorPlugin); - Button *region_button; + Button *texture_region_button; TextureRegionEditor *region_editor; EditorNode *editor; diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index f51e691be3..295d9439ad 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -244,7 +244,7 @@ void ThemeEditor::_save_template_cbk(String fname) { file->store_line("; "); file->store_line("; ******************* "); file->store_line("; "); - file->store_line("; Template Generated Using: " + String(VERSION_MKSTRING)); + file->store_line("; Template Generated Using: " + String(VERSION_FULL_BUILD)); file->store_line("; "); file->store_line("; "); file->store_line(""); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index a102d99d1c..c5c7272ed2 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -48,6 +48,20 @@ void TileMapEditor::_notification(int p_what) { } break; + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + + bool new_show_tile_info = EditorSettings::get_singleton()->get("editors/tile_map/show_tile_info_on_hover"); + if (new_show_tile_info != show_tile_info) { + show_tile_info = new_show_tile_info; + tile_info->set_visible(show_tile_info); + } + + if (is_visible_in_tree()) { + _update_palette(); + } + + } // fallthrough + case NOTIFICATION_ENTER_TREE: { transp->set_icon(get_icon("Transpose", "EditorIcons")); @@ -60,19 +74,13 @@ void TileMapEditor::_notification(int p_what) { search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); - } break; - - case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - - bool new_show_tile_info = EditorSettings::get_singleton()->get("editors/tile_map/show_tile_info_on_hover"); - if (new_show_tile_info != show_tile_info) { - show_tile_info = new_show_tile_info; - tile_info->set_visible(show_tile_info); - } + PopupMenu *p = options->get_popup(); + p->set_item_icon(p->get_item_index(OPTION_PAINTING), get_icon("Edit", "EditorIcons")); + p->set_item_icon(p->get_item_index(OPTION_PICK_TILE), get_icon("ColorPick", "EditorIcons")); + p->set_item_icon(p->get_item_index(OPTION_SELECT), get_icon("ToolSelect", "EditorIcons")); + p->set_item_icon(p->get_item_index(OPTION_DUPLICATE), get_icon("Duplicate", "EditorIcons")); + p->set_item_icon(p->get_item_index(OPTION_ERASE_SELECTION), get_icon("Remove", "EditorIcons")); - if (is_visible_in_tree()) { - _update_palette(); - } } break; } } @@ -139,6 +147,15 @@ void TileMapEditor::_menu_option(int p_option) { canvas_item_editor->update(); } break; + case OPTION_FIX_INVALID: { + + undo_redo->create_action(TTR("Fix Invalid Tiles")); + undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data")); + node->fix_invalid_tiles(); + undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data")); + undo_redo->commit_action(); + + } break; } } @@ -303,7 +320,7 @@ void TileMapEditor::_update_palette() { if (tex.is_valid()) { Rect2 region = tileset->tile_get_region(entries[i].id); - if (tileset->tile_get_is_autotile(entries[i].id)) { + if (tileset->tile_get_tile_mode(entries[i].id) == TileSet::AUTO_TILE) { int spacing = tileset->autotile_get_spacing(entries[i].id); region.size = tileset->autotile_get_size(entries[i].id); region.position += (region.size + Vector2(spacing, spacing)) * tileset->autotile_get_icon_coordinate(entries[i].id); @@ -506,7 +523,7 @@ void TileMapEditor::_draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h Vector2 tile_ofs = node->get_tileset()->tile_get_texture_offset(p_cell); Rect2 r = node->get_tileset()->tile_get_region(p_cell); - if (node->get_tileset()->tile_get_is_autotile(p_cell)) { + if (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::AUTO_TILE) { int spacing = node->get_tileset()->autotile_get_spacing(p_cell); r.size = node->get_tileset()->autotile_get_size(p_cell); r.position += (r.size + Vector2(spacing, spacing)) * node->get_tileset()->autotile_get_icon_coordinate(p_cell); @@ -1511,8 +1528,8 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { bucket_cache_tile = -1; bucket_cache_visited = 0; - ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase selection"), KEY_DELETE); - ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find tile"), KEY_MASK_CMD + KEY_F); + ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase Selection"), KEY_DELETE); + ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find Tile"), KEY_MASK_CMD + KEY_F); ED_SHORTCUT("tile_map_editor/transpose", TTR("Transpose"), KEY_T); ED_SHORTCUT("tile_map_editor/mirror_x", TTR("Mirror X"), KEY_A); ED_SHORTCUT("tile_map_editor/mirror_y", TTR("Mirror Y"), KEY_S); @@ -1575,6 +1592,8 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { p->add_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_MASK_CMD + KEY_B), OPTION_SELECT); p->add_shortcut(ED_SHORTCUT("tile_map_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_CMD + KEY_D), OPTION_DUPLICATE); p->add_shortcut(ED_GET_SHORTCUT("tile_map_editor/erase_selection"), OPTION_ERASE_SELECTION); + p->add_separator(); + p->add_item(TTR("Fix Invalid Tiles"), OPTION_FIX_INVALID); p->connect("id_pressed", this, "_menu_option"); diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index 0a937e200e..2d582d030b 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -71,6 +71,7 @@ class TileMapEditor : public VBoxContainer { OPTION_DUPLICATE, OPTION_ERASE_SELECTION, OPTION_PAINTING, + OPTION_FIX_INVALID, }; TileMap *node; diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 2ff8536b4c..2311439728 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -37,6 +37,9 @@ void TileSetEditor::edit(const Ref<TileSet> &p_tileset) { tileset = p_tileset; + tileset->add_change_receptor(this); + + update_tile_list(); } void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) { @@ -188,6 +191,7 @@ void TileSetEditor::_name_dialog_confirm(const String &name) { if (tileset->has_tile(id)) { tileset->remove_tile(id); + update_tile_list(); } else { err_dialog->set_text(TTR("Could not find tile:") + " " + name); err_dialog->popup_centered(Size2(300, 60)); @@ -202,8 +206,9 @@ void TileSetEditor::_menu_cbk(int p_option) { switch (p_option) { case MENU_OPTION_ADD_ITEM: { - tileset->create_tile(tileset->get_last_unused_tile_id()); + tileset->tile_set_name(tileset->get_last_unused_tile_id() - 1, itos(tileset->get_last_unused_tile_id() - 1)); + update_tile_list(); } break; case MENU_OPTION_REMOVE_ITEM: { @@ -235,106 +240,76 @@ void TileSetEditor::_bind_methods() { ClassDB::bind_method("_menu_cbk", &TileSetEditor::_menu_cbk); ClassDB::bind_method("_menu_confirm", &TileSetEditor::_menu_confirm); ClassDB::bind_method("_name_dialog_confirm", &TileSetEditor::_name_dialog_confirm); + ClassDB::bind_method("_on_tile_list_selected", &TileSetEditor::_on_tile_list_selected); + ClassDB::bind_method("_on_edit_mode_changed", &TileSetEditor::_on_edit_mode_changed); + ClassDB::bind_method("_on_workspace_overlay_draw", &TileSetEditor::_on_workspace_overlay_draw); + ClassDB::bind_method("_on_workspace_draw", &TileSetEditor::_on_workspace_draw); + ClassDB::bind_method("_on_workspace_input", &TileSetEditor::_on_workspace_input); + ClassDB::bind_method("_on_tool_clicked", &TileSetEditor::_on_tool_clicked); + ClassDB::bind_method("_on_priority_changed", &TileSetEditor::_on_priority_changed); + ClassDB::bind_method("_on_grid_snap_toggled", &TileSetEditor::_on_grid_snap_toggled); + ClassDB::bind_method("_set_snap_step_x", &TileSetEditor::_set_snap_step_x); + ClassDB::bind_method("_set_snap_step_y", &TileSetEditor::_set_snap_step_y); + ClassDB::bind_method("_set_snap_off_x", &TileSetEditor::_set_snap_off_x); + ClassDB::bind_method("_set_snap_off_y", &TileSetEditor::_set_snap_off_y); + ClassDB::bind_method("_set_snap_sep_x", &TileSetEditor::_set_snap_sep_x); + ClassDB::bind_method("_set_snap_sep_y", &TileSetEditor::_set_snap_sep_y); } -TileSetEditor::TileSetEditor(EditorNode *p_editor) { - - menu = memnew(MenuButton); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(menu); - menu->hide(); - menu->set_text(TTR("Tile Set")); - menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); - menu->get_popup()->add_item(TTR("Remove Item"), MENU_OPTION_REMOVE_ITEM); - menu->get_popup()->add_separator(); - menu->get_popup()->add_item(TTR("Create from Scene"), MENU_OPTION_CREATE_FROM_SCENE); - menu->get_popup()->add_item(TTR("Merge from Scene"), MENU_OPTION_MERGE_FROM_SCENE); - menu->get_popup()->connect("id_pressed", this, "_menu_cbk"); - editor = p_editor; - cd = memnew(ConfirmationDialog); - add_child(cd); - cd->get_ok()->connect("pressed", this, "_menu_confirm"); - - nd = memnew(EditorNameDialog); - add_child(nd); - nd->set_hide_on_ok(true); - nd->get_line_edit()->set_margin(MARGIN_TOP, 28); - nd->connect("name_confirmed", this, "_name_dialog_confirm"); - - err_dialog = memnew(AcceptDialog); - add_child(err_dialog); - err_dialog->set_title(TTR("Error")); -} - -void TileSetEditorPlugin::edit(Object *p_node) { - - if (Object::cast_to<TileSet>(p_node)) { - tileset_editor->edit(Object::cast_to<TileSet>(p_node)); - tileset_editor->show(); - autotile_editor->edit(p_node); - } else - tileset_editor->hide(); -} - -bool TileSetEditorPlugin::handles(Object *p_node) const { - - return p_node->is_class("TileSet"); -} - -void TileSetEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - tileset_editor->show(); - tileset_editor->menu->show(); - autotile_button->show(); - autotile_editor->side_panel->show(); - if (autotile_button->is_pressed()) { - autotile_editor->show(); - } - } else { - tileset_editor->hide(); - tileset_editor->menu->hide(); - autotile_editor->side_panel->hide(); - autotile_editor->hide(); - autotile_button->hide(); +void TileSetEditor::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + tools[TOOL_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); + tools[BITMASK_COPY]->set_icon(get_icon("Duplicate", "EditorIcons")); + 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_DELETE]->set_icon(get_icon("Remove", "EditorIcons")); + tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_icon("Snap", "EditorIcons")); + tools[SHAPE_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons")); + tools[ZOOM_OUT]->set_icon(get_icon("ZoomLess", "EditorIcons")); + tools[ZOOM_1]->set_icon(get_icon("ZoomReset", "EditorIcons")); + tools[ZOOM_IN]->set_icon(get_icon("ZoomMore", "EditorIcons")); } } -TileSetEditorPlugin::TileSetEditorPlugin(EditorNode *p_node) { - - tileset_editor = memnew(TileSetEditor(p_node)); - - add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, tileset_editor); - tileset_editor->set_anchors_and_margins_preset(Control::PRESET_TOP_WIDE); - tileset_editor->set_end(Point2(0, 22)); - tileset_editor->hide(); - - autotile_editor = memnew(AutotileEditor(p_node)); - add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE, autotile_editor->side_panel); - autotile_editor->side_panel->set_anchors_and_margins_preset(Control::PRESET_WIDE); - autotile_editor->side_panel->set_custom_minimum_size(Size2(200, 0)); - autotile_editor->side_panel->hide(); - autotile_button = p_node->add_bottom_panel_item(TTR("Autotiles"), autotile_editor); - autotile_button->hide(); +void TileSetEditor::_changed_callback(Object *p_changed, const char *p_prop) { + if (p_prop == StringName("region")) { + update_tile_list_icon(); + preview->set_region_rect(tileset->tile_get_region(get_current_tile())); + } else if (p_prop == StringName("name")) { + update_tile_list_icon(); + } else if (p_prop == StringName("texture") || p_prop == StringName("tile_mode")) { + _on_tile_list_selected(get_current_tile()); + workspace->update(); + preview->set_texture(tileset->tile_get_texture(get_current_tile())); + preview->set_region_rect(tileset->tile_get_region(get_current_tile())); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) + property_editor->show(); + else + property_editor->hide(); + texture_region_editor->_edit_region(); + update_tile_list_icon(); + } else if (p_prop == StringName("autotile")) { + workspace->update(); + } } -AutotileEditor::AutotileEditor(EditorNode *p_editor) { - - editor = p_editor; +void TileSetEditor::initialize_bottom_editor() { //Side Panel side_panel = memnew(Control); - side_panel->set_name("Autotiles"); + side_panel->set_name("Tile Set"); VSplitContainer *split = memnew(VSplitContainer); side_panel->add_child(split); split->set_anchors_and_margins_preset(Control::PRESET_WIDE); - autotile_list = memnew(ItemList); - autotile_list->set_v_size_flags(SIZE_EXPAND_FILL); - autotile_list->set_h_size_flags(SIZE_EXPAND_FILL); - autotile_list->set_custom_minimum_size(Size2(10, 200)); - autotile_list->connect("item_selected", this, "_on_autotile_selected"); - split->add_child(autotile_list); + tile_list = memnew(ItemList); + tile_list->set_v_size_flags(SIZE_EXPAND_FILL); + tile_list->set_h_size_flags(SIZE_EXPAND_FILL); + tile_list->set_custom_minimum_size(Size2(10, 200)); + tile_list->connect("item_selected", this, "_on_tile_list_selected"); + split->add_child(tile_list); property_editor = memnew(PropertyEditor); property_editor->set_v_size_flags(SIZE_EXPAND_FILL); @@ -342,25 +317,29 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { property_editor->set_custom_minimum_size(Size2(10, 70)); split->add_child(property_editor); - helper = memnew(AutotileEditorHelper(this)); + helper = memnew(TileSetEditorHelper(this)); property_editor->call_deferred("edit", helper); + helper->add_change_receptor(this); //Editor + //Bottom Panel + bottom_panel = memnew(Control); + bottom_panel->set_name("Tile Set Bottom Editor"); dragging_point = -1; creating_shape = false; snap_step = Vector2(32, 32); - set_custom_minimum_size(Size2(0, 150)); + bottom_panel->set_custom_minimum_size(Size2(0, 150)); VBoxContainer *main_vb = memnew(VBoxContainer); - add_child(main_vb); + bottom_panel->add_child(main_vb); main_vb->set_anchors_and_margins_preset(Control::PRESET_WIDE); HBoxContainer *tool_hb = memnew(HBoxContainer); Ref<ButtonGroup> g(memnew(ButtonGroup)); - String label[EDITMODE_MAX] = { "Icon", "Bitmask", "Collision", "Occlusion", "Navigation", "Priority" }; + String label[EDITMODE_MAX] = { "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon" }; for (int i = 0; i < (int)EDITMODE_MAX; i++) { tool_editmode[i] = memnew(Button); @@ -372,7 +351,8 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { tool_editmode[i]->connect("pressed", this, "_on_edit_mode_changed", args); tool_hb->add_child(tool_editmode[i]); } - tool_editmode[EDITMODE_ICON]->set_pressed(true); + tool_editmode[EDITMODE_COLLISION]->set_pressed(true); + edit_mode = EDITMODE_COLLISION; main_vb->add_child(tool_hb); main_vb->add_child(memnew(HSeparator)); @@ -386,15 +366,17 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { Ref<ButtonGroup> tg(memnew(ButtonGroup)); + Vector<Variant> p; tools[TOOL_SELECT] = memnew(ToolButton); tool_containers[TOOLBAR_DUMMY]->add_child(tools[TOOL_SELECT]); tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.")); tools[TOOL_SELECT]->set_toggle_mode(true); tools[TOOL_SELECT]->set_button_group(tg); tools[TOOL_SELECT]->set_pressed(true); + p.push_back((int)TOOL_SELECT); + tools[TOOL_SELECT]->connect("pressed", this, "_on_tool_clicked", p); tool_containers[TOOLBAR_DUMMY]->show(); - Vector<Variant> p; tools[BITMASK_COPY] = memnew(ToolButton); p.push_back((int)BITMASK_COPY); tools[BITMASK_COPY]->connect("pressed", this, "_on_tool_clicked", p); @@ -507,6 +489,8 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { spin_priority->hide(); toolbar->add_child(spin_priority); + tool_containers[TOOLBAR_SHAPE]->show(); + Control *separator = memnew(Control); separator->set_h_size_flags(SIZE_EXPAND_FILL); toolbar->add_child(separator); @@ -536,10 +520,15 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { workspace_container = memnew(Control); scroll->add_child(workspace_container); + workspace_overlay = memnew(Control); + workspace_overlay->connect("draw", this, "_on_workspace_overlay_draw"); + workspace_container->add_child(workspace_overlay); + workspace = memnew(Control); workspace->connect("draw", this, "_on_workspace_draw"); workspace->connect("gui_input", this, "_on_workspace_input"); - workspace_container->add_child(workspace); + workspace->set_draw_behind_parent(true); + workspace_overlay->add_child(workspace); preview = memnew(Sprite); workspace->add_child(preview); @@ -548,70 +537,63 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { preview->set_region(true); } -AutotileEditor::~AutotileEditor() { - memdelete(helper); -} +TileSetEditor::TileSetEditor(EditorNode *p_editor) { -void AutotileEditor::_bind_methods() { - - ClassDB::bind_method("_on_autotile_selected", &AutotileEditor::_on_autotile_selected); - ClassDB::bind_method("_on_edit_mode_changed", &AutotileEditor::_on_edit_mode_changed); - ClassDB::bind_method("_on_workspace_draw", &AutotileEditor::_on_workspace_draw); - ClassDB::bind_method("_on_workspace_input", &AutotileEditor::_on_workspace_input); - ClassDB::bind_method("_on_tool_clicked", &AutotileEditor::_on_tool_clicked); - ClassDB::bind_method("_on_priority_changed", &AutotileEditor::_on_priority_changed); - ClassDB::bind_method("_on_grid_snap_toggled", &AutotileEditor::_on_grid_snap_toggled); - ClassDB::bind_method("_set_snap_step_x", &AutotileEditor::_set_snap_step_x); - ClassDB::bind_method("_set_snap_step_y", &AutotileEditor::_set_snap_step_y); - ClassDB::bind_method("_set_snap_off_x", &AutotileEditor::_set_snap_off_x); - ClassDB::bind_method("_set_snap_off_y", &AutotileEditor::_set_snap_off_y); - ClassDB::bind_method("_set_snap_sep_x", &AutotileEditor::_set_snap_sep_x); - ClassDB::bind_method("_set_snap_sep_y", &AutotileEditor::_set_snap_sep_y); -} + menu = memnew(MenuButton); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(menu); + menu->hide(); + menu->set_text(TTR("Tile Set")); + menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); + menu->get_popup()->add_item(TTR("Remove Item"), MENU_OPTION_REMOVE_ITEM); + menu->get_popup()->add_separator(); + menu->get_popup()->add_item(TTR("Create from Scene"), MENU_OPTION_CREATE_FROM_SCENE); + menu->get_popup()->add_item(TTR("Merge from Scene"), MENU_OPTION_MERGE_FROM_SCENE); + menu->get_popup()->connect("id_pressed", this, "_menu_cbk"); + editor = p_editor; + cd = memnew(ConfirmationDialog); + add_child(cd); + cd->get_ok()->connect("pressed", this, "_menu_confirm"); -void AutotileEditor::_notification(int p_what) { + nd = memnew(EditorNameDialog); + add_child(nd); + nd->set_hide_on_ok(true); + nd->get_line_edit()->set_margin(MARGIN_TOP, 28); + nd->connect("name_confirmed", this, "_name_dialog_confirm"); - if (p_what == NOTIFICATION_ENTER_TREE) { - tools[TOOL_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); - tools[BITMASK_COPY]->set_icon(get_icon("Duplicate", "EditorIcons")); - 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_DELETE]->set_icon(get_icon("Remove", "EditorIcons")); - tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_icon("Snap", "EditorIcons")); - tools[SHAPE_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons")); - tools[ZOOM_OUT]->set_icon(get_icon("ZoomLess", "EditorIcons")); - tools[ZOOM_1]->set_icon(get_icon("ZoomReset", "EditorIcons")); - tools[ZOOM_IN]->set_icon(get_icon("ZoomMore", "EditorIcons")); - } -} + err_dialog = memnew(AcceptDialog); + add_child(err_dialog); + err_dialog->set_title(TTR("Error")); -void AutotileEditor::_changed_callback(Object *p_changed, const char *p_prop) { - if (p_prop == StringName("texture") || p_prop == StringName("is_autotile")) { - edit(tile_set.ptr()); - autotile_list->update(); - workspace->update(); - } + draw_handles = false; + + initialize_bottom_editor(); } -void AutotileEditor::_on_autotile_selected(int p_index) { +TileSetEditor::~TileSetEditor() { + if (helper) + memdelete(helper); +} +void TileSetEditor::_on_tile_list_selected(int p_index) { if (get_current_tile() >= 0) { current_item_index = p_index; - preview->set_texture(tile_set->tile_get_texture(get_current_tile())); - preview->set_region_rect(tile_set->tile_get_region(get_current_tile())); - workspace->set_custom_minimum_size(tile_set->tile_get_region(get_current_tile()).size); + preview->set_texture(tileset->tile_get_texture(get_current_tile())); + preview->set_region_rect(tileset->tile_get_region(get_current_tile())); + workspace->set_custom_minimum_size(tileset->tile_get_region(get_current_tile()).size); + update_workspace_tile_mode(); } else { current_item_index = -1; preview->set_texture(NULL); workspace->set_custom_minimum_size(Size2i()); } + texture_region_editor->selected_tile = get_current_tile(); + texture_region_editor->_edit_region(); + helper->selected_tile = get_current_tile(); helper->_change_notify(""); workspace->update(); } -void AutotileEditor::_on_edit_mode_changed(int p_edit_mode) { - +void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { edit_mode = (EditMode)p_edit_mode; switch (edit_mode) { case EDITMODE_BITMASK: { @@ -631,7 +613,6 @@ void AutotileEditor::_on_edit_mode_changed(int p_edit_mode) { tools[TOOL_SELECT]->set_tooltip(TTR("Select current edited sub-tile.")); spin_priority->hide(); - current_shape = PoolVector2Array(); select_coord(edited_shape_coord); } break; default: { @@ -650,17 +631,17 @@ void AutotileEditor::_on_edit_mode_changed(int p_edit_mode) { workspace->update(); } -void AutotileEditor::_on_workspace_draw() { +void TileSetEditor::_on_workspace_draw() { - if (get_current_tile() >= 0 && !tile_set.is_null()) { - int spacing = tile_set->autotile_get_spacing(get_current_tile()); - Vector2 size = tile_set->autotile_get_size(get_current_tile()); - Rect2i region = tile_set->tile_get_region(get_current_tile()); + if (get_current_tile() >= 0 && !tileset.is_null()) { + int spacing = tileset->autotile_get_spacing(get_current_tile()); + Vector2 size = tileset->autotile_get_size(get_current_tile()); + Rect2i region = tileset->tile_get_region(get_current_tile()); Color c(0.347214, 0.722656, 0.617063); switch (edit_mode) { case EDITMODE_ICON: { - Vector2 coord = tile_set->autotile_get_icon_coordinate(get_current_tile()); + Vector2 coord = tileset->autotile_get_icon_coordinate(get_current_tile()); draw_highlight_tile(coord); } break; case EDITMODE_BITMASK: { @@ -669,8 +650,8 @@ void AutotileEditor::_on_workspace_draw() { for (float y = 0; y < region.size.y / (spacing + size.y); y++) { Vector2 coord(x, y); Point2 anchor(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); - uint16_t mask = tile_set->autotile_get_bitmask(get_current_tile(), coord); - if (tile_set->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { + uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), coord); + if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { if (mask & TileSet::BIND_TOPLEFT) { workspace->draw_rect(Rect2(anchor, size / 2), c); } @@ -683,7 +664,7 @@ void AutotileEditor::_on_workspace_draw() { if (mask & TileSet::BIND_BOTTOMRIGHT) { workspace->draw_rect(Rect2(anchor + size / 2, size / 2), c); } - } else if (tile_set->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { + } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { if (mask & TileSet::BIND_TOPLEFT) { workspace->draw_rect(Rect2(anchor, size / 3), c); } @@ -718,19 +699,21 @@ void AutotileEditor::_on_workspace_draw() { case EDITMODE_COLLISION: case EDITMODE_OCCLUSION: case EDITMODE_NAVIGATION: { - Vector2 coord = edited_shape_coord; - draw_highlight_tile(coord); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + Vector2 coord = edited_shape_coord; + draw_highlight_tile(coord); + } draw_polygon_shapes(); draw_grid_snap(); } break; case EDITMODE_PRIORITY: { - spin_priority->set_value(tile_set->autotile_get_subtile_priority(get_current_tile(), edited_shape_coord)); - uint16_t mask = tile_set->autotile_get_bitmask(get_current_tile(), edited_shape_coord); + spin_priority->set_value(tileset->autotile_get_subtile_priority(get_current_tile(), edited_shape_coord)); + uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), edited_shape_coord); Vector<Vector2> queue_others; int total = 0; - for (Map<Vector2, uint16_t>::Element *E = tile_set->autotile_get_bitmask_map(get_current_tile()).front(); E; E = E->next()) { + for (Map<Vector2, uint16_t>::Element *E = tileset->autotile_get_bitmask_map(get_current_tile()).front(); E; E = E->next()) { if (E->value() == mask) { - total += tile_set->autotile_get_subtile_priority(get_current_tile(), E->key()); + total += tileset->autotile_get_subtile_priority(get_current_tile(), E->key()); if (E->key() != edited_shape_coord) { queue_others.push_back(E->key()); } @@ -741,53 +724,69 @@ void AutotileEditor::_on_workspace_draw() { } break; } - float j = -size.x; //make sure to draw at 0 - while (j < region.size.x) { - j += size.x; - if (spacing <= 0) { - workspace->draw_line(Point2(j, 0), Point2(j, region.size.y), c); - } else { - workspace->draw_rect(Rect2(Point2(j, 0), Size2(spacing, region.size.y)), c); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + float j = -size.x; //make sure to draw at 0 + while (j < region.size.x) { + j += size.x; + if (spacing <= 0) { + workspace->draw_line(Point2(j, 0), Point2(j, region.size.y), c); + } else { + workspace->draw_rect(Rect2(Point2(j, 0), Size2(spacing, region.size.y)), c); + } + j += spacing; } - j += spacing; - } - j = -size.y; //make sure to draw at 0 - while (j < region.size.y) { - j += size.y; - if (spacing <= 0) { - workspace->draw_line(Point2(0, j), Point2(region.size.x, j), c); - } else { - workspace->draw_rect(Rect2(Point2(0, j), Size2(region.size.x, spacing)), c); + j = -size.y; //make sure to draw at 0 + while (j < region.size.y) { + j += size.y; + if (spacing <= 0) { + workspace->draw_line(Point2(0, j), Point2(region.size.x, j), c); + } else { + workspace->draw_rect(Rect2(Point2(0, j), Size2(region.size.x, spacing)), c); + } + j += spacing; } - j += spacing; } } + workspace_overlay->update(); +} + +void TileSetEditor::_on_workspace_overlay_draw() { + + int t_id = get_current_tile(); + if (t_id < 0 || !draw_handles) + return; + + Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); + + for (int i = 0; i < current_shape.size(); i++) { + workspace_overlay->draw_texture(handle, current_shape[i] * workspace->get_scale().x - handle->get_size() * 0.5); + } } -#define MIN_DISTANCE_SQUARED 10 -void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { +#define MIN_DISTANCE_SQUARED 6 +void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { - if (get_current_tile() >= 0 && !tile_set.is_null()) { + if (get_current_tile() >= 0 && !tileset.is_null()) { Ref<InputEventMouseButton> mb = p_ie; Ref<InputEventMouseMotion> mm = p_ie; static bool dragging; static bool erasing; - int spacing = tile_set->autotile_get_spacing(get_current_tile()); - Vector2 size = tile_set->autotile_get_size(get_current_tile()); + int spacing = tileset->autotile_get_spacing(get_current_tile()); + Vector2 size = tileset->autotile_get_size(get_current_tile()); switch (edit_mode) { case EDITMODE_ICON: { if (mb.is_valid()) { if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { Vector2 coord((int)(mb->get_position().x / (spacing + size.x)), (int)(mb->get_position().y / (spacing + size.y))); - tile_set->autotile_set_icon_coordinate(get_current_tile(), coord); - Rect2 region = tile_set->tile_get_region(get_current_tile()); + tileset->autotile_set_icon_coordinate(get_current_tile(), coord); + Rect2 region = tileset->tile_get_region(get_current_tile()); region.size = size; coord.x *= (spacing + size.x); coord.y *= (spacing + size.y); region.position += coord; - autotile_list->set_item_icon_region(current_item_index, region); + tile_list->set_item_icon_region(current_item_index, region); workspace->update(); } } @@ -805,7 +804,7 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); pos = mb->get_position() - pos; uint16_t bit; - if (tile_set->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { + if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { if (pos.x < size.x / 2) { if (pos.y < size.y / 2) { bit = TileSet::BIND_TOPLEFT; @@ -819,7 +818,7 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { bit = TileSet::BIND_BOTTOMRIGHT; } } - } else if (tile_set->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { + } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { if (pos.x < size.x / 3) { if (pos.y < size.y / 3) { bit = TileSet::BIND_TOPLEFT; @@ -846,13 +845,13 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } - uint16_t mask = tile_set->autotile_get_bitmask(get_current_tile(), coord); + uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), coord); if (erasing) { mask &= ~bit; } else { mask |= bit; } - tile_set->autotile_set_bitmask(get_current_tile(), coord, mask); + tileset->autotile_set_bitmask(get_current_tile(), coord, mask); workspace->update(); } } else { @@ -868,7 +867,7 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); pos = mm->get_position() - pos; uint16_t bit; - if (tile_set->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { + if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { if (pos.x < size.x / 2) { if (pos.y < size.y / 2) { bit = TileSet::BIND_TOPLEFT; @@ -882,7 +881,7 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { bit = TileSet::BIND_BOTTOMRIGHT; } } - } else if (tile_set->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { + } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { if (pos.x < size.x / 3) { if (pos.y < size.y / 3) { bit = TileSet::BIND_TOPLEFT; @@ -909,13 +908,13 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } - uint16_t mask = tile_set->autotile_get_bitmask(get_current_tile(), coord); + uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), coord); if (erasing) { mask &= ~bit; } else { mask |= bit; } - tile_set->autotile_set_bitmask(get_current_tile(), coord, mask); + tileset->autotile_set_bitmask(get_current_tile(), coord, mask); workspace->update(); } } @@ -924,9 +923,12 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { case EDITMODE_OCCLUSION: case EDITMODE_NAVIGATION: case EDITMODE_PRIORITY: { - Vector2 shape_anchor = edited_shape_coord; - shape_anchor.x *= (size.x + spacing); - shape_anchor.y *= (size.y + spacing); + Vector2 shape_anchor = Vector2(0, 0); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + shape_anchor = edited_shape_coord; + shape_anchor.x *= (size.x + spacing); + shape_anchor.y *= (size.y + spacing); + } if (tools[TOOL_SELECT]->is_pressed()) { if (mb.is_valid()) { if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { @@ -939,23 +941,25 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } - Vector2 coord((int)(mb->get_position().x / (spacing + size.x)), (int)(mb->get_position().y / (spacing + size.y))); - if (edited_shape_coord != coord) { - edited_shape_coord = coord; - edited_occlusion_shape = tile_set->autotile_get_light_occluder(get_current_tile(), edited_shape_coord); - edited_navigation_shape = tile_set->autotile_get_navigation_polygon(get_current_tile(), edited_shape_coord); - Vector<TileSet::ShapeData> sd = tile_set->tile_get_shapes(get_current_tile()); - bool found_collision_shape = false; - for (int i = 0; i < sd.size(); i++) { - if (sd[i].autotile_coord == coord) { - edited_collision_shape = sd[i].shape; - found_collision_shape = true; - break; + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + Vector2 coord((int)(mb->get_position().x / (spacing + size.x)), (int)(mb->get_position().y / (spacing + size.y))); + if (edited_shape_coord != coord) { + edited_shape_coord = coord; + edited_occlusion_shape = tileset->autotile_get_light_occluder(get_current_tile(), edited_shape_coord); + edited_navigation_shape = tileset->autotile_get_navigation_polygon(get_current_tile(), edited_shape_coord); + Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(get_current_tile()); + bool found_collision_shape = false; + for (int i = 0; i < sd.size(); i++) { + if (sd[i].autotile_coord == coord) { + edited_collision_shape = sd[i].shape; + found_collision_shape = true; + break; + } } + if (!found_collision_shape) + edited_collision_shape = Ref<ConvexPolygonShape2D>(NULL); + select_coord(edited_shape_coord); } - if (!found_collision_shape) - edited_collision_shape = Ref<ConvexPolygonShape2D>(NULL); - select_coord(edited_shape_coord); } workspace->update(); } else if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { @@ -1023,8 +1027,6 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } else if (tools[SHAPE_NEW_POLYGON]->is_pressed()) { - if (!tools[TOOL_SELECT]->is_disabled()) - tools[TOOL_SELECT]->set_disabled(true); if (mb.is_valid()) { if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { @@ -1046,14 +1048,14 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { int t_id = get_current_tile(); if (t_id >= 0) { if (edit_mode == EDITMODE_COLLISION) { - Vector<TileSet::ShapeData> sd = tile_set->tile_get_shapes(t_id); + Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(t_id); for (int i = 0; i < sd.size(); i++) { - if (sd[i].autotile_coord == edited_shape_coord) { + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE || sd[i].autotile_coord == edited_shape_coord) { Ref<ConvexPolygonShape2D> shape = sd[i].shape; if (!shape.is_null()) { sd.remove(i); - tile_set->tile_set_shapes(get_current_tile(), sd); + tileset->tile_set_shapes(get_current_tile(), sd); edited_collision_shape = Ref<Shape2D>(); workspace->update(); } @@ -1061,25 +1063,30 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } else if (edit_mode == EDITMODE_OCCLUSION) { - Map<Vector2, Ref<OccluderPolygon2D> > map = tile_set->autotile_get_light_oclusion_map(t_id); - for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = map.front(); E; E = E->next()) { - if (E->key() == edited_shape_coord) { - tile_set->autotile_set_light_occluder(get_current_tile(), Ref<OccluderPolygon2D>(), edited_shape_coord); - break; + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + Map<Vector2, Ref<OccluderPolygon2D> > map = tileset->autotile_get_light_oclusion_map(t_id); + for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = map.front(); E; E = E->next()) { + if (E->key() == edited_shape_coord) { + tileset->autotile_set_light_occluder(get_current_tile(), Ref<OccluderPolygon2D>(), edited_shape_coord); + break; + } } - } + } else + tileset->tile_set_light_occluder(t_id, Ref<OccluderPolygon2D>()); edited_occlusion_shape = Ref<OccluderPolygon2D>(); workspace->update(); } else if (edit_mode == EDITMODE_NAVIGATION) { - Map<Vector2, Ref<NavigationPolygon> > map = tile_set->autotile_get_navigation_map(t_id); - for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = map.front(); E; E = E->next()) { - if (E->key() == edited_shape_coord) { - tile_set->autotile_set_navigation_polygon(t_id, Ref<NavigationPolygon>(), edited_shape_coord); - break; + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + Map<Vector2, Ref<NavigationPolygon> > map = tileset->autotile_get_navigation_map(t_id); + for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = map.front(); E; E = E->next()) { + if (E->key() == edited_shape_coord) { + tileset->autotile_set_navigation_polygon(t_id, Ref<NavigationPolygon>(), edited_shape_coord); + break; + } } - } - + } else + tileset->tile_set_navigation_polygon(t_id, Ref<NavigationPolygon>()); edited_navigation_shape = Ref<NavigationPolygon>(); workspace->update(); } @@ -1092,8 +1099,6 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT && current_shape.size() > 2) { if (creating_shape) { close_shape(shape_anchor); - if (tools[TOOL_SELECT]->is_disabled()) - tools[TOOL_SELECT]->set_disabled(false); } } } else if (mm.is_valid()) { @@ -1117,17 +1122,17 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } -void AutotileEditor::_on_tool_clicked(int p_tool) { +void TileSetEditor::_on_tool_clicked(int p_tool) { if (p_tool == BITMASK_COPY) { - bitmask_map_copy = tile_set->autotile_get_bitmask_map(get_current_tile()); + bitmask_map_copy = tileset->autotile_get_bitmask_map(get_current_tile()); } else if (p_tool == BITMASK_PASTE) { - tile_set->autotile_clear_bitmask_map(get_current_tile()); + tileset->autotile_clear_bitmask_map(get_current_tile()); for (Map<Vector2, uint16_t>::Element *E = bitmask_map_copy.front(); E; E = E->next()) { - tile_set->autotile_set_bitmask(get_current_tile(), E->key(), E->value()); + tileset->autotile_set_bitmask(get_current_tile(), E->key(), E->value()); } workspace->update(); } else if (p_tool == BITMASK_CLEAR) { - tile_set->autotile_clear_bitmask_map(get_current_tile()); + tileset->autotile_clear_bitmask_map(get_current_tile()); workspace->update(); } else if (p_tool == SHAPE_DELETE) { if (creating_shape) { @@ -1138,7 +1143,7 @@ void AutotileEditor::_on_tool_clicked(int p_tool) { switch (edit_mode) { case EDITMODE_COLLISION: { if (!edited_collision_shape.is_null()) { - Vector<TileSet::ShapeData> sd = tile_set->tile_get_shapes(get_current_tile()); + Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(get_current_tile()); int index; for (int i = 0; i < sd.size(); i++) { if (sd[i].shape == edited_collision_shape) { @@ -1148,7 +1153,7 @@ void AutotileEditor::_on_tool_clicked(int p_tool) { } if (index >= 0) { sd.remove(index); - tile_set->tile_set_shapes(get_current_tile(), sd); + tileset->tile_set_shapes(get_current_tile(), sd); edited_collision_shape = Ref<Shape2D>(); current_shape.resize(0); workspace->update(); @@ -1157,7 +1162,7 @@ void AutotileEditor::_on_tool_clicked(int p_tool) { } break; case EDITMODE_NAVIGATION: { if (!edited_navigation_shape.is_null()) { - tile_set->autotile_set_navigation_polygon(get_current_tile(), Ref<NavigationPolygon>(), edited_shape_coord); + tileset->autotile_set_navigation_polygon(get_current_tile(), Ref<NavigationPolygon>(), edited_shape_coord); edited_navigation_shape = Ref<NavigationPolygon>(); current_shape.resize(0); workspace->update(); @@ -1165,7 +1170,7 @@ void AutotileEditor::_on_tool_clicked(int p_tool) { } break; case EDITMODE_OCCLUSION: { if (!edited_occlusion_shape.is_null()) { - tile_set->autotile_set_light_occluder(get_current_tile(), Ref<OccluderPolygon2D>(), edited_shape_coord); + tileset->autotile_set_light_occluder(get_current_tile(), Ref<OccluderPolygon2D>(), edited_shape_coord); edited_occlusion_shape = Ref<OccluderPolygon2D>(); current_shape.resize(0); workspace->update(); @@ -1179,24 +1184,34 @@ void AutotileEditor::_on_tool_clicked(int p_tool) { scale /= 2; workspace->set_scale(Vector2(scale, scale)); workspace_container->set_custom_minimum_size(preview->get_region_rect().size * scale); + workspace_overlay->set_custom_minimum_size(preview->get_region_rect().size * scale); } } else if (p_tool == ZOOM_1) { workspace->set_scale(Vector2(1, 1)); workspace_container->set_custom_minimum_size(preview->get_region_rect().size); + workspace_overlay->set_custom_minimum_size(preview->get_region_rect().size); } else if (p_tool == ZOOM_IN) { float scale = workspace->get_scale().x; scale *= 2; workspace->set_scale(Vector2(scale, scale)); workspace_container->set_custom_minimum_size(preview->get_region_rect().size * scale); + workspace_overlay->set_custom_minimum_size(preview->get_region_rect().size * scale); + } else if (p_tool == TOOL_SELECT) { + if (creating_shape) { + //Cancel Creation + creating_shape = false; + current_shape.resize(0); + workspace->update(); + } } } -void AutotileEditor::_on_priority_changed(float val) { - tile_set->autotile_set_subtile_priority(get_current_tile(), edited_shape_coord, (int)val); +void TileSetEditor::_on_priority_changed(float val) { + tileset->autotile_set_subtile_priority(get_current_tile(), edited_shape_coord, (int)val); workspace->update(); } -void AutotileEditor::_on_grid_snap_toggled(bool p_val) { +void TileSetEditor::_on_grid_snap_toggled(bool p_val) { if (p_val) hb_grid->show(); else @@ -1204,40 +1219,40 @@ void AutotileEditor::_on_grid_snap_toggled(bool p_val) { workspace->update(); } -void AutotileEditor::_set_snap_step_x(float p_val) { +void TileSetEditor::_set_snap_step_x(float p_val) { snap_step.x = p_val; workspace->update(); } -void AutotileEditor::_set_snap_step_y(float p_val) { +void TileSetEditor::_set_snap_step_y(float p_val) { snap_step.y = p_val; workspace->update(); } -void AutotileEditor::_set_snap_off_x(float p_val) { +void TileSetEditor::_set_snap_off_x(float p_val) { snap_offset.x = p_val; workspace->update(); } -void AutotileEditor::_set_snap_off_y(float p_val) { +void TileSetEditor::_set_snap_off_y(float p_val) { snap_offset.y = p_val; workspace->update(); } -void AutotileEditor::_set_snap_sep_x(float p_val) { +void TileSetEditor::_set_snap_sep_x(float p_val) { snap_separation.x = p_val; workspace->update(); } -void AutotileEditor::_set_snap_sep_y(float p_val) { +void TileSetEditor::_set_snap_sep_y(float p_val) { snap_separation.y = p_val; workspace->update(); } -void AutotileEditor::draw_highlight_tile(Vector2 coord, const Vector<Vector2> &other_highlighted) { +void TileSetEditor::draw_highlight_tile(Vector2 coord, const Vector<Vector2> &other_highlighted) { - Vector2 size = tile_set->autotile_get_size(get_current_tile()); - int spacing = tile_set->autotile_get_spacing(get_current_tile()); - Rect2 region = tile_set->tile_get_region(get_current_tile()); + Vector2 size = tileset->autotile_get_size(get_current_tile()); + int spacing = tileset->autotile_get_spacing(get_current_tile()); + Rect2 region = tileset->tile_get_region(get_current_tile()); coord.x *= (size.x + spacing); coord.y *= (size.y + spacing); workspace->draw_rect(Rect2(0, 0, region.size.x, coord.y), Color(0.5, 0.5, 0.5, 0.5)); @@ -1255,7 +1270,7 @@ void AutotileEditor::draw_highlight_tile(Vector2 coord, const Vector<Vector2> &o } } -void AutotileEditor::draw_grid_snap() { +void TileSetEditor::draw_grid_snap() { if (tools[SHAPE_GRID_SNAP]->is_pressed()) { Color grid_color = Color(0.39, 0, 1, 0.2f); Size2 s = workspace->get_size(); @@ -1296,27 +1311,33 @@ void AutotileEditor::draw_grid_snap() { } } -void AutotileEditor::draw_polygon_shapes() { +void TileSetEditor::draw_polygon_shapes() { int t_id = get_current_tile(); if (t_id < 0) return; + draw_handles = false; + switch (edit_mode) { case EDITMODE_COLLISION: { - Vector<TileSet::ShapeData> sd = tile_set->tile_get_shapes(t_id); + Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(t_id); for (int i = 0; i < sd.size(); i++) { - Vector2 coord = sd[i].autotile_coord; - Vector2 anchor = tile_set->autotile_get_size(t_id); - anchor.x += tile_set->autotile_get_spacing(t_id); - anchor.y += tile_set->autotile_get_spacing(t_id); - anchor.x *= coord.x; - anchor.y *= coord.y; + Vector2 coord = Vector2(0, 0); + Vector2 anchor = Vector2(0, 0); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) { + coord = sd[i].autotile_coord; + anchor = tileset->autotile_get_size(t_id); + anchor.x += tileset->autotile_get_spacing(t_id); + anchor.y += tileset->autotile_get_spacing(t_id); + anchor.x *= coord.x; + anchor.y *= coord.y; + } Ref<ConvexPolygonShape2D> shape = sd[i].shape; if (shape.is_valid()) { Color c_bg; Color c_border; - if (coord == edited_shape_coord && sd[i].shape == edited_collision_shape) { + if ((tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE || coord == edited_shape_coord) && sd[i].shape == edited_collision_shape) { c_bg = Color(0, 1, 1, 0.5); c_border = Color(0, 1, 1); } else { @@ -1339,62 +1360,82 @@ void AutotileEditor::draw_polygon_shapes() { if (polygon.size() > 2) { workspace->draw_polygon(polygon, colors); } - if (coord == edited_shape_coord) { + if (coord == edited_shape_coord || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { for (int j = 0; j < shape->get_points().size() - 1; j++) { workspace->draw_line(shape->get_points()[j] + anchor, shape->get_points()[j + 1] + anchor, c_border, 1, true); } if (shape == edited_collision_shape) { - for (int j = 0; j < current_shape.size(); j++) { - workspace->draw_circle(current_shape[j], 8 / workspace->get_scale().x, Color(1, 0, 0, 0.7f)); - } + draw_handles = true; } } } } } break; case EDITMODE_OCCLUSION: { - Map<Vector2, Ref<OccluderPolygon2D> > map = tile_set->autotile_get_light_oclusion_map(t_id); - for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = map.front(); E; E = E->next()) { - Vector2 coord = E->key(); - Vector2 anchor = tile_set->autotile_get_size(t_id); - anchor.x += tile_set->autotile_get_spacing(t_id); - anchor.y += tile_set->autotile_get_spacing(t_id); - anchor.x *= coord.x; - anchor.y *= coord.y; - Ref<OccluderPolygon2D> shape = E->value(); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { + Ref<OccluderPolygon2D> shape = edited_occlusion_shape; if (shape.is_valid()) { - Color c_bg; - Color c_border; - if (coord == edited_shape_coord && shape == edited_occlusion_shape) { - c_bg = Color(0, 1, 1, 0.5); - c_border = Color(0, 1, 1); - } else { - c_bg = Color(0.9, 0.7, 0.07, 0.5); - c_border = Color(0.9, 0.7, 0.07, 1); - } + Color c_bg = Color(0, 1, 1, 0.5); + Color c_border = Color(0, 1, 1); + Vector<Vector2> polygon; Vector<Color> colors; - if (shape == edited_occlusion_shape && current_shape.size() > 2) { - for (int j = 0; j < current_shape.size(); j++) { - polygon.push_back(current_shape[j]); - colors.push_back(c_bg); - } - } else { - for (int j = 0; j < shape->get_polygon().size(); j++) { - polygon.push_back(shape->get_polygon()[j] + anchor); - colors.push_back(c_bg); - } + for (int j = 0; j < shape->get_polygon().size(); j++) { + polygon.push_back(shape->get_polygon()[j]); + colors.push_back(c_bg); } workspace->draw_polygon(polygon, colors); - if (coord == edited_shape_coord) { - for (int j = 0; j < shape->get_polygon().size() - 1; j++) { - workspace->draw_line(shape->get_polygon()[j] + anchor, shape->get_polygon()[j + 1] + anchor, c_border, 1, true); + + for (int j = 0; j < shape->get_polygon().size() - 1; j++) { + workspace->draw_line(shape->get_polygon()[j], shape->get_polygon()[j + 1], c_border, 1, true); + } + workspace->draw_line(shape->get_polygon()[shape->get_polygon().size() - 1], shape->get_polygon()[0], c_border, 1, true); + if (shape == edited_occlusion_shape) { + draw_handles = true; + } + } + } else { + Map<Vector2, Ref<OccluderPolygon2D> > map = tileset->autotile_get_light_oclusion_map(t_id); + for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = map.front(); E; E = E->next()) { + Vector2 coord = E->key(); + Vector2 anchor = tileset->autotile_get_size(t_id); + anchor.x += tileset->autotile_get_spacing(t_id); + anchor.y += tileset->autotile_get_spacing(t_id); + anchor.x *= coord.x; + anchor.y *= coord.y; + Ref<OccluderPolygon2D> shape = E->value(); + if (shape.is_valid()) { + Color c_bg; + Color c_border; + if (coord == edited_shape_coord && shape == edited_occlusion_shape) { + c_bg = Color(0, 1, 1, 0.5); + c_border = Color(0, 1, 1); + } else { + c_bg = Color(0.9, 0.7, 0.07, 0.5); + c_border = Color(0.9, 0.7, 0.07, 1); } - workspace->draw_line(shape->get_polygon()[shape->get_polygon().size() - 1] + anchor, shape->get_polygon()[0] + anchor, c_border, 1, true); - if (shape == edited_occlusion_shape) { + Vector<Vector2> polygon; + Vector<Color> colors; + if (shape == edited_occlusion_shape && current_shape.size() > 2) { for (int j = 0; j < current_shape.size(); j++) { - workspace->draw_circle(current_shape[j], 8 / workspace->get_scale().x, Color(1, 0, 0)); + polygon.push_back(current_shape[j]); + colors.push_back(c_bg); + } + } else { + for (int j = 0; j < shape->get_polygon().size(); j++) { + polygon.push_back(shape->get_polygon()[j] + anchor); + colors.push_back(c_bg); + } + } + workspace->draw_polygon(polygon, colors); + if (coord == edited_shape_coord) { + for (int j = 0; j < shape->get_polygon().size() - 1; j++) { + workspace->draw_line(shape->get_polygon()[j] + anchor, shape->get_polygon()[j + 1] + anchor, c_border, 1, true); + } + workspace->draw_line(shape->get_polygon()[shape->get_polygon().size() - 1] + anchor, shape->get_polygon()[0] + anchor, c_border, 1, true); + if (shape == edited_occlusion_shape) { + draw_handles = true; } } } @@ -1402,49 +1443,77 @@ void AutotileEditor::draw_polygon_shapes() { } } break; case EDITMODE_NAVIGATION: { - Map<Vector2, Ref<NavigationPolygon> > map = tile_set->autotile_get_navigation_map(t_id); - for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = map.front(); E; E = E->next()) { - Vector2 coord = E->key(); - Vector2 anchor = tile_set->autotile_get_size(t_id); - anchor.x += tile_set->autotile_get_spacing(t_id); - anchor.y += tile_set->autotile_get_spacing(t_id); - anchor.x *= coord.x; - anchor.y *= coord.y; - Ref<NavigationPolygon> shape = E->value(); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { + Ref<NavigationPolygon> shape = edited_navigation_shape; + if (shape.is_valid()) { - Color c_bg; - Color c_border; - if (coord == edited_shape_coord && shape == edited_navigation_shape) { - c_bg = Color(0, 1, 1, 0.5); - c_border = Color(0, 1, 1); - } else { - c_bg = Color(0.9, 0.7, 0.07, 0.5); - c_border = Color(0.9, 0.7, 0.07, 1); - } + Color c_bg = Color(0, 1, 1, 0.5); + Color c_border = Color(0, 1, 1); + Vector<Vector2> polygon; Vector<Color> colors; - if (shape == edited_navigation_shape && current_shape.size() > 2) { - for (int j = 0; j < current_shape.size(); j++) { - polygon.push_back(current_shape[j]); - colors.push_back(c_bg); - } - } else if (shape->get_polygon_count() > 0) { + + PoolVector<Vector2> vertices = shape->get_vertices(); + for (int j = 0; j < shape->get_polygon(0).size(); j++) { + polygon.push_back(vertices[shape->get_polygon(0)[j]]); + colors.push_back(c_bg); + } + workspace->draw_polygon(polygon, colors); + + if (shape->get_polygon_count() > 0) { PoolVector<Vector2> vertices = shape->get_vertices(); - for (int j = 0; j < shape->get_polygon(0).size(); j++) { - polygon.push_back(vertices[shape->get_polygon(0)[j]] + anchor); - colors.push_back(c_bg); + for (int j = 0; j < shape->get_polygon(0).size() - 1; j++) { + workspace->draw_line(vertices[shape->get_polygon(0)[j]], vertices[shape->get_polygon(0)[j + 1]], c_border, 1, true); + } + if (shape == edited_navigation_shape) { + draw_handles = true; } } - workspace->draw_polygon(polygon, colors); - if (coord == edited_shape_coord) { - if (shape->get_polygon_count() > 0) { + } + + } else { + Map<Vector2, Ref<NavigationPolygon> > map = tileset->autotile_get_navigation_map(t_id); + for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = map.front(); E; E = E->next()) { + Vector2 coord = E->key(); + Vector2 anchor = tileset->autotile_get_size(t_id); + anchor.x += tileset->autotile_get_spacing(t_id); + anchor.y += tileset->autotile_get_spacing(t_id); + anchor.x *= coord.x; + anchor.y *= coord.y; + Ref<NavigationPolygon> shape = E->value(); + if (shape.is_valid()) { + Color c_bg; + Color c_border; + if (coord == edited_shape_coord && shape == edited_navigation_shape) { + c_bg = Color(0, 1, 1, 0.5); + c_border = Color(0, 1, 1); + } else { + c_bg = Color(0.9, 0.7, 0.07, 0.5); + c_border = Color(0.9, 0.7, 0.07, 1); + } + Vector<Vector2> polygon; + Vector<Color> colors; + if (shape == edited_navigation_shape && current_shape.size() > 2) { + for (int j = 0; j < current_shape.size(); j++) { + polygon.push_back(current_shape[j]); + colors.push_back(c_bg); + } + } else if (shape->get_polygon_count() > 0) { PoolVector<Vector2> vertices = shape->get_vertices(); - for (int j = 0; j < shape->get_polygon(0).size() - 1; j++) { - workspace->draw_line(vertices[shape->get_polygon(0)[j]] + anchor, vertices[shape->get_polygon(0)[j + 1]] + anchor, c_border, 1, true); + for (int j = 0; j < shape->get_polygon(0).size(); j++) { + polygon.push_back(vertices[shape->get_polygon(0)[j]] + anchor); + colors.push_back(c_bg); } - if (shape == edited_navigation_shape) { - for (int j = 0; j < current_shape.size(); j++) { - workspace->draw_circle(current_shape[j], 8 / workspace->get_scale().x, Color(1, 0, 0)); + } + workspace->draw_polygon(polygon, colors); + if (coord == edited_shape_coord) { + if (shape->get_polygon_count() > 0) { + PoolVector<Vector2> vertices = shape->get_vertices(); + for (int j = 0; j < shape->get_polygon(0).size() - 1; j++) { + workspace->draw_line(vertices[shape->get_polygon(0)[j]] + anchor, vertices[shape->get_polygon(0)[j + 1]] + anchor, c_border, 1, true); + } + if (shape == edited_navigation_shape) { + draw_handles = true; } } } @@ -1461,7 +1530,7 @@ void AutotileEditor::draw_polygon_shapes() { } } -void AutotileEditor::close_shape(const Vector2 &shape_anchor) { +void TileSetEditor::close_shape(const Vector2 &shape_anchor) { creating_shape = false; @@ -1486,7 +1555,11 @@ void AutotileEditor::close_shape(const Vector2 &shape_anchor) { shape->set_points(segments); - tile_set->tile_add_shape(get_current_tile(), shape, Transform2D(), false, edited_shape_coord); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) + tileset->tile_add_shape(get_current_tile(), shape, Transform2D(), false, edited_shape_coord); + else + tileset->tile_set_shape(get_current_tile(), 0, shape); + edited_collision_shape = shape; } @@ -1506,7 +1579,10 @@ void AutotileEditor::close_shape(const Vector2 &shape_anchor) { w = PoolVector<Vector2>::Write(); shape->set_polygon(polygon); - tile_set->autotile_set_light_occluder(get_current_tile(), shape, edited_shape_coord); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) + tileset->autotile_set_light_occluder(get_current_tile(), shape, edited_shape_coord); + else + tileset->tile_set_light_occluder(get_current_tile(), shape); edited_occlusion_shape = shape; tools[TOOL_SELECT]->set_pressed(true); workspace->update(); @@ -1526,55 +1602,99 @@ void AutotileEditor::close_shape(const Vector2 &shape_anchor) { w = PoolVector<Vector2>::Write(); shape->set_vertices(polygon); shape->add_polygon(indices); - tile_set->autotile_set_navigation_polygon(get_current_tile(), shape, edited_shape_coord); + + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE) + tileset->autotile_set_navigation_polygon(get_current_tile(), shape, edited_shape_coord); + else + tileset->tile_set_navigation_polygon(get_current_tile(), shape); edited_navigation_shape = shape; tools[TOOL_SELECT]->set_pressed(true); workspace->update(); } + tileset->_change_notify(""); } -void AutotileEditor::select_coord(const Vector2 &coord) { - int spacing = tile_set->autotile_get_spacing(get_current_tile()); - Vector2 size = tile_set->autotile_get_size(get_current_tile()); - Vector2 shape_anchor = coord; - shape_anchor.x *= (size.x + spacing); - shape_anchor.y *= (size.y + spacing); - if (edit_mode == EDITMODE_COLLISION) { - current_shape.resize(0); - if (edited_collision_shape.is_valid()) { - for (int j = 0; j < edited_collision_shape->get_points().size(); j++) { - current_shape.push_back(edited_collision_shape->get_points()[j] + shape_anchor); +void TileSetEditor::select_coord(const Vector2 &coord) { + current_shape = PoolVector2Array(); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { + if (edited_collision_shape != tileset->tile_get_shape(get_current_tile(), 0)) + edited_collision_shape = tileset->tile_get_shape(get_current_tile(), 0); + if (edited_occlusion_shape != tileset->tile_get_light_occluder(get_current_tile())) + edited_occlusion_shape = tileset->tile_get_light_occluder(get_current_tile()); + if (edited_navigation_shape != tileset->tile_get_navigation_polygon(get_current_tile())) + edited_navigation_shape = tileset->tile_get_navigation_polygon(get_current_tile()); + + if (edit_mode == EDITMODE_COLLISION) { + current_shape.resize(0); + if (edited_collision_shape.is_valid()) { + for (int i = 0; i < edited_collision_shape->get_points().size(); i++) { + current_shape.push_back(edited_collision_shape->get_points()[i]); + } } - } - } else if (edit_mode == EDITMODE_OCCLUSION) { - current_shape.resize(0); - if (edited_occlusion_shape.is_valid()) { - for (int i = 0; i < edited_occlusion_shape->get_polygon().size(); i++) { - current_shape.push_back(edited_occlusion_shape->get_polygon()[i] + shape_anchor); + } else if (edit_mode == EDITMODE_OCCLUSION) { + current_shape.resize(0); + if (edited_occlusion_shape.is_valid()) { + for (int i = 0; i < edited_occlusion_shape->get_polygon().size(); i++) { + current_shape.push_back(edited_occlusion_shape->get_polygon()[i]); + } + } + } else if (edit_mode == EDITMODE_NAVIGATION) { + current_shape.resize(0); + if (edited_navigation_shape.is_valid()) { + if (edited_navigation_shape->get_polygon_count() > 0) { + PoolVector<Vector2> vertices = edited_navigation_shape->get_vertices(); + for (int i = 0; i < edited_navigation_shape->get_polygon(0).size(); i++) { + current_shape.push_back(vertices[edited_navigation_shape->get_polygon(0)[i]]); + } + } } } - } else if (edit_mode == EDITMODE_NAVIGATION) { - current_shape.resize(0); - if (edited_navigation_shape.is_valid()) { - if (edited_navigation_shape->get_polygon_count() > 0) { - PoolVector<Vector2> vertices = edited_navigation_shape->get_vertices(); - for (int i = 0; i < edited_navigation_shape->get_polygon(0).size(); i++) { - current_shape.push_back(vertices[edited_navigation_shape->get_polygon(0)[i]] + shape_anchor); + } else { + int spacing = tileset->autotile_get_spacing(get_current_tile()); + Vector2 size = tileset->autotile_get_size(get_current_tile()); + Vector2 shape_anchor = coord; + shape_anchor.x *= (size.x + spacing); + shape_anchor.y *= (size.y + spacing); + if (edit_mode == EDITMODE_COLLISION) { + current_shape.resize(0); + if (edited_collision_shape.is_valid()) { + for (int j = 0; j < edited_collision_shape->get_points().size(); j++) { + current_shape.push_back(edited_collision_shape->get_points()[j] + shape_anchor); + } + } + } else if (edit_mode == EDITMODE_OCCLUSION) { + current_shape.resize(0); + if (edited_occlusion_shape.is_valid()) { + for (int i = 0; i < edited_occlusion_shape->get_polygon().size(); i++) { + current_shape.push_back(edited_occlusion_shape->get_polygon()[i] + shape_anchor); + } + } + } else if (edit_mode == EDITMODE_NAVIGATION) { + current_shape.resize(0); + if (edited_navigation_shape.is_valid()) { + if (edited_navigation_shape->get_polygon_count() > 0) { + PoolVector<Vector2> vertices = edited_navigation_shape->get_vertices(); + for (int i = 0; i < edited_navigation_shape->get_polygon(0).size(); i++) { + current_shape.push_back(vertices[edited_navigation_shape->get_polygon(0)[i]] + shape_anchor); + } } } } } } -Vector2 AutotileEditor::snap_point(const Vector2 &point) { +Vector2 TileSetEditor::snap_point(const Vector2 &point) { Vector2 p = point; Vector2 coord = edited_shape_coord; - Vector2 tile_size = tile_set->autotile_get_size(get_current_tile()); - int spacing = tile_set->autotile_get_spacing(get_current_tile()); + Vector2 tile_size = tileset->autotile_get_size(get_current_tile()); + int spacing = tileset->autotile_get_spacing(get_current_tile()); Vector2 anchor = coord; anchor.x *= (tile_size.x + spacing); anchor.y *= (tile_size.y + spacing); Rect2 region(anchor, tile_size); + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) + region.position = Point2(0, 0); + if (tools[SHAPE_GRID_SNAP]->is_pressed()) { p.x = Math::snap_scalar_seperation(snap_offset.x, snap_step.x, p.x, snap_separation.x); p.y = Math::snap_scalar_seperation(snap_offset.y, snap_step.y, p.y, snap_separation.y); @@ -1592,86 +1712,136 @@ Vector2 AutotileEditor::snap_point(const Vector2 &point) { return p; } -void AutotileEditor::edit(Object *p_node) { +void TileSetEditor::update_tile_list() { + int selected_tile = get_current_tile(); + + if (selected_tile < 0) + selected_tile = 0; - tile_set = Ref<TileSet>(Object::cast_to<TileSet>(p_node)); - tile_set->add_change_receptor(this); - helper->set_tileset(tile_set); + helper->set_tileset(tileset); - autotile_list->clear(); + tile_list->clear(); List<int> ids; - tile_set->get_tile_list(&ids); + tileset->get_tile_list(&ids); for (List<int>::Element *E = ids.front(); E; E = E->next()) { - if (tile_set->tile_get_is_autotile(E->get())) { - autotile_list->add_item(tile_set->tile_get_name(E->get())); - autotile_list->set_item_metadata(autotile_list->get_item_count() - 1, E->get()); - autotile_list->set_item_icon(autotile_list->get_item_count() - 1, tile_set->tile_get_texture(E->get())); - Rect2 region = tile_set->tile_get_region(E->get()); - region.size = tile_set->autotile_get_size(E->get()); - Vector2 pos = tile_set->autotile_get_icon_coordinate(E->get()); - pos.x *= (tile_set->autotile_get_spacing(E->get()) + region.size.x); - pos.y *= (tile_set->autotile_get_spacing(E->get()) + region.size.y); + tile_list->add_item(tileset->tile_get_name(E->get())); + tile_list->set_item_metadata(tile_list->get_item_count() - 1, E->get()); + tile_list->set_item_icon(tile_list->get_item_count() - 1, tileset->tile_get_texture(E->get())); + Rect2 region = tileset->tile_get_region(E->get()); + if (tileset->tile_get_tile_mode(E->get()) == TileSet::AUTO_TILE) { + region.size = tileset->autotile_get_size(E->get()); + Vector2 pos = tileset->autotile_get_icon_coordinate(E->get()); + pos.x *= (tileset->autotile_get_spacing(E->get()) + region.size.x); + pos.y *= (tileset->autotile_get_spacing(E->get()) + region.size.y); region.position += pos; - autotile_list->set_item_icon_region(autotile_list->get_item_count() - 1, region); } + tile_list->set_item_icon_region(tile_list->get_item_count() - 1, region); } - if (autotile_list->get_item_count() > 0) { - autotile_list->select(0); - _on_autotile_selected(0); + if (tile_list->get_item_count() > 0 && selected_tile < tile_list->get_item_count()) { + tile_list->select(selected_tile); + _on_tile_list_selected(selected_tile); } helper->_change_notify(""); } -int AutotileEditor::get_current_tile() { +void TileSetEditor::update_tile_list_icon() { + List<int> ids; + tileset->get_tile_list(&ids); + int current_idx = 0; + for (List<int>::Element *E = ids.front(); E; E = E->next()) { + if (current_idx >= tile_list->get_item_count()) + break; + + Rect2 region = tileset->tile_get_region(E->get()); + if (tileset->tile_get_tile_mode(E->get()) == TileSet::AUTO_TILE) { + region.size = tileset->autotile_get_size(E->get()); + Vector2 pos = tileset->autotile_get_icon_coordinate(E->get()); + pos.x *= (tileset->autotile_get_spacing(E->get()) + region.size.x); + pos.y *= (tileset->autotile_get_spacing(E->get()) + region.size.y); + region.position += pos; + } + tile_list->set_item_metadata(current_idx, E->get()); + tile_list->set_item_icon(current_idx, tileset->tile_get_texture(E->get())); + tile_list->set_item_icon_region(current_idx, region); + tile_list->set_item_text(current_idx, tileset->tile_get_name(E->get())); + current_idx += 1; + } + tile_list->update(); +} + +void TileSetEditor::update_workspace_tile_mode() { + if (get_current_tile() < 0) + return; + if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { + if (tool_editmode[EDITMODE_ICON]->is_pressed() || tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed()) { + tool_editmode[EDITMODE_COLLISION]->set_pressed(true); + _on_edit_mode_changed(EDITMODE_COLLISION); + } else { + select_coord(Vector2(0, 0)); + } + + tool_editmode[EDITMODE_ICON]->hide(); + tool_editmode[EDITMODE_BITMASK]->hide(); + tool_editmode[EDITMODE_PRIORITY]->hide(); + property_editor->hide(); + } else { + tool_editmode[EDITMODE_ICON]->show(); + tool_editmode[EDITMODE_BITMASK]->show(); + tool_editmode[EDITMODE_PRIORITY]->show(); + property_editor->show(); + } +} - if (autotile_list->get_selected_items().size() == 0) +int TileSetEditor::get_current_tile() { + if (tile_list->get_selected_items().size() == 0) return -1; else - return autotile_list->get_item_metadata(autotile_list->get_selected_items()[0]); + return tile_list->get_item_metadata(tile_list->get_selected_items()[0]); } -void AutotileEditorHelper::set_tileset(const Ref<TileSet> &p_tileset) { +void TileSetEditorHelper::set_tileset(const Ref<TileSet> &p_tileset) { - tile_set = p_tileset; + tileset = p_tileset; } -bool AutotileEditorHelper::_set(const StringName &p_name, const Variant &p_value) { +bool TileSetEditorHelper::_set(const StringName &p_name, const Variant &p_value) { - if (autotile_editor->get_current_tile() < 0 || tile_set.is_null()) + if (selected_tile < 0 || tileset.is_null()) return false; String name = p_name.operator String(); bool v = false; if (name == "bitmask_mode") { - tile_set->set(String::num(autotile_editor->get_current_tile(), 0) + "/autotile/bitmask_mode", p_value, &v); + tileset->set(String::num(selected_tile, 0) + "/autotile/bitmask_mode", p_value, &v); } else if (name.left(7) == "layout/") { - tile_set->set(String::num(autotile_editor->get_current_tile(), 0) + "/autotile" + name.right(6), p_value, &v); + tileset->set(String::num(selected_tile, 0) + "/autotile" + name.right(6), p_value, &v); } if (v) { - tile_set->_change_notify(""); - autotile_editor->workspace->update(); + tileset->_change_notify("autotile"); } return v; } -bool AutotileEditorHelper::_get(const StringName &p_name, Variant &r_ret) const { +bool TileSetEditorHelper::_get(const StringName &p_name, Variant &r_ret) const { - if (autotile_editor->get_current_tile() < 0 || tile_set.is_null()) + if (selected_tile < 0 || tileset.is_null()) + return false; + if (!tileset->has_tile(selected_tile)) return false; String name = p_name.operator String(); bool v = false; if (name == "bitmask_mode") { - r_ret = tile_set->get(String::num(autotile_editor->get_current_tile(), 0) + "/autotile/bitmask_mode", &v); + r_ret = tileset->get(String::num(selected_tile, 0) + "/autotile/bitmask_mode", &v); } else if (name.left(7) == "layout/") { - r_ret = tile_set->get(String::num(autotile_editor->get_current_tile(), 0) + "/autotile" + name.right(6), &v); + r_ret = tileset->get(String::num(selected_tile, 0) + "/autotile" + name.right(6), &v); } return v; } -void AutotileEditorHelper::_get_property_list(List<PropertyInfo> *p_list) const { +void TileSetEditorHelper::_get_property_list(List<PropertyInfo> *p_list) const { - if (autotile_editor->get_current_tile() < 0 || tile_set.is_null()) + if (selected_tile < 0 || tileset.is_null()) return; p_list->push_back(PropertyInfo(Variant::INT, "bitmask_mode", PROPERTY_HINT_ENUM, "2x2,3x3")); @@ -1679,7 +1849,72 @@ void AutotileEditorHelper::_get_property_list(List<PropertyInfo> *p_list) const p_list->push_back(PropertyInfo(Variant::INT, "layout/spacing", PROPERTY_HINT_RANGE, "0,256,1")); } -AutotileEditorHelper::AutotileEditorHelper(AutotileEditor *p_autotile_editor) { +TileSetEditorHelper::TileSetEditorHelper(TileSetEditor *p_tileset_editor) { + + tileset_editor = p_tileset_editor; + selected_tile = -1; +} + +void TileSetEditorPlugin::edit(Object *p_node) { + + if (Object::cast_to<TileSet>(p_node)) { + tileset_editor->edit(Object::cast_to<TileSet>(p_node)); + tileset_editor->show(); + tileset_editor->texture_region_editor->edit(p_node); + } else + tileset_editor->hide(); +} + +bool TileSetEditorPlugin::handles(Object *p_node) const { + + return p_node->is_class("TileSet"); +} + +void TileSetEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + tileset_editor->show(); + tileset_editor->menu->show(); + tileset_editor_button->show(); + tileset_editor->side_panel->show(); + if (tileset_editor_button->is_pressed()) { + tileset_editor->bottom_panel->show(); + } + texture_region_button->show(); + if (texture_region_button->is_pressed()) + tileset_editor->texture_region_editor->show(); + } else { + tileset_editor->hide(); + tileset_editor->menu->hide(); + tileset_editor->side_panel->hide(); + tileset_editor->bottom_panel->hide(); + tileset_editor_button->hide(); + texture_region_button->hide(); + tileset_editor->texture_region_editor->hide(); + } +} + +TileSetEditorPlugin::TileSetEditorPlugin(EditorNode *p_node) { + + tileset_editor = memnew(TileSetEditor(p_node)); + + add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, tileset_editor); + tileset_editor->set_anchors_and_margins_preset(Control::PRESET_TOP_WIDE); + tileset_editor->set_end(Point2(0, 22)); + tileset_editor->hide(); + + tileset_editor->texture_region_editor = memnew(TextureRegionEditor(p_node)); + texture_region_button = p_node->add_bottom_panel_item(TTR("Texture Region"), tileset_editor->texture_region_editor); + texture_region_button->set_tooltip(TTR("Texture Region Editor")); + + tileset_editor->texture_region_editor->set_custom_minimum_size(Size2(0, 200)); + tileset_editor->texture_region_editor->hide(); + texture_region_button->hide(); - autotile_editor = p_autotile_editor; + add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE, tileset_editor->side_panel); + tileset_editor->side_panel->set_anchors_and_margins_preset(Control::PRESET_WIDE); + tileset_editor->side_panel->set_custom_minimum_size(Size2(200, 0)); + tileset_editor->side_panel->hide(); + tileset_editor_button = p_node->add_bottom_panel_item(TTR("Tile Set"), tileset_editor->bottom_panel); + tileset_editor_button->hide(); } diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 30f6e2b925..4894d641a3 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -33,35 +33,38 @@ #include "editor/editor_name_dialog.h" #include "editor/editor_node.h" +#include "editor/plugins/texture_region_editor_plugin.h" #include "scene/2d/sprite.h" #include "scene/resources/convex_polygon_shape_2d.h" #include "scene/resources/tile_set.h" -class AutotileEditorHelper; -class AutotileEditor : public Control { +class TileSetEditorHelper; + +class TileSetEditor : public Control { friend class TileSetEditorPlugin; - friend class AutotileEditorHelper; - GDCLASS(AutotileEditor, Control); + friend class TextureRegionEditor; + + GDCLASS(TileSetEditor, Control); enum EditMode { - EDITMODE_ICON, - EDITMODE_BITMASK, EDITMODE_COLLISION, EDITMODE_OCCLUSION, EDITMODE_NAVIGATION, + EDITMODE_BITMASK, EDITMODE_PRIORITY, + EDITMODE_ICON, EDITMODE_MAX }; - enum AutotileToolbars { + enum TileSetToolbar { TOOLBAR_DUMMY, TOOLBAR_BITMASK, TOOLBAR_SHAPE, TOOLBAR_MAX }; - enum AutotileTools { + enum TileSetTools { TOOL_SELECT, BITMASK_COPY, BITMASK_PASTE, @@ -78,17 +81,18 @@ class AutotileEditor : public Control { TOOL_MAX }; - Ref<TileSet> tile_set; + Ref<TileSet> tileset; + Ref<ConvexPolygonShape2D> edited_collision_shape; Ref<OccluderPolygon2D> edited_occlusion_shape; Ref<NavigationPolygon> edited_navigation_shape; - EditorNode *editor; - int current_item_index; Sprite *preview; ScrollContainer *scroll; Control *workspace_container; + bool draw_handles; + Control *workspace_overlay; Control *workspace; Button *tool_editmode[EDITMODE_MAX]; HBoxContainer *tool_containers[TOOLBAR_MAX]; @@ -114,22 +118,51 @@ class AutotileEditor : public Control { PoolVector2Array current_shape; Map<Vector2, uint16_t> bitmask_map_copy; + EditorNode *editor; + TextureRegionEditor *texture_region_editor; + Control *bottom_panel; Control *side_panel; - ItemList *autotile_list; + ItemList *tile_list; PropertyEditor *property_editor; - AutotileEditorHelper *helper; + TileSetEditorHelper *helper; + + MenuButton *menu; + ConfirmationDialog *cd; + EditorNameDialog *nd; + AcceptDialog *err_dialog; + + enum { - AutotileEditor(EditorNode *p_editor); - ~AutotileEditor(); + MENU_OPTION_ADD_ITEM, + MENU_OPTION_REMOVE_ITEM, + MENU_OPTION_CREATE_FROM_SCENE, + MENU_OPTION_MERGE_FROM_SCENE + }; + + int option; + void _menu_cbk(int p_option); + void _menu_confirm(); + void _name_dialog_confirm(const String &name); + + static void _import_node(Node *p_node, Ref<TileSet> p_library); + static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge); protected: static void _bind_methods(); void _notification(int p_what); virtual void _changed_callback(Object *p_changed, const char *p_prop); +public: + void edit(const Ref<TileSet> &p_tileset); + static Error update_library_file(Node *p_base_scene, Ref<TileSet> ml, bool p_merge = true); + + TileSetEditor(EditorNode *p_editor); + ~TileSetEditor(); + private: - void _on_autotile_selected(int p_index); + void _on_tile_list_selected(int p_index); void _on_edit_mode_changed(int p_edit_mode); + void _on_workspace_overlay_draw(); void _on_workspace_draw(); void _on_workspace_input(const Ref<InputEvent> &p_ie); void _on_tool_clicked(int p_tool); @@ -142,24 +175,28 @@ private: void _set_snap_sep_x(float p_val); void _set_snap_sep_y(float p_val); + void initialize_bottom_editor(); void draw_highlight_tile(Vector2 coord, const Vector<Vector2> &other_highlighted = Vector<Vector2>()); void draw_grid_snap(); void draw_polygon_shapes(); void close_shape(const Vector2 &shape_anchor); void select_coord(const Vector2 &coord); Vector2 snap_point(const Vector2 &point); + void update_tile_list(); + void update_tile_list_icon(); + void update_workspace_tile_mode(); - void edit(Object *p_node); int get_current_tile(); }; -class AutotileEditorHelper : public Object { +class TileSetEditorHelper : public Object { - friend class AutotileEditor; - GDCLASS(AutotileEditorHelper, Object); + friend class TileSetEditor; + GDCLASS(TileSetEditorHelper, Object); - Ref<TileSet> tile_set; - AutotileEditor *autotile_editor; + Ref<TileSet> tileset; + TileSetEditor *tileset_editor; + int selected_tile; public: void set_tileset(const Ref<TileSet> &p_tileset); @@ -169,46 +206,7 @@ protected: bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; - AutotileEditorHelper(AutotileEditor *p_autotile_editor); -}; - -class TileSetEditor : public Control { - - friend class TileSetEditorPlugin; - GDCLASS(TileSetEditor, Control); - - Ref<TileSet> tileset; - - EditorNode *editor; - MenuButton *menu; - ConfirmationDialog *cd; - EditorNameDialog *nd; - AcceptDialog *err_dialog; - - enum { - - MENU_OPTION_ADD_ITEM, - MENU_OPTION_REMOVE_ITEM, - MENU_OPTION_CREATE_FROM_SCENE, - MENU_OPTION_MERGE_FROM_SCENE - }; - - int option; - void _menu_cbk(int p_option); - void _menu_confirm(); - void _name_dialog_confirm(const String &name); - - static void _import_node(Node *p_node, Ref<TileSet> p_library); - static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge); - -protected: - static void _bind_methods(); - -public: - void edit(const Ref<TileSet> &p_tileset); - static Error update_library_file(Node *p_base_scene, Ref<TileSet> ml, bool p_merge = true); - - TileSetEditor(EditorNode *p_editor); + TileSetEditorHelper(TileSetEditor *p_tileset_editor); }; class TileSetEditorPlugin : public EditorPlugin { @@ -216,10 +214,10 @@ class TileSetEditorPlugin : public EditorPlugin { GDCLASS(TileSetEditorPlugin, EditorPlugin); TileSetEditor *tileset_editor; - AutotileEditor *autotile_editor; EditorNode *editor; - ToolButton *autotile_button; + ToolButton *tileset_editor_button; + ToolButton *texture_region_button; public: virtual String get_name() const { return "TileSet"; } diff --git a/editor/project_export.cpp b/editor/project_export.cpp index d15a37a19c..4dbd9d500e 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -56,6 +56,12 @@ void ProjectExportDialog::_notification(int p_what) { case NOTIFICATION_POPUP_HIDE: { EditorSettings::get_singleton()->set("interface/dialogs/export_bounds", get_rect()); } break; + case NOTIFICATION_THEME_CHANGED: { + delete_preset->set_icon(get_icon("Remove", "EditorIcons")); + Control *panel = custom_feature_display->get_parent_control(); + if (panel) + panel->add_style_override("panel", get_stylebox("bg", "Tree")); + } break; } } diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index da283b16dc..5f93e984cc 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -304,8 +304,9 @@ private: ProjectSettings *current = memnew(ProjectSettings); - if (current->setup(dir, "")) { - set_message(TTR("Couldn't get project.godot in project path."), MESSAGE_ERROR); + int err = current->setup(dir, ""); + 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(); @@ -530,8 +531,9 @@ public: ProjectSettings *current = memnew(ProjectSettings); - if (current->setup(project_path->get_text(), "")) { - set_message(TTR("Couldn't get project.godot in the project path."), MESSAGE_ERROR); + int err = current->setup(project_path->get_text(), ""); + 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); status_rect->show(); msg->show(); get_ok()->set_disabled(true); @@ -687,7 +689,7 @@ void ProjectManager::_notification(int p_what) { } break; case NOTIFICATION_READY: { - if (scroll_children->get_child_count() == 0) + if (scroll_children->get_child_count() == 0 && StreamPeerSSL::is_available()) open_templates->popup_centered_minsize(); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -713,6 +715,12 @@ void ProjectManager::_update_project_buttons() { CanvasItem *item = Object::cast_to<CanvasItem>(scroll_children->get_child(i)); item->update(); + + Button *show = Object::cast_to<Button>(item->get_node(NodePath("project/path_box/show"))); + if (show) { + String current = item->get_meta("name"); + show->set_visible(selected_list.has(current)); + } } erase_btn->set_disabled(selected_list.size() < 1); @@ -1092,9 +1100,26 @@ void ProjectManager::_load_recent_projects() { title->add_color_override("font_color", font_color); title->set_clip_text(true); vb->add_child(title); + + HBoxContainer *path_hb = memnew(HBoxContainer); + path_hb->set_name("path_box"); + path_hb->set_h_size_flags(SIZE_EXPAND_FILL); + vb->add_child(path_hb); + + Button *show = memnew(Button); + show->set_name("show"); + show->set_icon(get_icon("Filesystem", "EditorIcons")); + show->set_flat(true); + show->set_modulate(Color(1, 1, 1, 0.5)); + path_hb->add_child(show); + show->connect("pressed", this, "_show_project", varray(path)); + show->set_tooltip(TTR("Show In File Manager")); + show->set_visible(false); + Label *fpath = memnew(Label(path)); fpath->set_name("path"); - vb->add_child(fpath); + path_hb->add_child(fpath); + fpath->set_h_size_flags(SIZE_EXPAND_FILL); fpath->set_modulate(Color(1, 1, 1, 0.5)); fpath->add_color_override("font_color", font_color); fpath->set_clip_text(true); @@ -1124,7 +1149,7 @@ void ProjectManager::_on_project_created(const String &dir) { 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)); - Label *fpath = Object::cast_to<Label>(hb->get_node(NodePath("project/path"))); + Label *fpath = Object::cast_to<Label>(hb->get_node(NodePath("project/path_box/path"))); if (fpath->get_text() == dir) { has_already = true; break; @@ -1142,7 +1167,7 @@ void ProjectManager::_on_project_created(const String &dir) { void ProjectManager::_update_scroll_position(const String &dir) { for (int i = 0; i < scroll_children->get_child_count(); i++) { HBoxContainer *hb = Object::cast_to<HBoxContainer>(scroll_children->get_child(i)); - Label *fpath = Object::cast_to<Label>(hb->get_node(NodePath("project/path"))); + Label *fpath = Object::cast_to<Label>(hb->get_node(NodePath("project/path_box/path"))); if (fpath->get_text() == dir) { last_clicked = hb->get_meta("name"); selected_list.clear(); @@ -1260,6 +1285,11 @@ void ProjectManager::_run_project() { } } +void ProjectManager::_show_project(const String &p_path) { + + OS::get_singleton()->shell_open(String("file://") + p_path); +} + void ProjectManager::_scan_dir(DirAccess *da, float pos, float total, List<String> *r_projects) { List<String> subdirs; @@ -1448,6 +1478,7 @@ void ProjectManager::_bind_methods() { ClassDB::bind_method("_open_project_confirm", &ProjectManager::_open_project_confirm); ClassDB::bind_method("_run_project", &ProjectManager::_run_project); ClassDB::bind_method("_run_project_confirm", &ProjectManager::_run_project_confirm); + ClassDB::bind_method("_show_project", &ProjectManager::_show_project); ClassDB::bind_method("_scan_projects", &ProjectManager::_scan_projects); ClassDB::bind_method("_scan_begin", &ProjectManager::_scan_begin); ClassDB::bind_method("_import_project", &ProjectManager::_import_project); @@ -1539,7 +1570,7 @@ ProjectManager::ProjectManager() { String hash = String(VERSION_HASH); if (hash.length() != 0) hash = "." + hash.left(7); - l->set_text("v" VERSION_MKSTRING "" + hash); + l->set_text("v" VERSION_FULL_BUILD "" + hash); l->set_align(Label::ALIGN_CENTER); top_hb->add_child(l); diff --git a/editor/project_manager.h b/editor/project_manager.h index 23ffa2f857..a9d23b1f71 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -85,6 +85,7 @@ class ProjectManager : public Control { void _run_project_confirm(); void _open_project(); void _open_project_confirm(); + void _show_project(const String &p_path); void _import_project(); void _new_project(); void _rename_project(); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 9625bc19c0..8080a04a67 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -110,6 +110,14 @@ void ProjectSettingsEditor::_notification(int p_what) { EditorSettings::get_singleton()->set("interface/dialogs/project_settings_bounds", get_rect()); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + + search_button->set_icon(get_icon("Search", "EditorIcons")); + clear_button->set_icon(get_icon("Close", "EditorIcons")); + action_add_error->add_color_override("font_color", get_color("error_color", "Editor")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY), get_icon("Keyboard", "EditorIcons")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_BUTTON), get_icon("JoyButton", "EditorIcons")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_MOTION), get_icon("JoyAxis", "EditorIcons")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_MOUSE_BUTTON), get_icon("Mouse", "EditorIcons")); _update_actions(); } break; } @@ -137,12 +145,12 @@ void ProjectSettingsEditor::_action_edited() { if (new_name == old_name) return; - if (new_name.find("/") != -1 || new_name.find(":") != -1 || new_name == "") { + if (new_name.find("/") != -1 || new_name.find(":") != -1 || new_name.find("\"") != -1 || new_name == "") { ti->set_text(0, old_name); add_at = "input/" + old_name; - message->set_text(TTR("Invalid action (anything goes but '/' or ':').")); + message->set_text(TTR("Invalid action (anything goes but '/', ':' or '\"').")); message->popup_centered(Size2(300, 100) * EDSCALE); return; } @@ -830,9 +838,9 @@ void ProjectSettingsEditor::_action_check(String p_action) { action_add->set_disabled(true); } else { - if (p_action.find("/") != -1 || p_action.find(":") != -1) { + if (p_action.find("/") != -1 || p_action.find(":") != -1 || p_action.find("\"") != -1) { - action_add_error->set_text(TTR("Can't contain '/' or ':'")); + action_add_error->set_text(TTR("Can't contain '/', ':' or '\"'")); action_add_error->show(); action_add->set_disabled(true); return; diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 452cf5b060..9364b0ff2c 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -176,6 +176,8 @@ public: void popup_project_settings(); void set_plugins_page(); + EditorAutoloadSettings *get_autoload_settings() { return autoload_settings; } + TabContainer *get_tabs(); void queue_save(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 8506c75a68..002d702bac 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1402,70 +1402,81 @@ void SceneTreeDock::_create() { Node *newnode = Object::cast_to<Node>(c); ERR_FAIL_COND(!newnode); - List<PropertyInfo> pinfo; - n->get_property_list(&pinfo); - - for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) - continue; - if (E->get().name == "__meta__") - continue; - newnode->set(E->get().name, n->get(E->get().name)); - } + replace_node(n, newnode); + } + } +} - editor->push_item(NULL); +void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node) { - //reconnect signals - List<MethodInfo> sl; + Node *n = p_node; + Node *newnode = p_by_node; + Node *default_oldnode = Object::cast_to<Node>(ClassDB::instance(n->get_class())); + List<PropertyInfo> pinfo; + n->get_property_list(&pinfo); - n->get_signal_list(&sl); - for (List<MethodInfo>::Element *E = sl.front(); E; E = E->next()) { + for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + continue; + if (E->get().name == "__meta__") + continue; + if (default_oldnode->get(E->get().name) != n->get(E->get().name)) { + newnode->set(E->get().name, n->get(E->get().name)); + } + } + memdelete(default_oldnode); - List<Object::Connection> cl; - n->get_signal_connection_list(E->get().name, &cl); + editor->push_item(NULL); - for (List<Object::Connection>::Element *F = cl.front(); F; F = F->next()) { + //reconnect signals + List<MethodInfo> sl; - Object::Connection &c = F->get(); - if (!(c.flags & Object::CONNECT_PERSIST)) - continue; - newnode->connect(c.signal, c.target, c.method, varray(), Object::CONNECT_PERSIST); - } - } + n->get_signal_list(&sl); + for (List<MethodInfo>::Element *E = sl.front(); E; E = E->next()) { - String newname = n->get_name(); + List<Object::Connection> cl; + n->get_signal_connection_list(E->get().name, &cl); - List<Node *> to_erase; - for (int i = 0; i < n->get_child_count(); i++) { - if (n->get_child(i)->get_owner() == NULL && n->is_owned_by_parent()) { - to_erase.push_back(n->get_child(i)); - } - } - n->replace_by(newnode, true); + for (List<Object::Connection>::Element *F = cl.front(); F; F = F->next()) { - if (n == edited_scene) { - edited_scene = newnode; - editor->set_edited_scene(newnode); - newnode->set_editable_instances(n->get_editable_instances()); - } + Object::Connection &c = F->get(); + if (!(c.flags & Object::CONNECT_PERSIST)) + continue; + newnode->connect(c.signal, c.target, c.method, varray(), Object::CONNECT_PERSIST); + } + } - //small hack to make collisionshapes and other kind of nodes to work - for (int i = 0; i < newnode->get_child_count(); i++) { - Node *c = newnode->get_child(i); - c->call("set_transform", c->call("get_transform")); - } - editor_data->get_undo_redo().clear_history(); - newnode->set_name(newname); + String newname = n->get_name(); + + List<Node *> to_erase; + for (int i = 0; i < n->get_child_count(); i++) { + if (n->get_child(i)->get_owner() == NULL && n->is_owned_by_parent()) { + to_erase.push_back(n->get_child(i)); + } + } + n->replace_by(newnode, true); - editor->push_item(newnode); + if (n == edited_scene) { + edited_scene = newnode; + editor->set_edited_scene(newnode); + newnode->set_editable_instances(n->get_editable_instances()); + } - memdelete(n); + //small hack to make collisionshapes and other kind of nodes to work + for (int i = 0; i < newnode->get_child_count(); i++) { + Node *c = newnode->get_child(i); + c->call("set_transform", c->call("get_transform")); + } + editor_data->get_undo_redo().clear_history(); + newnode->set_name(newname); - while (to_erase.front()) { - memdelete(to_erase.front()->get()); - to_erase.pop_front(); - } - } + editor->push_item(newnode); + + memdelete(n); + + while (to_erase.front()) { + memdelete(to_erase.front()->get()); + to_erase.pop_front(); } } @@ -1885,8 +1896,6 @@ void SceneTreeDock::_local_tree_selected() { remote_tree->hide(); edit_remote->set_pressed(false); edit_local->set_pressed(true); - - _node_selected(); } void SceneTreeDock::_bind_methods() { diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 0a68aa7dc2..a4f36e31ee 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -208,6 +208,8 @@ public: void show_tab_buttons(); void hide_tab_buttons(); + void replace_node(Node *p_node, Node *p_by_node); + void open_script_dialog(Node *p_for_node); SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data); }; diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index fd21b83605..e38347a653 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -69,24 +69,10 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i emit_signal("open_script", script); } else if (p_id == BUTTON_VISIBILITY) { - - if (n->is_class("Spatial")) { - - bool v = bool(n->call("is_visible")); - undo_redo->create_action(TTR("Toggle Spatial Visible")); - undo_redo->add_do_method(n, "set_visible", !v); - undo_redo->add_undo_method(n, "set_visible", v); - undo_redo->commit_action(); - - } else if (n->is_class("CanvasItem")) { - - bool v = bool(n->call("is_visible")); - undo_redo->create_action(TTR("Toggle CanvasItem Visible")); - undo_redo->add_do_method(n, v ? "hide" : "show"); - undo_redo->add_undo_method(n, v ? "show" : "hide"); - undo_redo->commit_action(); - } - + undo_redo->create_action(TTR("Toggle Visible")); + undo_redo->add_do_method(this, "toggle_visible", n); + undo_redo->add_undo_method(this, "toggle_visible", n); + undo_redo->commit_action(); } else if (p_id == BUTTON_LOCK) { if (n->is_class("CanvasItem") || n->is_class("Spatial")) { @@ -131,7 +117,34 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i NodeDock::singleton->show_groups(); } } +void SceneTreeEditor::_toggle_visible(Node *p_node) { + if (p_node->is_class("Spatial")) { + bool v = bool(p_node->call("is_visible")); + p_node->call("set_visible", !v); + } else if (p_node->is_class("CanvasItem")) { + bool v = bool(p_node->call("is_visible")); + if (v) { + p_node->call("hide"); + } else { + p_node->call("show"); + } + } +} +void SceneTreeEditor::toggle_visible(Node *p_node) { + _toggle_visible(p_node); + List<Node *> selection = editor_selection->get_selected_node_list(); + if (selection.size() > 1) { + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { + Node *nv = E->get(); + ERR_FAIL_COND(!nv); + if (nv == p_node) { + continue; + } + _toggle_visible(nv); + } + } +} bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { if (!p_node) @@ -523,6 +536,7 @@ void SceneTreeEditor::_notification(int p_what) { tree->connect("item_collapsed", this, "_cell_collapsed"); EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed"); + _editor_settings_changed(); //get_scene()->connect("tree_changed",this,"_tree_changed",Vector<Variant>(),CONNECT_DEFERRED); //get_scene()->connect("node_removed",this,"_node_removed",Vector<Variant>(),CONNECT_DEFERRED); @@ -536,6 +550,10 @@ void SceneTreeEditor::_notification(int p_what) { get_tree()->disconnect("node_configuration_warning_changed", this, "_warning_changed"); EditorSettings::get_singleton()->disconnect("settings_changed", this, "_editor_settings_changed"); } + if (p_what == NOTIFICATION_THEME_CHANGED) { + + _update_tree(); + } } TreeItem *SceneTreeEditor::_find(TreeItem *p_node, const NodePath &p_path) { @@ -949,6 +967,8 @@ void SceneTreeEditor::_bind_methods() { ClassDB::bind_method("_cell_collapsed", &SceneTreeEditor::_cell_collapsed); ClassDB::bind_method("_rmb_select", &SceneTreeEditor::_rmb_select); ClassDB::bind_method("_warning_changed", &SceneTreeEditor::_warning_changed); + ClassDB::bind_method("_toggle_visible", &SceneTreeEditor::_toggle_visible); + ClassDB::bind_method("toggle_visible", &SceneTreeEditor::toggle_visible); ClassDB::bind_method("_node_script_changed", &SceneTreeEditor::_node_script_changed); ClassDB::bind_method("_node_visibility_changed", &SceneTreeEditor::_node_visibility_changed); diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index 45194bb81d..b63eb2a1f0 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -70,6 +70,8 @@ class SceneTreeEditor : public Control { void _compute_hash(Node *p_node, uint64_t &hash); + void toggle_visible(Node *p_node); + bool _add_nodes(Node *p_node, TreeItem *p_parent); void _test_update_tree(); void _update_tree(); @@ -103,6 +105,7 @@ class SceneTreeEditor : public Control { static void _bind_methods(); void _cell_button_pressed(Object *p_item, int p_column, int p_id); + void _toggle_visible(Node *p_node); void _cell_multi_selected(Object *p_object, int p_cell, bool p_selected); void _update_selection(TreeItem *item); void _node_script_changed(Node *p_node); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index e56a7f2a55..57a003060e 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -41,10 +41,12 @@ void ScriptCreateDialog::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { path_button->set_icon(get_icon("Folder", "EditorIcons")); parent_browse_button->set_icon(get_icon("Folder", "EditorIcons")); - } + status_panel->add_style_override("panel", get_stylebox("bg", "Tree")); + } break; } } @@ -434,6 +436,13 @@ void ScriptCreateDialog::_path_changed(const String &p_path) { return; } + String path_error = ScriptServer::get_language(language_menu->get_selected())->validate_path(p); + if (path_error != "") { + _msg_path_valid(false, path_error); + _update_dialog(); + return; + } + /* All checks passed */ is_path_valid = true; @@ -535,15 +544,19 @@ void ScriptCreateDialog::_update_dialog() { /* Is Script created or loaded from existing file */ - if (is_new_script_created) { + if (is_built_in) { + get_ok()->set_text(TTR("Create")); + parent_name->set_editable(true); + parent_browse_button->set_disabled(false); + internal->set_disabled(!supports_built_in); + _msg_path_valid(true, TTR("Built-in script (into scene file)")); + } else if (is_new_script_created) { // New Script Created get_ok()->set_text(TTR("Create")); parent_name->set_editable(true); parent_browse_button->set_disabled(false); internal->set_disabled(!supports_built_in); - if (is_built_in) { - _msg_path_valid(true, TTR("Built-in script (into scene file)")); - } else if (is_path_valid) { + if (is_path_valid) { _msg_path_valid(true, TTR("Create new script file")); } } else { @@ -551,7 +564,7 @@ void ScriptCreateDialog::_update_dialog() { get_ok()->set_text(TTR("Load")); parent_name->set_editable(false); parent_browse_button->set_disabled(true); - internal->set_disabled(true); + internal->set_disabled(!supports_built_in); if (is_path_valid) { _msg_path_valid(true, TTR("Load existing script file")); } @@ -605,10 +618,10 @@ ScriptCreateDialog::ScriptCreateDialog() { hb->add_child(path_error_label); vb->add_child(hb); - PanelContainer *pc = memnew(PanelContainer); - pc->set_h_size_flags(Control::SIZE_FILL); - pc->add_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_stylebox("bg", "Tree")); - pc->add_child(vb); + status_panel = memnew(PanelContainer); + status_panel->set_h_size_flags(Control::SIZE_FILL); + status_panel->add_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_stylebox("bg", "Tree")); + status_panel->add_child(vb); /* Margins */ @@ -627,7 +640,7 @@ ScriptCreateDialog::ScriptCreateDialog() { vb->add_child(empty_h->duplicate()); vb->add_child(gc); vb->add_child(empty_h->duplicate()); - vb->add_child(pc); + vb->add_child(status_panel); vb->add_child(empty_h->duplicate()); hb = memnew(HBoxContainer); hb->add_child(empty_v->duplicate()); diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h index 99e5bc9e6a..1ad4a1b7a1 100644 --- a/editor/script_create_dialog.h +++ b/editor/script_create_dialog.h @@ -46,6 +46,7 @@ class ScriptCreateDialog : public ConfirmationDialog { LineEdit *class_name; Label *error_label; Label *path_error_label; + PanelContainer *status_panel; LineEdit *parent_name; Button *parent_browse_button; OptionButton *language_menu; diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 86ab84909e..e9529eb1c0 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -948,7 +948,7 @@ void ScriptEditorDebugger::_notification(int p_what) { inspector->edit(variables); - copy->set_icon(get_icon("Duplicate", "EditorIcons")); + copy->set_icon(get_icon("ActionCopy", "EditorIcons")); step->set_icon(get_icon("DebugStep", "EditorIcons")); next->set_icon(get_icon("DebugNext", "EditorIcons")); @@ -965,6 +965,14 @@ void ScriptEditorDebugger::_notification(int p_what) { reason->add_color_override("font_color", get_color("error_color", "Editor")); + bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines"); + Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color"); + + if (enable_rl) { + inspect_scene_tree->add_constant_override("draw_relationship_lines", 1); + inspect_scene_tree->add_color_override("relationship_line_color", rl_color); + } else + inspect_scene_tree->add_constant_override("draw_relationship_lines", 0); } break; case NOTIFICATION_PROCESS: { @@ -1152,6 +1160,16 @@ void ScriptEditorDebugger::_notification(int p_what) { inspect_scene_tree->add_color_override("relationship_line_color", rl_color); } else inspect_scene_tree->add_constant_override("draw_relationship_lines", 0); + + copy->set_icon(get_icon("ActionCopy", "EditorIcons")); + step->set_icon(get_icon("DebugStep", "EditorIcons")); + next->set_icon(get_icon("DebugNext", "EditorIcons")); + back->set_icon(get_icon("Back", "EditorIcons")); + forward->set_icon(get_icon("Forward", "EditorIcons")); + dobreak->set_icon(get_icon("Pause", "EditorIcons")); + docontinue->set_icon(get_icon("DebugContinue", "EditorIcons")); + vmem_refresh->set_icon(get_icon("Reload", "EditorIcons")); + } break; } } @@ -1277,14 +1295,14 @@ void ScriptEditorDebugger::_stack_dump_frame_selected() { emit_signal("goto_script_line", stack_script, int(d["line"]) - 1); stack_script.unref(); - ERR_FAIL_COND(connection.is_null()); - ERR_FAIL_COND(!connection->is_connected_to_host()); - /// - - Array msg; - msg.push_back("get_stack_frame_vars"); - msg.push_back(d["frame"]); - ppeer->put_var(msg); + if (connection.is_valid() && connection->is_connected_to_host()) { + Array msg; + msg.push_back("get_stack_frame_vars"); + msg.push_back(d["frame"]); + ppeer->put_var(msg); + } else { + inspector->edit(NULL); + } } void ScriptEditorDebugger::_output_clear() { @@ -1638,12 +1656,20 @@ void ScriptEditorDebugger::_error_selected(int p_idx) { md.push_back(st[i + 1]); md.push_back(st[i + 2]); - String str = func + " in " + script.get_file() + ":line " + itos(line); + String str = func; + String tooltip_str = TTR("Function:") + " " + func; + if (script.length() > 0) { + str += " in " + script.get_file(); + tooltip_str = TTR("File:") + " " + script + "\n" + tooltip_str; + if (line > 0) { + str += ":line " + itos(line); + tooltip_str += "\n" + TTR("Line:") + " " + itos(line); + } + } error_stack->add_item(str); error_stack->set_item_metadata(error_stack->get_item_count() - 1, md); - error_stack->set_item_tooltip(error_stack->get_item_count() - 1, - TTR("File:") + " " + script + "\n" + TTR("Function:") + " " + func + "\n" + TTR("Line:") + " " + itos(line)); + error_stack->set_item_tooltip(error_stack->get_item_count() - 1, tooltip_str); } } @@ -1726,7 +1752,7 @@ void ScriptEditorDebugger::_error_list_item_rmb_selected(int p_item, const Vecto bool single_item_selected = error_list->get_selected_items().size() == 1; if (single_item_selected) { - item_menu->add_icon_item(get_icon("CopyNodePath", "EditorIcons"), TTR("Copy Error"), ITEM_MENU_COPY_ERROR); + item_menu->add_icon_item(get_icon("ActionCopy", "EditorIcons"), TTR("Copy Error"), ITEM_MENU_COPY_ERROR); } if (item_menu->get_item_count() > 0) { @@ -1873,6 +1899,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { sc->set_v_size_flags(SIZE_EXPAND_FILL); stack_dump = memnew(Tree); + stack_dump->set_allow_reselect(true); stack_dump->set_columns(1); stack_dump->set_column_titles_visible(true); stack_dump->set_column_title(0, TTR("Stack Frames")); diff --git a/editor/translations/af.po b/editor/translations/af.po index 9d4ce1e29d..0f5a2b890f 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -2400,12 +2400,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2458,10 +2452,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3634,15 +3624,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4465,6 +4455,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4748,10 +4754,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4764,6 +4766,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5604,11 +5610,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5869,10 +5870,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5894,7 +5891,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5914,10 +5913,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6608,10 +6603,6 @@ msgstr "Hulpbron" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6721,10 +6712,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7148,11 +7135,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7160,19 +7159,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7281,6 +7280,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Skep Intekening" @@ -7297,6 +7300,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7799,6 +7806,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/ar.po b/editor/translations/ar.po index deb49f0619..7e9f894292 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -19,8 +19,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-24 11:45+0000\n" -"Last-Translator: anonymous <>\n" +"PO-Revision-Date: 2018-01-30 16:34+0000\n" +"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n" "Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/" "godot/ar/>\n" "Language: ar\n" @@ -2445,12 +2445,6 @@ msgid "Invalid version.txt format inside templates." msgstr "صيغة غير صالØØ© لـ version.txt داخل القالب." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "صيغة غير صالØØ© لـ version.txt داخل القالب. المراجعة ليست معرÙاً صالØاً." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "لا مل٠version.txt تم إيجاده داخل القالب." @@ -2505,10 +2499,6 @@ msgid "Failed:" msgstr "Ùشل:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "لا يمكن كتابة الملÙ." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "التØميل إكتمل." @@ -3685,15 +3675,15 @@ msgid "Show Grid" msgstr "إظهار الشبكة" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "أظهر المساعدات" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "أظهر المساطر" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "أظهر الموجهات" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4520,6 +4510,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4802,10 +4808,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "إلغاء/تÙعيل طي الخط" @@ -4818,6 +4820,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5658,11 +5664,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5922,10 +5923,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5946,7 +5943,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5966,10 +5965,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6657,10 +6652,6 @@ msgstr "مورد Ùرعي" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6770,10 +6761,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "ÙØªØ Ø§Ù„ÙƒÙˆØ¯" @@ -7201,11 +7188,25 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +#, fuzzy +msgid "Next Plane" +msgstr "التبويب التالي" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Plane" +msgstr "التبويب السابق" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7213,19 +7214,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7326,15 +7327,19 @@ msgstr "تم" #: modules/mono/editor/godotsharp_editor.cpp msgid "Failed to create C# project." -msgstr "Ùشل إنشاء مشروع C#." +msgstr "Ùشل إنشاء مشروع C#‎." #: modules/mono/editor/godotsharp_editor.cpp msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" -msgstr "إنشاء ØÙ„ C#" +msgstr "إنشاء ØÙ„ C#‎" #: modules/mono/editor/mono_bottom_panel.cpp msgid "Builds" @@ -7348,6 +7353,10 @@ msgstr "بناء المشروع" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7851,6 +7860,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8012,6 +8029,15 @@ msgstr "" msgid "Invalid font size." msgstr "" +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "صيغة غير صالØØ© لـ version.txt داخل القالب. المراجعة ليست معرÙاً صالØاً." + +#~ msgid "Can't write file." +#~ msgstr "لا يمكن كتابة الملÙ." + #~ msgid "Next" #~ msgstr "التالي" diff --git a/editor/translations/bg.po b/editor/translations/bg.po index ecef737d82..24b9345051 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -2375,12 +2375,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2435,11 +2429,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -#, fuzzy -msgid "Can't write file." -msgstr "ÐеуÑпешно Ñъздаване на папка." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3629,15 +3618,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4463,6 +4452,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4748,10 +4753,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Изтриване на анимациÑта?" @@ -4765,6 +4766,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5612,11 +5617,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5882,10 +5882,6 @@ msgid "Please choose an empty folder." msgstr "МолÑ, изнеÑете извън папката на проекта!" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "ВнеÑен проект" @@ -5907,7 +5903,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5928,10 +5926,6 @@ msgid "Rename Project" msgstr "Ðов проект" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6629,10 +6623,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6747,10 +6737,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "Ðова Ñцена" @@ -7196,32 +7182,46 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +#, fuzzy +msgid "Next Plane" +msgstr "Следващ подпрозорец" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Plane" +msgstr "Предишен подпрозорец" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Floor" +msgstr "Предишен подпрозорец" + +#: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "Previous Floor" -msgstr "Предишен подпрозорец" +msgid "Grid Map" +msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7335,6 +7335,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7351,6 +7355,10 @@ msgstr "Проект" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7883,6 +7891,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8049,6 +8065,10 @@ msgid "Invalid font size." msgstr "" #, fuzzy +#~ msgid "Can't write file." +#~ msgstr "ÐеуÑпешно Ñъздаване на папка." + +#, fuzzy #~ msgid "Setting '" #~ msgstr "ÐаÑтройки" diff --git a/editor/translations/bn.po b/editor/translations/bn.po index b50fc38439..ff5533e22e 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -2519,13 +2519,6 @@ msgid "Invalid version.txt format inside templates." msgstr "টেমপà§à¦²à§‡à¦Ÿ à¦à¦° version.txt ফরমà§à¦¯à¦¾à¦Ÿ গà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯ নয়।" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"টেমপà§à¦²à§‡à¦Ÿ à¦à¦° version.txt ফরমà§à¦¯à¦¾à¦Ÿ অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯à¥¤ Revision কোন কাংখিত আইডেনà§à¦Ÿà¦¿à¦«à¦¾à§Ÿà¦¾à¦° নয়।" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "টেমপà§à¦²à§‡à¦Ÿà§‡ version.txt খà§à¦à¦œà§‡ পাওয়া যায়নি।" @@ -2585,11 +2578,6 @@ msgstr "বà§à¦¯à¦°à§à¦¥:" #: editor/export_template_manager.cpp #, fuzzy -msgid "Can't write file." -msgstr "টাইলটি খà§à¦à¦œà§‡ পাওয়া যায়নি:" - -#: editor/export_template_manager.cpp -#, fuzzy msgid "Download Complete." msgstr "নীচে" @@ -3839,17 +3827,17 @@ msgstr "গà§à¦°à¦¿à¦¡ দেখান" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show helpers" +msgid "Show Helpers" msgstr "বোনà§â€Œ/হাড় দেখান" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show rulers" +msgid "Show Rulers" msgstr "বোনà§â€Œ/হাড় দেখান" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show guides" +msgid "Show Guides" msgstr "বোনà§â€Œ/হাড় দেখান" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4719,6 +4707,22 @@ msgid "Resource clipboard is empty!" msgstr "রিসোরà§à¦¸à§‡à¦° কà§à¦²à§€à¦ªà¦¬à§‹à¦°à§à¦¡ খালি!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "à¦à¦¡à¦¿à¦Ÿà¦°à§‡ খà§à¦²à§à¦¨" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "ধরণ:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "রিসোরà§à¦¸ লোড করà§à¦¨" @@ -5017,10 +5021,6 @@ msgid "Toggle Comment" msgstr "কমেনà§à¦Ÿ টগল করà§à¦¨" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "কà§à¦²à§‹à¦¨ করে নীচে নিন" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "লাইন আনফোলà§à¦¡ করà§à¦¨" @@ -5034,6 +5034,10 @@ msgid "Unfold All Lines" msgstr "সবগà§à¦²à¦¿ লাইন আনফোলà§à¦¡ করà§à¦¨" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "কà§à¦²à§‹à¦¨ করে নীচে নিন" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "সিমà§à¦¬à¦² সমà§à¦ªà§‚রà§à¦£ করà§à¦¨" @@ -5908,11 +5912,6 @@ msgstr "টà§à¦¯à¦¾à¦¬ ২" msgid "Tab 3" msgstr "টà§à¦¯à¦¾à¦¬ ৩" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "ধরণ:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "ডাটার ধরণ:" @@ -6204,10 +6203,6 @@ msgid "Please choose an empty folder." msgstr "অনà§à¦—à§à¦°à¦¹ করে পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° ফোলà§à¦¡à¦¾à¦°à§‡à¦° বাইরে à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿ করà§à¦¨!" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "à¦à¦®à¦¨ à¦à¦•à¦Ÿà¦¿ ফোলà§à¦¡à¦¾à¦° বাছাই করà§à¦¨ যেখানে 'project.godot' নামে কোন ফাইল নেই।" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "পà§à¦°à¦•à¦²à§à¦ª ইমà§à¦ªà§‹à¦°à§à¦Ÿ করা হয়েছে" @@ -6230,7 +6225,9 @@ msgstr "অকারà§à¦¯à¦•à¦° পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথ (কোনৠ#: editor/project_manager.cpp #, fuzzy -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦à¦¬ হয়নি।" #: editor/project_manager.cpp @@ -6253,11 +6250,6 @@ msgid "Rename Project" msgstr "নামহীন পà§à¦°à¦•à¦²à§à¦ª" #: editor/project_manager.cpp -#, fuzzy -msgid "Couldn't get project.godot in the project path." -msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦à¦¬ হয়নি।" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "নতà§à¦¨ গেম পà§à¦°à¦•à¦²à§à¦ª" @@ -6992,10 +6984,6 @@ msgstr "রিসোরà§à¦¸à¦¸à¦®à§‚হ:" msgid "Clear Inheritance" msgstr "উতà§à¦¤à¦°à¦¾à¦§à¦¿à¦•à¦¾à¦°à¦¤à§à¦¬ পরিসà§à¦•à¦¾à¦° করà§à¦¨" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "à¦à¦¡à¦¿à¦Ÿà¦°à§‡ খà§à¦²à§à¦¨" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "নোড(সমূহ) অপসারণ করà§à¦¨" @@ -7117,10 +7105,6 @@ msgstr "" "গà§à¦°à§à¦ª ডক পà§à¦°à¦¦à¦°à§à¦¶à¦¨ করতে কà§à¦²à¦¿à¦• করà§à¦¨à¥¤" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸:" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "পরবরà§à¦¤à§€ সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ" @@ -7570,13 +7554,26 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অপসারণ করà§à¦¨" +msgid "Next Plane" +msgstr "পরের টà§à¦¯à¦¾à¦¬" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অনà§à¦²à¦¿à¦ªà¦¿ করà§à¦¨" +msgid "Previous Plane" +msgstr "পূরà§à¦¬à§‡à¦° টà§à¦¯à¦¾à¦¬" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Floor" +msgstr "পূরà§à¦¬à§‡à¦° টà§à¦¯à¦¾à¦¬" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" @@ -7584,22 +7581,23 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Grid Map" -msgstr "গà§à¦°à¦¿à¦¡ সà§à¦¨à§à¦¯à¦¾à¦ª" +msgid "GridMap Delete Selection" +msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অপসারণ করà§à¦¨" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Snap View" -msgstr "শীরà§à¦· দরà§à¦¶à¦¨" +msgid "GridMap Duplicate Selection" +msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অনà§à¦²à¦¿à¦ªà¦¿ করà§à¦¨" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Previous Floor" -msgstr "পূরà§à¦¬à§‡à¦° টà§à¦¯à¦¾à¦¬" +msgid "Grid Map" +msgstr "গà§à¦°à¦¿à¦¡ সà§à¦¨à§à¦¯à¦¾à¦ª" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "" +#, fuzzy +msgid "Snap View" +msgstr "শীরà§à¦· দরà§à¦¶à¦¨" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy @@ -7721,6 +7719,10 @@ msgid "Mono" msgstr "মনো" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "পà§à¦°à¦¾à¦¨à§à¦¤à¦°à§‡à¦–া তৈরি করà§à¦¨" @@ -7739,6 +7741,10 @@ msgstr "নতà§à¦¨ পà§à¦°à¦•à¦²à§à¦ª" msgid "Warnings" msgstr "সতরà§à¦•à¦¤à¦¾" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8301,6 +8307,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp #, fuzzy msgid "Plotting Meshes: " msgstr "ছবিসমূহ বà§à¦²à¦¿à¦Ÿà¦¿à¦‚ (Blitting) করা হচà§à¦›à§‡" @@ -8491,6 +8505,28 @@ msgstr "ফনà§à¦Ÿ তà§à¦²à¦¤à§‡/লোডে সমসà§à¦¯à¦¾ হয়েঠmsgid "Invalid font size." msgstr "ফনà§à¦Ÿà§‡à¦° আকার অগà§à¦°à¦¹à¦¨à¦¯à§‹à¦—à§à¦¯à¥¤" +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "টেমপà§à¦²à§‡à¦Ÿ à¦à¦° version.txt ফরমà§à¦¯à¦¾à¦Ÿ অগà§à¦°à¦¹à¦£à¦¯à§‹à¦—à§à¦¯à¥¤ Revision কোন কাংখিত আইডেনà§à¦Ÿà¦¿à¦«à¦¾à§Ÿà¦¾à¦° " +#~ "নয়।" + +#, fuzzy +#~ msgid "Can't write file." +#~ msgstr "টাইলটি খà§à¦à¦œà§‡ পাওয়া যায়নি:" + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "à¦à¦®à¦¨ à¦à¦•à¦Ÿà¦¿ ফোলà§à¦¡à¦¾à¦° বাছাই করà§à¦¨ যেখানে 'project.godot' নামে কোন ফাইল নেই।" + +#, fuzzy +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦à¦¬ হয়নি।" + +#, fuzzy +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "পà§à¦°à¦•à¦²à§à¦ªà§‡à¦° পথে engine.cfg তৈরি করা সমà§à¦à¦¬ হয়নি।" + #~ msgid "Next" #~ msgstr "পরবরà§à¦¤à§€" diff --git a/editor/translations/ca.po b/editor/translations/ca.po index 91d1d55e64..5af9d98ec6 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-24 02:50+0000\n" +"PO-Revision-Date: 2018-02-27 02:34+0000\n" "Last-Translator: Roger Blanco Ribera <roger.blancoribera@gmail.com>\n" "Language-Team: Catalan <https://hosted.weblate.org/projects/godot-engine/" "godot/ca/>\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -2455,14 +2455,6 @@ msgid "Invalid version.txt format inside templates." msgstr "El format de version.txt dins de les plantilles no és và lid." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"El format de version.txt dins les plantilles no és và lid. \"Revision\" no és " -"un indentificador và lid." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "No s'ha trobat cap version.txt dins les plantilles." @@ -2517,10 +2509,6 @@ msgid "Failed:" msgstr "Ha fallat:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "No es pot escriure el fitxer." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Baixada Completa." @@ -3702,15 +3690,15 @@ msgid "Show Grid" msgstr "Mostra la graella" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Mostrar els Ajudants" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Mostra els regles" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Mostra les guies" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -3984,7 +3972,7 @@ msgstr "La Malla continguda no és del tipus ArrayMesh." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "UV Unwrap failed, mesh may not be manifold?" -msgstr "No s'han pogut desembolcar les UV. Comproveu la topologia de la malla" +msgstr "No s'han pogut desembolcar les UV. Comproveu la topologia de la malla." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "No mesh to debug." @@ -4537,6 +4525,22 @@ msgid "Resource clipboard is empty!" msgstr "El porta-retalls de Recursos és buit!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Obre en l'Editor" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Instà ncia:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Tipus:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Carrega un Recurs" @@ -4823,10 +4827,6 @@ msgid "Toggle Comment" msgstr "Comentaris" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Clona avall" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "(Des)Plega la lÃnia" @@ -4839,6 +4839,10 @@ msgid "Unfold All Lines" msgstr "Desplega totes les LÃnies" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Clona avall" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Completa el SÃmbol" @@ -5682,11 +5686,6 @@ msgstr "Pestanya 2" msgid "Tab 3" msgstr "Pestanya 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Tipus:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Tipus de Dades:" @@ -5955,11 +5954,6 @@ msgid "Please choose an empty folder." msgstr "Selecciona un directori buit." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" -"Seleccioneu un directori que no contingui ja un fitxer 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Project importat" @@ -5980,8 +5974,12 @@ msgid "Invalid project path (changed anything?)." msgstr "El Camà del Projecte no és và lid (S'ha produit algun canvi?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "No s'ha trobat el fitxer 'project.godot' en el camà del Projecte." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"No es pot carregar el fitxer 'project.godot' en el camà del projecte (error " +"%d). Pot ser que falti o que estigui malmès." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6000,10 +5998,6 @@ msgid "Rename Project" msgstr "Reanomena el Projecte" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "No es pot trobat el el fitxer 'project.godot' en el camà del projecte." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Nou Projecte de Joc" @@ -6706,10 +6700,6 @@ msgstr "Sub-Recursos" msgid "Clear Inheritance" msgstr "Elimina l'Herència" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Obre en l'Editor" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Elimina els Nodes" @@ -6827,10 +6817,6 @@ msgstr "" "Clic per mostrar el Tauler de Grups." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Instà ncia:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Obre un Script" @@ -7261,32 +7247,44 @@ msgid "Object can't provide a length." msgstr "L'objecte no pot proporcionar una longitud." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "Elimina la Selecció del GridMap" +msgid "Next Plane" +msgstr "Pla següent" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "Duplica la Selecció del GridMap" +msgid "Previous Plane" +msgstr "Pla anterior" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "Pla:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Planta Següent" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Planta Anterior" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Planta:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Mapa de Graella" +msgid "GridMap Delete Selection" +msgstr "Elimina la Selecció del GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "Alinea la Vista" +msgid "GridMap Duplicate Selection" +msgstr "Duplica la Selecció del GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Planta Anterior" +msgid "Grid Map" +msgstr "Mapa de Graella" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Planta Següent" +msgid "Snap View" +msgstr "Alinea la Vista" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7393,6 +7391,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "Sobre el suport de C#" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "Crea una solució en C#" @@ -7408,6 +7410,10 @@ msgstr "Munta el Projecte" msgid "Warnings" msgstr "Avisos" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7960,6 +7966,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "El node ARVROrigin requreix un node Fill del tipus ARVRCamera" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(Temps restant: %d:%02d s)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "S'està n traçant les Malles: " @@ -8159,6 +8173,27 @@ msgstr "Error carregant lletra." msgid "Invalid font size." msgstr "La mida de la lletra no és và lida." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "El format de version.txt dins les plantilles no és và lid. \"Revision\" no " +#~ "és un indentificador và lid." + +#~ msgid "Can't write file." +#~ msgstr "No es pot escriure el fitxer." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "Seleccioneu un directori que no contingui ja un fitxer 'project.godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "No s'ha trobat el fitxer 'project.godot' en el camà del Projecte." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "" +#~ "No es pot trobat el el fitxer 'project.godot' en el camà del projecte." + #~ msgid "Next" #~ msgstr "Següent" diff --git a/editor/translations/cs.po b/editor/translations/cs.po index ce645b139b..aa29f16038 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -2428,13 +2428,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Neplatný formát version.txt uvnitÅ™ Å¡ablon." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Neplatný formát version.txt uvnitÅ™ Å¡ablon. Revize nenà platný identifikátor." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Nenalezena version.txt uvnitÅ™ Å¡ablon." @@ -2487,10 +2480,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Nelze zapsat soubor." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3670,15 +3659,15 @@ msgstr "Zobrazit mřÞku" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show helpers" +msgid "Show Helpers" msgstr "Zobrazit pomocné" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Zobrazit pravÃtka" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Zobrazit vodÃtka" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4514,6 +4503,22 @@ msgid "Resource clipboard is empty!" msgstr "Schránka zdroje je prázdná!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "NaÄÃst zdroj" @@ -4801,10 +4806,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Běž na řádek" @@ -4818,6 +4819,10 @@ msgid "Unfold All Lines" msgstr "Rozložit vÅ¡echny řádky" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5665,11 +5670,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5936,10 +5936,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5960,7 +5956,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5980,10 +5978,6 @@ msgid "Rename Project" msgstr "PÅ™ejmenovat projekt" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6676,10 +6670,6 @@ msgstr "DÃlÄà zdroje" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6792,10 +6782,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "OtevÅ™Ãt skript" @@ -7225,32 +7211,46 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "Smazat vybraný" +msgid "Next Plane" +msgstr "DalÅ¡Ã záložka" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "Duplikovat výbÄ›r" +msgid "Previous Plane" +msgstr "PÅ™edchozà záložka" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Delete Selection" +msgstr "Smazat vybraný" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "GridMap Duplicate Selection" +msgstr "Duplikovat výbÄ›r" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7364,6 +7364,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "VytvoÅ™it C# Å™eÅ¡enÃ" @@ -7380,6 +7384,10 @@ msgstr "Sestavit projekt" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp #, fuzzy msgid "" @@ -7924,6 +7932,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8114,6 +8130,16 @@ msgstr "Chyba nahrávánà fontu." msgid "Invalid font size." msgstr "Neplatná velikost fontu." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Neplatný formát version.txt uvnitÅ™ Å¡ablon. Revize nenà platný " +#~ "identifikátor." + +#~ msgid "Can't write file." +#~ msgstr "Nelze zapsat soubor." + #~ msgid "Next" #~ msgstr "DalÅ¡Ã" diff --git a/editor/translations/da.po b/editor/translations/da.po index 786cabcbdc..ca47dc00e1 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -2485,14 +2485,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Ugyldigt version.txt format inde i skabeloner." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Ugyldigt version.txt format inde i skabeloner. Revision er ikke en gyldig " -"identifikator." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Ingen version.txt fundet inde i skabeloner." @@ -2550,10 +2542,6 @@ msgid "Failed:" msgstr "Fejlet:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Kan ikke skrive til fil." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Download fuldført." @@ -3742,15 +3730,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4581,6 +4569,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4866,10 +4870,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Fold Line" @@ -4883,6 +4883,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5725,11 +5729,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5991,10 +5990,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -6016,7 +6011,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -6036,10 +6033,6 @@ msgid "Rename Project" msgstr "Omdøb Projekt" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6733,10 +6726,6 @@ msgstr "Sub-Ressourcer:" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6847,10 +6836,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Ã…ben script" @@ -7277,31 +7262,45 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "GridMap Slet Markerede" +msgid "Next Plane" +msgstr "Næste fane" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "GridMap Duplikér Markerede" +#, fuzzy +msgid "Previous Plane" +msgstr "Forrige fane" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Delete Selection" +msgstr "GridMap Slet Markerede" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "GridMap Duplicate Selection" +msgstr "GridMap Duplikér Markerede" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7412,6 +7411,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Opret Abonnement" @@ -7429,6 +7432,10 @@ msgstr "Projekt" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7969,6 +7976,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8154,6 +8169,16 @@ msgstr "Error loading skrifttype." msgid "Invalid font size." msgstr "Ugyldig skriftstørrelse." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Ugyldigt version.txt format inde i skabeloner. Revision er ikke en gyldig " +#~ "identifikator." + +#~ msgid "Can't write file." +#~ msgstr "Kan ikke skrive til fil." + #~ msgid "Next" #~ msgstr "Næste" diff --git a/editor/translations/de.po b/editor/translations/de.po index d0fa1597a5..87f69c3fde 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -28,7 +28,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-01-22 08:08+0000\n" +"PO-Revision-Date: 2018-02-12 08:36+0000\n" "Last-Translator: So Wieso <sowieso@dukun.de>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" @@ -53,11 +53,11 @@ msgstr "Schlüsselbildzeit ändern" #: editor/animation_editor.cpp msgid "Anim Change Transition" -msgstr "Ãœbergang beim Animationswechsel" +msgstr "Ãœbergang bearbeiten" #: editor/animation_editor.cpp msgid "Anim Change Transform" -msgstr "Transformation ändern" +msgstr "Transformation bearbeiten" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Value" @@ -207,11 +207,11 @@ msgstr "Animation bereinigen" #: editor/animation_editor.cpp msgid "Create NEW track for %s and insert key?" -msgstr "NEUE Spur für %s erstellenund Schlüsselbild hinzufügen?" +msgstr "NEUE Spur für %s erstellen und Schlüsselbild hinzufügen?" #: editor/animation_editor.cpp msgid "Create %d NEW tracks and insert keys?" -msgstr "%d NEUE Spuren erstelleb und Schlüsselbilder hinzufügen?" +msgstr "%d NEUE Spuren erstellen und Schlüsselbilder hinzufügen?" #: editor/animation_editor.cpp editor/create_dialog.cpp #: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp @@ -267,11 +267,11 @@ msgstr "Länge (s):" #: editor/animation_editor.cpp msgid "Animation length (in seconds)." -msgstr "Animationslänge (in Sekunden)." +msgstr "Animationsdauer (in Sekunden)." #: editor/animation_editor.cpp msgid "Step (s):" -msgstr "Schritte (s):" +msgstr "Schrittweite (s):" #: editor/animation_editor.cpp msgid "Cursor step snap (in seconds)." @@ -279,7 +279,7 @@ msgstr "Cursor Schrittraster (in Sekunden)." #: editor/animation_editor.cpp msgid "Enable/Disable looping in animation." -msgstr "Animationswiederholung aktivieren/deaktivieren." +msgstr "Animationsschleife aktivieren/deaktivieren." #: editor/animation_editor.cpp msgid "Add new tracks." @@ -344,7 +344,7 @@ msgstr "Skalierungsverhältnis:" #: editor/animation_editor.cpp msgid "Call Functions in Which Node?" -msgstr "In welcher Node sollen die Funktionen aufgerufen werden?" +msgstr "Node dessen Funktionen aufgerufen werden sollen auswählen." #: editor/animation_editor.cpp msgid "Remove invalid keys" @@ -360,7 +360,7 @@ msgstr "Alle Animationen bereinigen" #: editor/animation_editor.cpp msgid "Clean-Up Animation(s) (NO UNDO!)" -msgstr "Alle Animationen bereinigen (Kann nicht rückgängig gemacht werden!)" +msgstr "Animationen bereinigen (Kann nicht rückgängig gemacht werden!)" #: editor/animation_editor.cpp msgid "Clean-Up" @@ -507,7 +507,7 @@ msgstr "Verbinden" #: editor/connections_dialog.cpp msgid "Connect '%s' to '%s'" -msgstr "Verbinde '%s' zu '%s'" +msgstr "Verbinde ‚%s‘ mit ‚%s‘" #: editor/connections_dialog.cpp msgid "Connecting Signal:" @@ -577,23 +577,23 @@ msgstr "Suche Ersatz für:" #: editor/dependency_editor.cpp msgid "Dependencies For:" -msgstr "Abhängigkeiten Für:" +msgstr "Abhängigkeiten für:" #: editor/dependency_editor.cpp msgid "" "Scene '%s' is currently being edited.\n" "Changes will not take effect unless reloaded." msgstr "" -"Die Szene '%s' wird momentan bearbeitet.\n" -"Änderungen werden nicht angezeigt bis die Szene neu geladen wird." +"Die Szene ‚%s‘ wird momentan bearbeitet.\n" +"Änderungen werden erst wirksam, wenn die Szene neu geladen wird." #: editor/dependency_editor.cpp msgid "" "Resource '%s' is in use.\n" "Changes will take effect when reloaded." msgstr "" -"Die Ressource '%s' wird momentan benutzt.\n" -"Änderungen werden erst nach Neuladen der Ressource aktiv." +"Die Ressource ‚%s‘ wird momentan benutzt.\n" +"Änderungen werden erst durch Neuladen wirksam." #: editor/dependency_editor.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp @@ -624,7 +624,7 @@ msgstr "Abhängigkeiteneditor" #: editor/dependency_editor.cpp msgid "Search Replacement Resource:" -msgstr "Ersatz-Ressource suchen:" +msgstr "Ersatzressource suchen:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help.cpp editor/editor_node.cpp editor/filesystem_dock.cpp @@ -649,8 +649,8 @@ msgid "" "work.\n" "Remove them anyway? (no undo)" msgstr "" -"Die zu entfernenden Dateien werden von anderen Ressourcen gebraucht, damit " -"sie richtig funktionieren können.\n" +"Andere Ressourcen benötigen die zu entfernenden Dateien, um richtig zu " +"funktionieren.\n" "Trotzdem entfernen? (Kann nicht rückgängig gemacht werden)" #: editor/dependency_editor.cpp @@ -721,7 +721,7 @@ msgstr "Wörterbuchwert ändern" #: editor/editor_about.cpp msgid "Thanks from the Godot community!" -msgstr "Danke von der Godot-Community!" +msgstr "Die Godot-Gemeinschaft bedankt sich!" #: editor/editor_about.cpp msgid "Thanks!" @@ -741,7 +741,7 @@ msgstr "Hauptentwickler" #: editor/editor_about.cpp msgid "Project Manager " -msgstr "Projektverwalter " +msgstr "Projektverwaltung " #: editor/editor_about.cpp msgid "Developers" @@ -753,27 +753,27 @@ msgstr "Autoren" #: editor/editor_about.cpp msgid "Platinum Sponsors" -msgstr "Platinum Sponsoren" +msgstr "Platin-Sponsoren" #: editor/editor_about.cpp msgid "Gold Sponsors" -msgstr "Gold Sponsoren" +msgstr "Gold-Sponsoren" #: editor/editor_about.cpp msgid "Mini Sponsors" -msgstr "Mini Sponsoren" +msgstr "Mini-Sponsoren" #: editor/editor_about.cpp msgid "Gold Donors" -msgstr "Gold Unterstützer" +msgstr "Gold-Unterstützer" #: editor/editor_about.cpp msgid "Silver Donors" -msgstr "Silver Unterstützer" +msgstr "Silber-Unterstützer" #: editor/editor_about.cpp msgid "Bronze Donors" -msgstr "Bronze Unterstützer" +msgstr "Bronze-Unterstützer" #: editor/editor_about.cpp msgid "Donors" @@ -794,10 +794,10 @@ msgid "" "is an exhaustive list of all such thirdparty components with their " "respective copyright statements and license terms." msgstr "" -"Die Godot-Engine baut auf einer Vielzahl freier und quelloffener projekt-" -"externer Bibliotheken auf, die alle kompatibel mit den Auflagen der MIT-" -"Lizenz sind. Es folgt eine vollständige Liste aller verwendeten externen " -"Bibliotheken mit den jeweiligen zugehörigen Urheberrechtserklärungen und " +"Die Godot-Engine baut auf vielen freien und quelloffenen Bibliotheken von " +"Drittanbietern auf, welche alle mit der MIT-Lizenz konform sind. Es folgt " +"eine vollständige Liste aller verwendeten Bibliotheken von Drittanbietern " +"mit den jeweiligen zugehörigen Urheberrechtserklärungen und " "Lizenzbedingungen." #: editor/editor_about.cpp @@ -836,7 +836,7 @@ msgstr "Installieren" #: editor/editor_asset_installer.cpp msgid "Package Installer" -msgstr "Paketinstaller" +msgstr "Erweiterungenverwaltung" #: editor/editor_audio_buses.cpp msgid "Speakers" @@ -844,7 +844,7 @@ msgstr "Lautsprecher" #: editor/editor_audio_buses.cpp msgid "Add Effect" -msgstr "Audiobuseffekt hinzufügen" +msgstr "Effekt hinzufügen" #: editor/editor_audio_buses.cpp msgid "Rename Audio Bus" @@ -868,7 +868,7 @@ msgstr "Audiobus Bypasseffekte umschalten" #: editor/editor_audio_buses.cpp msgid "Select Audio Bus Send" -msgstr "Audiobus Senden auswählen" +msgstr "Audiobus senden auswählen" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus Effect" @@ -983,7 +983,7 @@ msgstr "Lade ein existierendes Bus-Layout." #: editor/editor_audio_buses.cpp #: editor/plugins/animation_player_editor_plugin.cpp msgid "Save As" -msgstr "Speichern als" +msgstr "Speichern unter" #: editor/editor_audio_buses.cpp msgid "Save this Bus Layout to a file." @@ -995,7 +995,7 @@ msgstr "Standard laden" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." -msgstr "Standart Bus Layout laden." +msgstr "Standard Bus-Layout laden." #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -1364,8 +1364,9 @@ msgid "" "$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/" "url][/color]." msgstr "" -"Es gibt zurzeit keine Tutorials zu dieser Klasse. [color=$color][url=" -"$url]Ergänzungen durch eigene Beiträge[/url][/color] sind sehr erwünscht!" +"Es gibt zurzeit keine Tutorials zu dieser Klasse. Mitwirkungen durch [color=" +"$color][url=$url]eigene Beiträge[/url][/color] oder [color=$color][url=" +"$url2]Meldung von Problemen[/url][/color] sind sehr erwünscht." #: editor/editor_help.cpp msgid "Properties" @@ -2485,14 +2486,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Ungültiges version.txt-Format in Templates." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Ungültiges version.txt-Format in Templates. Revision ist kein gültiger " -"Bezeichner." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Keine version.txt in Templates gefunden." @@ -2547,10 +2540,6 @@ msgid "Failed:" msgstr "Fehlgeschlagen:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Konnte Datei nicht schreiben." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Download abgeschlossen." @@ -2909,7 +2898,7 @@ msgstr "Gruppen" #: editor/node_dock.cpp msgid "Select a Node to edit Signals and Groups." -msgstr "Wähle ein Node um Signale und Gruppen zu bearbeiten." +msgstr "Node auswählen um Signale und Gruppen zu bearbeiten." #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -3738,15 +3727,15 @@ msgid "Show Grid" msgstr "Raster anzeigen" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Helfer anzeigen" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Lineale anzeigen" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Hilfslinien anzeigen" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4577,6 +4566,22 @@ msgid "Resource clipboard is empty!" msgstr "Zwischenablage für Ressourcen ist leer!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Im Editor öffnen" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Instanz:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Typ:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Ressource laden" @@ -4863,10 +4868,6 @@ msgid "Toggle Comment" msgstr "Kommentar umschalten" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Klone herunter" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Zeile ein/aufklappen" @@ -4879,6 +4880,10 @@ msgid "Unfold All Lines" msgstr "Alle Zeilen aufklappen" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Klone herunter" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Symbol vervollständigen" @@ -5722,11 +5727,6 @@ msgstr "Tab 2" msgid "Tab 3" msgstr "Tab 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Typ:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Datentyp:" @@ -5994,10 +5994,6 @@ msgid "Please choose an empty folder." msgstr "Bitte einen leeren Ordner auswählen." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "Ein Ordner ohne ‚project.godot‘-Datei muss ausgewählt werden." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Importiertes Projekt" @@ -6019,8 +6015,11 @@ msgid "Invalid project path (changed anything?)." msgstr "Ungültiger Projektpfad (etwas geändert?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "project.godot konnte nicht im Projektpfad gefunden werden." +#, fuzzy +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "project.godot des Projektpfads konnte nicht bearbeitet werden." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6039,10 +6038,6 @@ msgid "Rename Project" msgstr "Projekt umbenennen" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "project.godot konnte nicht im Projektpfad gefunden werden." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Neues Spiel" @@ -6750,10 +6745,6 @@ msgstr "Unter-Ressourcen" msgid "Clear Inheritance" msgstr "Leere Vererbung" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Im Editor öffnen" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Node(s) löschen" @@ -6871,10 +6862,6 @@ msgstr "" "Hier klicken zur Gruppenverwaltung." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Instanz:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Skript öffnen" @@ -6917,7 +6904,7 @@ msgstr "Node-Konfigurationswarnung!" #: editor/scene_tree_editor.cpp msgid "Select a Node" -msgstr "Wähle ein Node" +msgstr "Node auswählen" #: editor/script_create_dialog.cpp msgid "Error loading template '%s'" @@ -7306,32 +7293,46 @@ msgid "Object can't provide a length." msgstr "Objekt kann keine Länge vorweisen." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "GridMap-Auswahl löschen" +#, fuzzy +msgid "Next Plane" +msgstr "Nächster Tab" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "GridMap-Auswahl duplizieren" +#, fuzzy +msgid "Previous Plane" +msgstr "Vorheriger Tab" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Nächste Ebene" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Vorherige Ebene" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Ebene:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Gitterkarte" +msgid "GridMap Delete Selection" +msgstr "GridMap-Auswahl löschen" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "Sicht einrasten" +msgid "GridMap Duplicate Selection" +msgstr "GridMap-Auswahl duplizieren" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Vorherige Ebene" +msgid "Grid Map" +msgstr "Gitterkarte" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Nächste Ebene" +msgid "Snap View" +msgstr "Sicht einrasten" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7438,6 +7439,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "Erzeuge C#-Lösung" @@ -7453,6 +7458,10 @@ msgstr "Projekt bauen" msgid "Warnings" msgstr "Warnungen" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8017,6 +8026,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin benötigt ein ARVRCamera-Unterobjekt" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "Plotte Meshe: " @@ -8222,6 +8239,25 @@ msgstr "Fehler beim Laden der Schriftart." msgid "Invalid font size." msgstr "Ungültige Schriftgröße." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Ungültiges version.txt-Format in Templates. Revision ist kein gültiger " +#~ "Bezeichner." + +#~ msgid "Can't write file." +#~ msgstr "Konnte Datei nicht schreiben." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "Ein Ordner ohne ‚project.godot‘-Datei muss ausgewählt werden." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "project.godot konnte nicht im Projektpfad gefunden werden." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "project.godot konnte nicht im Projektpfad gefunden werden." + #~ msgid "Next" #~ msgstr "Nächste" diff --git a/editor/translations/de_CH.po b/editor/translations/de_CH.po index e0d10c9264..a9b1b8a994 100644 --- a/editor/translations/de_CH.po +++ b/editor/translations/de_CH.po @@ -2398,12 +2398,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2457,11 +2451,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -#, fuzzy -msgid "Can't write file." -msgstr "Neues Projekt erstellen" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3662,15 +3651,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4510,6 +4499,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4793,10 +4798,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Bild einfügen" @@ -4810,6 +4811,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5661,11 +5666,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5932,10 +5932,6 @@ msgid "Please choose an empty folder." msgstr "Bitte ausserhalb des Projekt Verzeichnis exportieren!" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Importierte Projekte" @@ -5958,7 +5954,9 @@ msgstr "Ungültiger Projektpfad, (wurde was geändert?)!" #: editor/project_manager.cpp #, fuzzy -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden." #: editor/project_manager.cpp @@ -5981,11 +5979,6 @@ msgid "Rename Project" msgstr "Neues Projekt erstellen" #: editor/project_manager.cpp -#, fuzzy -msgid "Couldn't get project.godot in the project path." -msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6690,10 +6683,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Node(s) löschen" @@ -6808,10 +6797,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "Script hinzufügen" @@ -7244,11 +7229,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7256,19 +7253,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7380,6 +7377,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7396,6 +7397,10 @@ msgstr "Projektname:" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7940,6 +7945,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8105,6 +8118,18 @@ msgstr "" msgid "Invalid font size." msgstr "" +#, fuzzy +#~ msgid "Can't write file." +#~ msgstr "Neues Projekt erstellen" + +#, fuzzy +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden." + +#, fuzzy +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "Die engine.cfg kann im Projektverzeichnis nicht erstellt werden." + #~ msgid "Move Add Key" #~ msgstr "Bild bewegen/einfügen" diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index a1e1b1d4ae..7a13a5bcc8 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -2357,12 +2357,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2415,10 +2409,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3581,15 +3571,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4412,6 +4402,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4694,10 +4700,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4710,6 +4712,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5550,11 +5556,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5814,10 +5815,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5838,7 +5835,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5858,10 +5857,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6549,10 +6544,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6662,10 +6653,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7088,11 +7075,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7100,19 +7099,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7220,6 +7219,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7235,6 +7238,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7734,6 +7741,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/el.po b/editor/translations/el.po index e8841a9338..6eea5da60d 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-24 19:46+0000\n" +"PO-Revision-Date: 2018-02-27 22:19+0000\n" "Last-Translator: George Tsiamasiotis <gtsiam@windowslive.com>\n" "Language-Team: Greek <https://hosted.weblate.org/projects/godot-engine/godot/" "el/>\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -2460,14 +2460,6 @@ msgid "Invalid version.txt format inside templates." msgstr "ΆκυÏη μοÏφή version.txt μÎσα στα Ï€Ïότυπα." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"ΆκυÏη μοÏφή version.txt μÎσα στα Ï€Ïότυπα. Το Revision δεν είναι ÎγκυÏο " -"αναγνωÏιστικό." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Δεν βÏÎθηκε version.txt μÎσα στα Ï€Ïότυπα." @@ -2522,10 +2514,6 @@ msgid "Failed:" msgstr "ΑπÎτυχε:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Δεν ήταν δυνατή η εγγÏαφή στο αÏχείο." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Η λήψη ολοκληÏώθηκε." @@ -3716,15 +3704,15 @@ msgid "Show Grid" msgstr "Εμφάνιση πλÎγματος" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Εμφάνιση βοηθών" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Εμφάνιση χαÏάκων" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Εμφάνιση οδηγών" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4555,6 +4543,22 @@ msgid "Resource clipboard is empty!" msgstr "Το Ï€ÏόχειÏο πόÏων είναι άδειο!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Άνοιγμα στον επεξεÏγαστή" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Στιγμιότυπο:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "ΤÏπος:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "ΦόÏτωση πόÏου" @@ -4841,10 +4845,6 @@ msgid "Toggle Comment" msgstr "Εναλλαγή σχολιασμοÏ" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Κλωνοποίηση κάτω" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Δίπλωμα/Ξεδίπλωμα γÏαμμής" @@ -4857,6 +4857,10 @@ msgid "Unfold All Lines" msgstr "Ξεδίπλωμα όλων των γÏαμμών" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Κλωνοποίηση κάτω" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "ΣυμπλήÏωση συμβόλου" @@ -5702,11 +5706,6 @@ msgstr "ΚαÏÏ„Îλα 2" msgid "Tab 3" msgstr "ΚαÏÏ„Îλα 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "ΤÏπος:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "ΤÏπος δεδομÎνων:" @@ -5976,11 +5975,6 @@ msgid "Please choose an empty folder." msgstr "ΠαÏακαλοÏμε επιλÎξτε Îναν άδειο φάκελο." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" -"ΠαÏακαλοÏμε επιλÎξτε Îναν φάκελο που δεν πεÏιÎχει Îνα αÏχείο 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "ΕισαγμÎνο ÎÏγο" @@ -6001,8 +5995,12 @@ msgid "Invalid project path (changed anything?)." msgstr "Μη ÎγκυÏη διαδÏομή ÎÏγου (Αλλάξατε τίποτα;)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "Δεν βÏÎθηκε το project.godot στη διαδÏομή του ÎÏγου." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"ΑδÏνατη η φόÏτωση του project.godot (σφάλμα %d). ΜποÏεί να λείπει ή να είναι " +"κατεστÏαμÎνο." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6022,10 +6020,6 @@ msgid "Rename Project" msgstr "Μετονομασία ÎÏγου" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "Δεν βÏÎθηκε το project.godot στη διαδÏομή του ÎÏγου." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "ÎÎο ÎÏγο παιχνιδιοÏ" @@ -6736,10 +6730,6 @@ msgstr "Yπο-Î ÏŒÏοι" msgid "Clear Inheritance" msgstr "ΕκκαθάÏιση κληÏονομικότητας" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Άνοιγμα στον επεξεÏγαστή" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "ΔιαγÏαφή Κόμβων" @@ -6857,10 +6847,6 @@ msgstr "" "Πατήστε για να δείξετε την πλατφόÏμα σημάτων." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Στιγμιότυπο:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Άνοιγμα δεσμής ενεÏγειών" @@ -7293,32 +7279,44 @@ msgid "Object can't provide a length." msgstr "Το αντικείμενο δεν Îχει μήκος." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "GridMap ΔιαγÏαφή επιλογής" +msgid "Next Plane" +msgstr "Επόμενο επίπεδο" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "GridMap Διπλασιασμός επιλογής" +msgid "Previous Plane" +msgstr "Î ÏοηγοÏμενο επίπεδο" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "Επίπεδο:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Επόμενο πάτωμα" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Î ÏοηγοÏμενο πάτωμα" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Δάπεδο:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "ΧάÏτης δικτÏου" +msgid "GridMap Delete Selection" +msgstr "GridMap ΔιαγÏαφή επιλογής" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "ΚοÏμπωμα όψης" +msgid "GridMap Duplicate Selection" +msgstr "GridMap Διπλασιασμός επιλογής" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Î ÏοηγοÏμενο πάτωμα" +msgid "Grid Map" +msgstr "ΧάÏτης δικτÏου" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Επόμενο πάτωμα" +msgid "Snap View" +msgstr "ΚοÏμπωμα όψης" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7425,6 +7423,10 @@ msgid "Mono" msgstr "Μονοφωνικό" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "Σχετικά με την υποστήÏιξη C#" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "ΔημιουÏγία λÏσης C#" @@ -7440,6 +7442,10 @@ msgstr "Δόμηση ÎÏγου" msgid "Warnings" msgstr "Î Ïοειδοποιήσεις" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7998,6 +8004,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "Το ARVROrigin απαιτεί Îναν κόμβο ARVRCamera ως παιδί" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(ΟλοκλήÏωση σε: %d:%02d s)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "ΤοποθÎτηση πλεγμάτων: " @@ -8202,6 +8216,27 @@ msgstr "Σφάλμα κατά την φόÏτωση της γÏαμματοσεΠmsgid "Invalid font size." msgstr "Μη ÎγκυÏο μÎγεθος γÏαμματοσειÏάς." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "ΆκυÏη μοÏφή version.txt μÎσα στα Ï€Ïότυπα. Το Revision δεν είναι ÎγκυÏο " +#~ "αναγνωÏιστικό." + +#~ msgid "Can't write file." +#~ msgstr "Δεν ήταν δυνατή η εγγÏαφή στο αÏχείο." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "ΠαÏακαλοÏμε επιλÎξτε Îναν φάκελο που δεν πεÏιÎχει Îνα αÏχείο 'project." +#~ "godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "Δεν βÏÎθηκε το project.godot στη διαδÏομή του ÎÏγου." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "Δεν βÏÎθηκε το project.godot στη διαδÏομή του ÎÏγου." + #~ msgid "Next" #~ msgstr "Επόμενο" diff --git a/editor/translations/es.po b/editor/translations/es.po index df1a38d45b..b9b342114c 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -8,26 +8,29 @@ # Alejandro Alvarez <eliluminado00@gmail.com>, 2017. # BLaDoM GUY <simplybladom@gmail.com>, 2017. # Carlos López <genetita@gmail.com>, 2016. +# David Arranz <davarrcal@hotmail.com>, 2018. # David Couto <davidcouto@gmail.com>, 2017. # Dharkael <izhe@hotmail.es>, 2017. # Diego López <diegodario21@gmail.com>, 2017. -# Gustavo Leon <gleondiaz@gmail.com>, 2017. +# Gustavo Leon <gleondiaz@gmail.com>, 2017-2018. # Juan Quiroga <juanquiroga9@gmail.com>, 2017. # Kiji Pixel <raccoon.fella@gmail.com>, 2017. # Lisandro Lorea <lisandrolorea@gmail.com>, 2016-2017. -# Lonsfor <lotharw@protonmail.com>, 2017. -# Oscar Carballal <oscar.carballal@protonmail.com>, 2017. +# Lonsfor <lotharw@protonmail.com>, 2017-2018. +# Mario Nachbaur <manachbaur@gmail.com>, 2018. +# Oscar Carballal <oscar.carballal@protonmail.com>, 2017-2018. # Rabid Orange <theorangerabid@gmail.com>, 2017. -# Roger Blanco Ribera <roger.blancoribera@gmail.com>, 2016-2017. +# Roger Blanco Ribera <roger.blancoribera@gmail.com>, 2016-2018. # Sebastian Silva <sebastian@fuentelibre.org>, 2016. # Swyter <swyterzone@gmail.com>, 2016-2017. +# Vazquinhos <vazquinhos@gmail.com>, 2018. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2017-12-09 22:50+0000\n" -"Last-Translator: Aleix Sanchis <aleixsanchis@hotmail.com>\n" +"PO-Revision-Date: 2018-03-03 09:49+0000\n" +"Last-Translator: David Arranz <davarrcal@hotmail.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/" "godot/es/>\n" "Language: es\n" @@ -35,7 +38,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 2.18-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -46,9 +49,8 @@ msgid "All Selection" msgstr "Toda la selección" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Change Keyframe Time" -msgstr "Cambiar valor de animación" +msgstr "Cambiar el tiempo de la clave de animación" #: editor/animation_editor.cpp msgid "Anim Change Transition" @@ -59,9 +61,8 @@ msgid "Anim Change Transform" msgstr "Cambiar transformación de animación" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Change Keyframe Value" -msgstr "Cambiar valor de animación" +msgstr "Cambiar valor de la clave de animación" #: editor/animation_editor.cpp msgid "Anim Change Call" @@ -178,9 +179,8 @@ msgid "Constant" msgstr "Constante" #: editor/animation_editor.cpp -#, fuzzy msgid "In" -msgstr "In" +msgstr "Entrada" #: editor/animation_editor.cpp msgid "Out" @@ -276,7 +276,7 @@ msgstr "Paso (s):" #: editor/animation_editor.cpp msgid "Cursor step snap (in seconds)." -msgstr "Fijado de cursor por pasos (en segundos)." +msgstr "Fijado del cursor por pasos (en segundos)." #: editor/animation_editor.cpp msgid "Enable/Disable looping in animation." @@ -288,7 +288,7 @@ msgstr "Añadir Nuevas Pistas." #: editor/animation_editor.cpp msgid "Move current track up." -msgstr "Subir la pasta actual." +msgstr "Subir la pista actual." #: editor/animation_editor.cpp msgid "Move current track down." @@ -390,7 +390,7 @@ msgstr "Número de lÃnea:" #: editor/code_editor.cpp msgid "No Matches" -msgstr "Sin soincidencias" +msgstr "Sin coincidencias" #: editor/code_editor.cpp msgid "Replaced %d occurrence(s)." @@ -467,11 +467,11 @@ msgstr "Quitar" #: editor/connections_dialog.cpp msgid "Add Extra Call Argument:" -msgstr "Añadir argumento de llamada Extra:" +msgstr "Añadir argumento extra de llamada:" #: editor/connections_dialog.cpp msgid "Extra Call Arguments:" -msgstr "Argumentos de llamada extras:" +msgstr "Argumentos extras de llamada:" #: editor/connections_dialog.cpp msgid "Path to Node:" @@ -479,7 +479,7 @@ msgstr "Ruta al nodo:" #: editor/connections_dialog.cpp msgid "Make Function" -msgstr "Crear runción" +msgstr "Crear función" #: editor/connections_dialog.cpp msgid "Deferred" @@ -516,9 +516,8 @@ msgid "Connecting Signal:" msgstr "Conectando señal:" #: editor/connections_dialog.cpp -#, fuzzy msgid "Disconnect '%s' from '%s'" -msgstr "Conectar «%s» a «%s»" +msgstr "Desconectar '%s' de '%s'" #: editor/connections_dialog.cpp msgid "Connect.." @@ -534,9 +533,8 @@ msgid "Signals" msgstr "Señales" #: editor/create_dialog.cpp -#, fuzzy msgid "Change %s Type" -msgstr "Cambiar tipo" +msgstr "Cambiar el tipo de %s" #: editor/create_dialog.cpp editor/project_settings_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -544,9 +542,8 @@ msgid "Change" msgstr "Cambiar" #: editor/create_dialog.cpp -#, fuzzy msgid "Create New %s" -msgstr "Crear nuevo" +msgstr "Crear nuevo %s" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp @@ -629,7 +626,7 @@ msgstr "Editor de dependencias" #: editor/dependency_editor.cpp msgid "Search Replacement Resource:" -msgstr "Buscar reemplazo de recurso:" +msgstr "Buscar recurso de reemplazo:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help.cpp editor/editor_node.cpp editor/filesystem_dock.cpp @@ -659,9 +656,8 @@ msgstr "" "¿Seguro que quieres quitarlos? (No puedes deshacerlo)" #: editor/dependency_editor.cpp -#, fuzzy msgid "Cannot remove:" -msgstr "No se puede eliminar:\n" +msgstr "No se puede eliminar:" #: editor/dependency_editor.cpp msgid "Error loading:" @@ -737,16 +733,15 @@ msgstr "Contribuidores de Godot" #: editor/editor_about.cpp msgid "Project Founders" -msgstr "Los Fundadores del Proyecto" +msgstr "Fundadores del proyecto" #: editor/editor_about.cpp msgid "Lead Developer" msgstr "Desarrollador Principal" #: editor/editor_about.cpp -#, fuzzy msgid "Project Manager " -msgstr "Administrador de proyectos" +msgstr "Administrador de proyectos " #: editor/editor_about.cpp msgid "Developers" @@ -770,15 +765,15 @@ msgstr "Mini Patrocinadores" #: editor/editor_about.cpp msgid "Gold Donors" -msgstr "Donadores Oro" +msgstr "Donantes Oro" #: editor/editor_about.cpp msgid "Silver Donors" -msgstr "Donadores Plata" +msgstr "Donantes Plata" #: editor/editor_about.cpp msgid "Bronze Donors" -msgstr "Donadores Bronce" +msgstr "Donantes de Bronce" #: editor/editor_about.cpp msgid "Donors" @@ -818,7 +813,7 @@ msgstr "Licencias" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Error opening package file, not in zip format." -msgstr "Error al abrir el paquete, no se encuentra en formato zip." +msgstr "Error al abrir el archivo empaquetado, no tiene formato zip." #: editor/editor_asset_installer.cpp msgid "Uncompressing Assets" @@ -831,7 +826,7 @@ msgstr "¡El paquete se ha instalado correctamente!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Success!" -msgstr "Finalizado!" +msgstr "¡Finalizado!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -852,12 +847,11 @@ msgstr "Añadir Efecto" #: editor/editor_audio_buses.cpp msgid "Rename Audio Bus" -msgstr "Renombrar Audio Bus" +msgstr "Renombrar bus de audio" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Change Audio Bus Volume" -msgstr "Alternar Audio Bus Solo" +msgstr "Cambiar volumen del bus de audio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" @@ -869,11 +863,11 @@ msgstr "Alternar Mute del Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Bypass Effects" -msgstr "Alternar efectos de bypass del Bus de Audio" +msgstr "Alternar puenteado de efectos en Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Select Audio Bus Send" -msgstr "Seleccionar Bus de Audio de envÃo" +msgstr "Seleccionar envÃo a bus de audio" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus Effect" @@ -901,7 +895,7 @@ msgstr "Silenciar" #: editor/editor_audio_buses.cpp msgid "Bypass" -msgstr "Sobrepasar" +msgstr "Puentear" #: editor/editor_audio_buses.cpp msgid "Bus options" @@ -922,7 +916,7 @@ msgstr "Borrar Efecto" #: editor/editor_audio_buses.cpp msgid "Audio" -msgstr "" +msgstr "Audio" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus" @@ -930,7 +924,7 @@ msgstr "Añadir Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Master bus can't be deleted!" -msgstr "¡El Bus Maestro no puede ser borrado!" +msgstr "¡No se puede borrar el Bus Maestro!" #: editor/editor_audio_buses.cpp msgid "Delete Audio Bus" @@ -942,7 +936,7 @@ msgstr "Duplicar Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Reset Bus Volume" -msgstr "Restablecer Volumen de Bus" +msgstr "Restablecer Volumen del Bus" #: editor/editor_audio_buses.cpp msgid "Move Audio Bus" @@ -950,15 +944,15 @@ msgstr "Mover Bus de Audio" #: editor/editor_audio_buses.cpp msgid "Save Audio Bus Layout As.." -msgstr "Guardar formato de los Audio Bus como..." +msgstr "Guardar configuración de los Buses de Audio como..." #: editor/editor_audio_buses.cpp msgid "Location for New Layout.." -msgstr "Ruta al nuevo diseño.." +msgstr "Ruta para nueva configuración.." #: editor/editor_audio_buses.cpp msgid "Open Audio Bus Layout" -msgstr "Abrir diseño del Audio Bus" +msgstr "Abrir configuración de Bus de Audio" #: editor/editor_audio_buses.cpp msgid "There is no 'res://default_bus_layout.tres' file." @@ -966,7 +960,7 @@ msgstr "No existe el archivo 'res://default_bus_layout.tres'." #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." -msgstr "Archivo inválido, no es un formato de bus de audio" +msgstr "Archivo inválido, no es una configuración de bus de audio." #: editor/editor_audio_buses.cpp msgid "Add Bus" @@ -974,7 +968,7 @@ msgstr "Añadir Bus" #: editor/editor_audio_buses.cpp msgid "Create a new Bus Layout." -msgstr "Crear nuevo Formato de Bus de Audio." +msgstr "Crear nueva configuración de Bus de Audio." #: editor/editor_audio_buses.cpp editor/property_editor.cpp #: editor/script_create_dialog.cpp @@ -983,7 +977,7 @@ msgstr "Cargar" #: editor/editor_audio_buses.cpp msgid "Load an existing Bus Layout." -msgstr "Cargar un Fomato de Bus de Audio existente." +msgstr "Cargar una configuración de Bus de Audio existente." #: editor/editor_audio_buses.cpp #: editor/plugins/animation_player_editor_plugin.cpp @@ -992,15 +986,15 @@ msgstr "Guardar como" #: editor/editor_audio_buses.cpp msgid "Save this Bus Layout to a file." -msgstr "Guardar este Formato Bus como..." +msgstr "Guardar la configuración de este Bus a un archivo." #: editor/editor_audio_buses.cpp editor/import_dock.cpp msgid "Load Default" -msgstr "Cargar Predeterminado" +msgstr "Cargar Ajuste Predeterminado" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." -msgstr "Cargar Formato de Bus predeterminado." +msgstr "Cargar configuración de Bus por defecto." #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -1013,20 +1007,20 @@ msgstr "Letras válidas:" #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing engine class name." msgstr "" -"El nombre no es correcto. No puede coincidir con un nombre de clase que ya " -"existe en el motor gráfico." +"El nombre no es correcto. No puede coincidir con el nombre de una clase que " +"ya exista en el motor gráfico." #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing buit-in type name." msgstr "" -"El nombre no es correcto. No puede coincidir con un nombre de tipo " -"predeterminado que ya existe en el motor gráfico." +"El nombre no es correcto. No puede coincidir con un nombre de tipo que ya " +"esté integrado en el motor gráfico." #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing global constant name." msgstr "" "El nombre no es correcto. No puede coincidir con un nombre de constante " -"global que ya existe en el motor gráfico." +"global ya existente en el motor gráfico." #: editor/editor_autoload_settings.cpp msgid "Invalid Path." @@ -1034,7 +1028,7 @@ msgstr "Ruta incorrecta." #: editor/editor_autoload_settings.cpp msgid "File does not exist." -msgstr "El archivo existe." +msgstr "El archivo no existe." #: editor/editor_autoload_settings.cpp msgid "Not in resource path." @@ -1103,17 +1097,16 @@ msgid "Updating scene.." msgstr "Actualizando escena.." #: editor/editor_data.cpp -#, fuzzy msgid "[empty]" -msgstr "(vacÃo)" +msgstr "[vacÃo]" #: editor/editor_data.cpp msgid "[unsaved]" -msgstr "" +msgstr "[no guardado]" #: editor/editor_dir_dialog.cpp msgid "Please select a base directory first" -msgstr "Por favor seleccione primero un directorio base" +msgstr "Por favor, primero seleccione un directorio base" #: editor/editor_dir_dialog.cpp msgid "Choose a Directory" @@ -1142,16 +1135,15 @@ msgstr "Elegir" #: editor/editor_export.cpp msgid "Storing File:" -msgstr "Almacén de archivo:" +msgstr "Archivo de almacenamiento:" #: editor/editor_export.cpp msgid "Packing" msgstr "Empaquetando" #: editor/editor_export.cpp platform/javascript/export/export.cpp -#, fuzzy msgid "Template file not found:" -msgstr "No se encontró archivo plantilla:\n" +msgstr "No se encontró archivo de plantilla:" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "File Exists, Overwrite?" @@ -1170,9 +1162,8 @@ msgid "Show In File Manager" msgstr "Mostrar en el navegador de archivos" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp -#, fuzzy msgid "New Folder.." -msgstr "Crear carpeta" +msgstr "Nueva carpeta..." #: editor/editor_file_dialog.cpp msgid "Refresh" @@ -1267,11 +1258,11 @@ msgstr "Archivo:" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Must use a valid extension." -msgstr "Debe ser una extensión válida." +msgstr "Debe tener una extensión válida." #: editor/editor_file_system.cpp msgid "ScanSources" -msgstr "AnalizandoFuentes" +msgstr "Analizando fuentes" #: editor/editor_file_system.cpp msgid "(Re)Importing Assets" @@ -1363,19 +1354,18 @@ msgid "Description" msgstr "Descripción" #: editor/editor_help.cpp -#, fuzzy msgid "Online Tutorials:" -msgstr "Tutoriales" +msgstr "Tutoriales en lÃnea:" #: editor/editor_help.cpp -#, fuzzy msgid "" "There are currently no tutorials for this class, you can [color=$color][url=" "$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/" "url][/color]." msgstr "" -"Actualmente no hay una descripción para este método. Por favor, ¡ayúdanos " -"[color=$color][url=$url]aportando una[/url][/color]!" +"De momento no hay tutoriales para esta clase, puedes [color=$color][url=" +"$url]añadir uno[/url][/color] o [color=$color][url=$url2]pedir uno[color=" +"$color][url=$url2]." #: editor/editor_help.cpp msgid "Properties" @@ -1383,7 +1373,7 @@ msgstr "Propiedades" #: editor/editor_help.cpp msgid "Property Description:" -msgstr "Descripción de Propiedad:" +msgstr "Descripción de la Propiedad:" #: editor/editor_help.cpp msgid "" @@ -1429,9 +1419,8 @@ msgid "Clear" msgstr "Borrar todo" #: editor/editor_log.cpp -#, fuzzy msgid "Clear Output" -msgstr "Salida" +msgstr "Borrar salida" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Error saving resource!" @@ -1468,7 +1457,7 @@ msgstr "Error al analizar '%s'." #: editor/editor_node.cpp msgid "Unexpected end of file '%s'." -msgstr "Fin de archivo inesperado '%s'." +msgstr "Fin de archivo '%s' inesperado." #: editor/editor_node.cpp msgid "Missing '%s' or its dependencies." @@ -1495,13 +1484,12 @@ msgid "This operation can't be done without a tree root." msgstr "Esta operación no puede realizarse sin una escena raÃz." #: editor/editor_node.cpp -#, fuzzy msgid "" "Couldn't save scene. Likely dependencies (instances or inheritance) couldn't " "be satisfied." msgstr "" -"No se pudo guardar la escena. Es posible que no se hayan podido satisfacer " -"las dependencias (instancias)." +"No se pudo guardar la escena. Las dependencias (instancias o herencia) no se " +"pudieron resolver." #: editor/editor_node.cpp msgid "Failed to load resource." @@ -1574,7 +1562,7 @@ msgid "" "understand this workflow." msgstr "" "Esta escena ha sido importada, por lo tanto, los cambios no se mantendrán.\n" -"Instanciarlo o heredarlo permitirá hacerle cambios.\n" +"Instanciarla o heredarla permitirá hacerle cambios.\n" "Por favor, lee la documentación referente a la importación de escenas para " "entender mejor el flujo de trabajo." @@ -1589,12 +1577,10 @@ msgstr "" "mejor el flujo de trabajo." #: editor/editor_node.cpp -#, fuzzy msgid "Expand all properties" msgstr "Expandir todas las propiedades" #: editor/editor_node.cpp -#, fuzzy msgid "Collapse all properties" msgstr "Colapsar todo" @@ -1616,11 +1602,11 @@ msgstr "Copiar recurso" #: editor/editor_node.cpp msgid "Make Built-In" -msgstr "Hacerlo integrado" +msgstr "Convertirlo en integrado" #: editor/editor_node.cpp msgid "Make Sub-Resources Unique" -msgstr "Crear subrecurso único" +msgstr "Hacer sub-recursos únicos" #: editor/editor_node.cpp msgid "Open in Help" @@ -1647,8 +1633,8 @@ msgid "" "category." msgstr "" "La escena '%s' seleccionada no existe, ¿seleccionar una válida?\n" -"Es posible cambiarla más tarde en \"Ajustes del Proyecto\" bajo la categoria " -"'aplicacion'." +"Es posible cambiarla más tarde en \"Ajustes del Proyecto\" bajo la categorÃa " +"'aplicación'." #: editor/editor_node.cpp msgid "" @@ -1658,13 +1644,13 @@ msgid "" msgstr "" "La escena '%s' seleccionada no es un archivo de escena, ¿seleccionar uno " "válido?\n" -"Es posible cambiarla más tarde en \"Ajustes del Proyecto\" bajo la categoria " -"'aplicacion'." +"Es posible cambiarla más tarde en \"Ajustes del Proyecto\" bajo la categorÃa " +"'aplicación'." #: editor/editor_node.cpp msgid "Current scene was never saved, please save it prior to running." msgstr "" -"La escena actual nunca se guardó. Favor de guardarla antes de ejecutar." +"La escena actual nunca se guardó. Por favor, guárdela antes de ejecutar." #: editor/editor_node.cpp msgid "Could not start subprocess!" @@ -1717,7 +1703,7 @@ msgstr "Esta operación no puede realizarse sin una escena." #: editor/editor_node.cpp msgid "Export Mesh Library" -msgstr "Exportar biblioteca de modelos" +msgstr "Exportar biblioteca de mallas" #: editor/editor_node.cpp msgid "This operation can't be done without a root node." @@ -1745,7 +1731,9 @@ msgstr "Revertir" #: editor/editor_node.cpp msgid "This action cannot be undone. Revert anyway?" -msgstr "Esta acción es irreversible. ¿Quieres revertirla de todos modos?" +msgstr "" +"Esta acción no se podrá volver a realizar. ¿Quieres revertirla de todos " +"modos?" #: editor/editor_node.cpp msgid "Quick Run Scene.." @@ -1822,7 +1810,7 @@ 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 "" -"La escena '%s' fue importado automáticamente, por lo tanto no puede ser " +"La escena '%s' fue importada automáticamente, por lo tanto no puede ser " "modificada.\n" "Para poder modificarla, se tiene que crear una nueva escena heredada." @@ -1886,9 +1874,8 @@ msgid "Distraction Free Mode" msgstr "Modo sin distracciones" #: editor/editor_node.cpp -#, fuzzy msgid "Toggle distraction-free mode." -msgstr "Alternar Modo sin distracciones." +msgstr "Alternar modo sin distracciones." #: editor/editor_node.cpp msgid "Add a new scene." @@ -1952,11 +1939,11 @@ msgstr "Convertir a.." #: editor/editor_node.cpp msgid "MeshLibrary.." -msgstr "MeshLibrary.." +msgstr "LibrerÃa de mallas.." #: editor/editor_node.cpp msgid "TileSet.." -msgstr "TileSet.." +msgstr "\"TileSet\".." #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp @@ -1974,7 +1961,7 @@ msgstr "Revertir escena" #: editor/editor_node.cpp msgid "Miscellaneous project or scene-wide tools." -msgstr "Herramientas varias o de escenas." +msgstr "Herramientas variadas de proyecto o escena." #: editor/editor_node.cpp msgid "Project" @@ -1998,7 +1985,7 @@ msgstr "Herramientas" #: editor/editor_node.cpp msgid "Quit to Project List" -msgstr "Salir al listado del proyecto" +msgstr "Salir al listado de proyectos" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Debug" @@ -2013,8 +2000,8 @@ msgid "" "When exporting or deploying, the resulting executable will attempt to " "connect to the IP of this computer in order to be debugged." msgstr "" -"Al exportar o publicarlo, el ejecutable tratará de conectarse a la IP de " -"este equipo para iniciar la depuración." +"Al exportar o publicar, el ejecutable tratará de conectarse a la IP de este " +"equipo para iniciar la depuración." #: editor/editor_node.cpp msgid "Small Deploy with Network FS" @@ -2029,7 +2016,7 @@ msgid "" "On Android, deploy will use the USB cable for faster performance. This " "option speeds up testing for games with a large footprint." msgstr "" -"Cuando esta opción está activa, al exportar o publicar se producirá un " +"Cuando esta opción está activa, al exportar o publicar se creará un " "ejecutable mÃnimo.\n" "El sistema de archivos del proyecto se pasará desde el editor por la red.\n" "En Android, publicar utilizará el cable USB para un mejor rendimiento. Esta " @@ -2044,8 +2031,8 @@ msgid "" "Collision shapes and raycast nodes (for 2D and 3D) will be visible on the " "running game if this option is turned on." msgstr "" -"Los Collision shapes y nodos raycast (para 2D y 3D) seran visibiles durante " -"la ejecución del juego cuando esta opción queda activada." +"Los \"Collision Shapes\" y los nodos \"raycast\" (para 2D y 3D) serán " +"visibles durante la ejecución del juego cuando esta opción esté activada." #: editor/editor_node.cpp msgid "Visible Navigation" @@ -2056,7 +2043,7 @@ msgid "" "Navigation meshes and polygons will be visible on the running game if this " "option is turned on." msgstr "" -"Si activas esta opción podrás ver los modelos y polÃgonos de navegación " +"Si activas esta opción podrás ver las mallas y polÃgonos de navegación " "durante la ejecución del juego." #: editor/editor_node.cpp @@ -2070,7 +2057,7 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"Cuando esta opción este encendida, cualquier cambio hecho a la escena en el " +"Cuando esta opción este activada, cualquier cambio hecho a la escena en el " "editor sera replicado en el juego en ejecución.\n" "Cuando se usa remotamente en un dispositivo, esto es mas eficiente con un " "sistema de archivos remoto." @@ -2086,7 +2073,7 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"Cuando esta opción esta activa, cualquier script que se guarde sera vuelto a " +"Cuando esta opción esté activa, cualquier script que se guarde se volverá a " "cargar en el juego en ejecución.\n" "Cuando se use remotamente en un dispositivo, esto es mas eficiente con un " "sistema de archivos de red." @@ -2109,7 +2096,7 @@ msgstr "Modo Pantalla Completa" #: editor/editor_node.cpp editor/project_export.cpp msgid "Manage Export Templates" -msgstr "Cargando Plantillas de Exportación" +msgstr "Cargar Plantillas de Exportación" #: editor/editor_node.cpp msgid "Help" @@ -2136,7 +2123,7 @@ msgstr "P&R" #: editor/editor_node.cpp msgid "Issue Tracker" -msgstr "Registros de problemas" +msgstr "Registro de problemas" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp msgid "Community" @@ -2188,7 +2175,7 @@ msgstr "Reproducir escena personalizada" #: editor/editor_node.cpp msgid "Spins when the editor window repaints!" -msgstr "Gira cuando la ventana del editor repinta!" +msgstr "¡Gira cuando la ventana del editor redibuja!" #: editor/editor_node.cpp msgid "Update Always" @@ -2240,7 +2227,7 @@ msgstr "Propiedades del objeto." #: editor/editor_node.cpp msgid "Changes may be lost!" -msgstr "¡Se pueden perder los cambios!" +msgstr "¡Se perderán los cambios realizados!" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp #: editor/project_manager.cpp @@ -2325,7 +2312,7 @@ msgstr "Abrir Editor anterior" #: editor/editor_plugin.cpp msgid "Creating Mesh Previews" -msgstr "Creando vistas previas de los modelos 3D" +msgstr "Creando vistas previas de las mallas" #: editor/editor_plugin.cpp msgid "Thumbnail.." @@ -2366,7 +2353,7 @@ msgstr "Medida:" #: editor/editor_profiler.cpp msgid "Frame Time (sec)" -msgstr "Duracion de cuadro (seg)" +msgstr "Duración de cuadro (seg)" #: editor/editor_profiler.cpp msgid "Average Time (sec)" @@ -2377,9 +2364,8 @@ msgid "Frame %" msgstr "% de cuadro" #: editor/editor_profiler.cpp -#, fuzzy msgid "Physics Frame %" -msgstr "% de cuadro fijo" +msgstr "% de cuadro fÃsico" #: editor/editor_profiler.cpp editor/script_editor_debugger.cpp msgid "Time:" @@ -2398,14 +2384,12 @@ msgid "Frame #:" msgstr "Nº de cuadro:" #: editor/editor_profiler.cpp -#, fuzzy msgid "Time" -msgstr "Tiempo:" +msgstr "Tiempo" #: editor/editor_profiler.cpp -#, fuzzy msgid "Calls" -msgstr "Llamada" +msgstr "Llamadas" #: editor/editor_run_native.cpp msgid "Select device from the list" @@ -2416,7 +2400,7 @@ msgid "" "No runnable export preset found for this platform.\n" "Please add a runnable preset in the export menu." msgstr "" -"No se ha encontrado ningún preset ejecutable de exportación para esta " +"No se ha encontrado ningún preset de exportación ejecutable para esta " "plataforma.\n" "Por favor, añade un preset ejecutable en el menú de exportación." @@ -2490,7 +2474,7 @@ msgstr "Obteniendo mirrors, por favor espere..." #: editor/export_template_manager.cpp msgid "Remove template version '%s'?" -msgstr "Eliminar diseño de versión '%s'?" +msgstr "¿Eliminar plantilla versión '%s'?" #: editor/export_template_manager.cpp msgid "Can't open export templates zip." @@ -2498,24 +2482,15 @@ msgstr "No se puede abir el zip de plantillas de exportación." #: editor/export_template_manager.cpp msgid "Invalid version.txt format inside templates." -msgstr "version.txt invalido en el diseño." - -#: editor/export_template_manager.cpp -#, fuzzy -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Formato de version.txt inválido. Revision no es un identificador válido." +msgstr "Formato de \"version.txt\" inválido dentro de las plantillas." #: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "No se ha encontrado el archivo version.txt dentro de las plantillas." #: editor/export_template_manager.cpp -#, fuzzy msgid "Error creating path for templates:" -msgstr "Error al crear ruta para las plantillas:\n" +msgstr "Error al crear ruta para las plantillas:" #: editor/export_template_manager.cpp msgid "Extracting Export Templates" @@ -2550,9 +2525,8 @@ msgstr "No responde." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Request Failed." -msgstr "Solicitud fallida." +msgstr "Petición fallida." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -2565,10 +2539,6 @@ msgid "Failed:" msgstr "Fallido:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "No se puede escribir el archivo." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Descarga completada." @@ -2577,9 +2547,8 @@ msgid "Error requesting url: " msgstr "Error al solicitar url: " #: editor/export_template_manager.cpp -#, fuzzy msgid "Connecting to Mirror.." -msgstr "Conectando.." +msgstr "Intentando conexión alternativa.." #: editor/export_template_manager.cpp msgid "Disconnected" @@ -2599,7 +2568,6 @@ msgid "Connecting.." msgstr "Conectando.." #: editor/export_template_manager.cpp -#, fuzzy msgid "Can't Connect" msgstr "No se puede conectar" @@ -2642,10 +2610,9 @@ msgstr "Eliminar plantilla" #: editor/export_template_manager.cpp msgid "Select template file" -msgstr "Seleccionar archivo de plantilla" +msgstr "Seleccionar archivo plantilla" #: editor/export_template_manager.cpp -#, fuzzy msgid "Export Template Manager" msgstr "Gestor de plantillas de exportación" @@ -2678,45 +2645,38 @@ msgid "View items as a list" msgstr "Ver elementos como una lista" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" -"\n" -"Estado: No se pudo importar el archivo. Por favor, arregla el archivo e " -"impórtalo manualmente." +"Estado: No se pudo importar el archivo. Por favor, arregla el archivo y " +"reimpórtalo manualmente." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Cannot move/rename resources root." -msgstr "No se puede mover/renombrar la raÃz de recursos." +msgstr "No se puede mover/renombrar la raÃz de los recursos." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Cannot move a folder into itself." -msgstr "No se puede importar una carpeta sobre si misma.\n" +msgstr "No se puede mover una carpeta a dentro de sà misma." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Error moving:" -msgstr "Error al mover:\n" +msgstr "Error al mover:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Error duplicating:" -msgstr "Error al cargar:" +msgstr "Error al duplicar:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Unable to update dependencies:" -msgstr "No se ha podido actualizar las dependencias:\n" +msgstr "No se han podido actualizar las dependencias:" #: editor/filesystem_dock.cpp msgid "No name provided" -msgstr "No se proveyó un nombre" +msgstr "No se proporcionó un nombre" #: editor/filesystem_dock.cpp msgid "Provided name contains invalid characters" -msgstr "El nombre obtenido contiene caracteres inválidos" +msgstr "El nombre proporcionado contiene caracteres inválidos" #: editor/filesystem_dock.cpp msgid "No name provided." @@ -2739,14 +2699,12 @@ msgid "Renaming folder:" msgstr "Renombrar carpeta:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicating file:" -msgstr "Duplicar" +msgstr "Duplicando archivo:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicating folder:" -msgstr "Renombrar carpeta:" +msgstr "Duplicando carpeta:" #: editor/filesystem_dock.cpp msgid "Expand all" @@ -2765,9 +2723,8 @@ msgid "Move To.." msgstr "Mover a.." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Open Scene(s)" -msgstr "Abrir escena" +msgstr "Abrir escena/s" #: editor/filesystem_dock.cpp msgid "Instance" @@ -2778,14 +2735,12 @@ msgid "Edit Dependencies.." msgstr "Editar dependencias.." #: editor/filesystem_dock.cpp -#, fuzzy msgid "View Owners.." msgstr "Ver propietarios.." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicate.." -msgstr "Duplicar" +msgstr "Duplicar.." #: editor/filesystem_dock.cpp msgid "Previous Directory" @@ -2834,14 +2789,12 @@ msgid "Remove from Group" msgstr "Quitar del grupo" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Import as Single Scene" -msgstr "Importando escena…" +msgstr "Importar como escena individual" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Import with Separate Animations" -msgstr "Importar con materiales separados" +msgstr "Importar con animaciones separadas" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials" @@ -2852,29 +2805,24 @@ msgid "Import with Separate Objects" msgstr "Importar con objetos separados" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Import with Separate Objects+Materials" msgstr "Importar con objetos y materiales separados" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Import with Separate Objects+Animations" -msgstr "Importar con objetos y materiales separados" +msgstr "Importar con objetos y animaciones separados" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Import with Separate Materials+Animations" -msgstr "Importar con materiales separados" +msgstr "Importar con materiales y animaciones separados" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Import with Separate Objects+Materials+Animations" -msgstr "Importar con objetos y materiales separados" +msgstr "Importar con objetos, materiales y animaciones separados" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Import as Multiple Scenes" -msgstr "Importar escena 3D" +msgstr "Importar como múltiples escenas" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes+Materials" @@ -2890,14 +2838,12 @@ msgid "Importing Scene.." msgstr "Importando escena.." #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Generating Lightmaps" -msgstr "Transfiriendo a «lightmaps»:" +msgstr "Generando \"Lightmaps\"" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Generating for Mesh: " -msgstr "Generar AABB" +msgstr "Generando para modelo: " #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script.." @@ -2929,21 +2875,18 @@ msgid "Clear Default for '%s'" msgstr "Borrar por defecto para '%s'" #: editor/import_dock.cpp -#, fuzzy msgid " Files" -msgstr "Archivo" +msgstr " Archivos" #: editor/import_dock.cpp -#, fuzzy msgid "Import As:" -msgstr "Importar" +msgstr "Importar como:" #: editor/import_dock.cpp editor/property_editor.cpp msgid "Preset.." msgstr "Ajuste.." #: editor/import_dock.cpp -#, fuzzy msgid "Reimport" msgstr "Reimportar" @@ -2971,9 +2914,8 @@ msgid "Edit Poly" msgstr "Editar polÃgono" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy msgid "Insert Point" -msgstr "Insertando" +msgstr "Insertar punto" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/collision_polygon_editor_plugin.cpp @@ -2986,9 +2928,8 @@ msgid "Remove Poly And Point" msgstr "Quitar polÃgono y punto" #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy msgid "Create a new polygon from scratch" -msgstr "Crea un nuevo polÃgono desde cero." +msgstr "Crear un nuevo polÃgono desde cero" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "" @@ -3003,9 +2944,8 @@ msgstr "" "Click derecho: Borrar punto." #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy msgid "Delete points" -msgstr "Eliminar punto" +msgstr "Eliminar puntos" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Toggle Autoplay" @@ -3024,9 +2964,8 @@ msgid "Change Animation Name:" msgstr "Cambiar nombre de animación:" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Delete Animation?" -msgstr "Duplicar animación" +msgstr "¿Eliminar animación?" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp @@ -3107,7 +3046,7 @@ msgstr "Reproducir animación seleccionada desde el principio. (Mayús + D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from current pos. (D)" -msgstr "Reproducir animación seleccionada desde la posicion actual. (D)" +msgstr "Reproducir animación seleccionada desde la posición actual. (D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation position (in seconds)." @@ -3115,7 +3054,7 @@ msgstr "Posición de animación (en segundos)." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Scale animation playback globally for the node." -msgstr "Escalar la reproducción de la animación globalmente para el nodo." +msgstr "Escalar globalmente la reproducción de la animación para el nodo." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Create new animation in player." @@ -3135,7 +3074,7 @@ msgstr "Guardar la animación actual" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Display list of animations in player." -msgstr "Lista de animaciones en el reproductor." +msgstr "Mostrar la lista de animaciones en el reproductor." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Autoplay on Load" @@ -3143,7 +3082,7 @@ msgstr "Autoreproducir al cargar" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Edit Target Blend Times" -msgstr "Editar Blend Times Objetivo" +msgstr "Editar tiempos de mezcla de selección" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Tools" @@ -3162,36 +3101,30 @@ msgid "Enable Onion Skinning" msgstr "Activar Papel Cebolla" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Directions" -msgstr "Selecciones:" +msgstr "Direcciones" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Past" -msgstr "Pegar" +msgstr "Anterior" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Future" -msgstr "Textura" +msgstr "Posterior" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Depth" msgstr "Profundidad" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "1 step" msgstr "1 paso" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "2 steps" msgstr "2 pasos" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "3 steps" msgstr "3 pasos" @@ -3201,7 +3134,7 @@ msgstr "Solo las Diferencias" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Force White Modulate" -msgstr "" +msgstr "Forzar modulación hacia el blanco" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Include Gizmos (3D)" @@ -3244,9 +3177,8 @@ msgid "New name:" msgstr "Nuevo nombre:" #: editor/plugins/animation_tree_editor_plugin.cpp -#, fuzzy msgid "Edit Filters" -msgstr "Editar filtros de nodo" +msgstr "Editar filtros" #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/multimesh_editor_plugin.cpp @@ -3255,15 +3187,15 @@ msgstr "Escala:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Fade In (s):" -msgstr "Aparición (s):" +msgstr "Fundido de entrada (s):" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Fade Out (s):" -msgstr "Desaparición (s):" +msgstr "Fundido de salida (s):" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend" -msgstr "Mezclar" +msgstr "Mezcla" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Mix" @@ -3292,15 +3224,15 @@ msgstr "Cantidad:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend:" -msgstr "Blend:" +msgstr "Mezcla:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend 0:" -msgstr "Blend 0:" +msgstr "Mezcla 0:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend 1:" -msgstr "Blend 1:" +msgstr "Mezcla 1:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "X-Fade Time (s):" @@ -3360,7 +3292,7 @@ msgstr "Nodo Blend4" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "TimeScale Node" -msgstr "Nodo TimeScale" +msgstr "Nodo TimeScale (Escala de tiempo)" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "TimeSeek Node" @@ -3383,9 +3315,8 @@ msgid "Filters.." msgstr "Filtros.." #: editor/plugins/animation_tree_editor_plugin.cpp -#, fuzzy msgid "AnimationTree" -msgstr "Animación" +msgstr "Ãrbol de animación" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Free" @@ -3405,10 +3336,9 @@ msgstr "No se ha podido resolver el nombre de Dominio:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Connection error, please try again." -msgstr "Error de conexion, por favor intente otra vez." +msgstr "Error de conexión, por favor inténtelo otra vez." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Can't connect to host:" msgstr "No se puede conectar al host:" @@ -3417,18 +3347,16 @@ msgid "No response from host:" msgstr "No hay respuesta desde el host:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Request failed, return code:" -msgstr "Petición falida, código de retorno:" +msgstr "Petición fallida, código:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Request failed, too many redirects" msgstr "Petición fallida, demasiadas redirecciones" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Bad download hash, assuming file has been tampered with." -msgstr "Error de descarga, al pareser el archivo ha sido manipulado." +msgstr "Error de descarga, al parecer el archivo ha sido manipulado." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Expected:" @@ -3464,7 +3392,7 @@ msgstr "Inactivo" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Retry" -msgstr "Reintente" +msgstr "Reintentar" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download Error" @@ -3472,7 +3400,7 @@ msgstr "Error de Descarga" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download for this asset is already in progress!" -msgstr "Este asset ya esta descargandose!" +msgstr "¡Éste asset ya está descargándose!" #: editor/plugins/asset_library_editor_plugin.cpp msgid "first" @@ -3488,7 +3416,7 @@ msgstr "siguiente" #: editor/plugins/asset_library_editor_plugin.cpp msgid "last" -msgstr "ultimo" +msgstr "último" #: editor/plugins/asset_library_editor_plugin.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp @@ -3539,21 +3467,27 @@ msgid "" "Save your scene (for images to be saved in the same dir), or pick a save " "path from the BakedLightmap properties." msgstr "" +"No se puede encontrar una ruta válida para las imágenes \"lightmap\".\n" +"Guarda la escena (para que las imágenes se guarden en el mismo directorio), " +"o selecciona otra ruta desde las propiedades del \"BackedLightmap\"." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" "No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake " "Light' flag is on." msgstr "" +"No hay mallas que pre-calcular. Asegúrese de que contienen el canal UV2 y el " +"flag 'Bake Light' esté activo." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Failed creating lightmap images, make sure path is writable." msgstr "" +"Error al crear las imágenes del \"lighmap\", asegúrate de que se puede " +"escribir en la ruta." #: editor/plugins/baked_lightmap_editor_plugin.cpp -#, fuzzy msgid "Bake Lightmaps" -msgstr "Transfiriendo a «lightmaps»:" +msgstr "Calculando «lightmaps»" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -3562,7 +3496,7 @@ msgstr "Vista previa" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap" -msgstr "Ajustes de fijado" +msgstr "Configurar ajuste" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -3595,29 +3529,24 @@ msgid "Move vertical guide" msgstr "Mover GuÃa Vertical" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Create new vertical guide" -msgstr "Crear script" +msgstr "Crear nueva guÃa vertical" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Remove vertical guide" -msgstr "Quitar variable" +msgstr "Quitar guÃa vertical" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move horizontal guide" -msgstr "Mover Punto en Curva" +msgstr "Mover guÃa horizontal" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Create new horizontal guide" -msgstr "Crear script" +msgstr "Crear nueva guÃa horizontal" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Remove horizontal guide" -msgstr "Quitar claves incorrectas" +msgstr "Quitar guÃa horizontal" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create new horizontal and vertical guides" @@ -3632,14 +3561,12 @@ msgid "Edit CanvasItem" msgstr "Editar CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Anchors only" -msgstr "Ancla" +msgstr "Sólo anclado" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Change Anchors and Margins" -msgstr "Cambiar anclas" +msgstr "Cambiar anclas y márgenes" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors" @@ -3659,17 +3586,17 @@ msgstr "Arrastrar: Rotar" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+Drag: Move" -msgstr "Alt+Arrastrae: Mover" +msgstr "Alt+Arrastrar: Mover" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)." msgstr "" -"Presioná 'v' para Cambiar el Pivote, 'Shift+v' para Arrastrar el Pivote (al " +"Presiona 'v' para Cambiar el Pivote, 'Shift+v' para Arrastrar el Pivote (al " "mover)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+RMB: Depth list selection" -msgstr "Alt+Click Der.: Selección en depth list" +msgstr "Alt+Click Der.: Selección en listado de solapamientos" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move Mode" @@ -3685,7 +3612,7 @@ msgid "" "Show a list of all objects at the position clicked\n" "(same as Alt+RMB in select mode)." msgstr "" -"Mostrar una lista de todos los objetos en la posicion cliqueada\n" +"Mostrar una lista de todos los objetos en la posición cliqueada\n" "(igual que Alt+Click Der. en modo selección)." #: editor/plugins/canvas_item_editor_plugin.cpp @@ -3697,32 +3624,28 @@ msgid "Pan Mode" msgstr "Modo desplazamiento lateral" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Toggles snapping" -msgstr "Des/activar «breakpoint»" +msgstr "Activar/desactivar fijado" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Snap" -msgstr "Fijar a cuadrÃcula" +msgstr "Usar fijado" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Snapping options" -msgstr "Opciones de Animación" +msgstr "Opciones de fijado" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Snap to grid" -msgstr "Modo de fijado:" +msgstr "Ajustar a cuadrÃcula" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Rotation Snap" -msgstr "Fijar rotación" +msgstr "Ajustar rotación" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Configure Snap..." -msgstr "Configurar fijado.." +msgstr "Configurar CuadrÃcula..." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap Relative" @@ -3730,37 +3653,31 @@ msgstr "Fijado relativo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Pixel Snap" -msgstr "Adherir a pÃxeles" +msgstr "Ajustar a pÃxeles" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Smart snapping" -msgstr "Ajuste Inteligente" +msgstr "Fijado inteligente" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Snap to parent" -msgstr "Expandir al padre" +msgstr "Ajustar al padre" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Snap to node anchor" -msgstr "Ajustar al Nodo Ancla" +msgstr "Ajustar al anclado del nodo" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Snap to node sides" -msgstr "Ajustar a Lados del Nodo" +msgstr "Ajustar a los lados de los nodos" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Snap to other nodes" -msgstr "Ajustar a Otros Nodos" +msgstr "Ajustar a otros nodos" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Snap to guides" -msgstr "Modo de fijado:" +msgstr "Ajustar a guÃas" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -3770,7 +3687,7 @@ msgstr "Inmovilizar el objeto." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Unlock the selected object (can be moved)." -msgstr "Liberar el objeto." +msgstr "Liberar objeto inmovilizado." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Makes sure the object's children are not selectable." @@ -3789,9 +3706,8 @@ msgid "Clear Bones" msgstr "Reestablecer huesos" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Show Bones" -msgstr "Crear huesos" +msgstr "Mostrar huesos" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" @@ -3812,19 +3728,16 @@ msgid "Show Grid" msgstr "Mostrar rejilla" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy -msgid "Show helpers" -msgstr "Crear huesos" +msgid "Show Helpers" +msgstr "Mostrar ayudas" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy -msgid "Show rulers" -msgstr "Crear huesos" +msgid "Show Rulers" +msgstr "Mostrar reglas" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy -msgid "Show guides" -msgstr "Crear huesos" +msgid "Show Guides" +msgstr "Mostrar guÃas" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Selection" @@ -3835,9 +3748,8 @@ msgid "Frame Selection" msgstr "Encuadrar selección" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Layout" -msgstr "Guardar ajustes" +msgstr "Disposición" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Keys" @@ -3864,27 +3776,22 @@ msgid "Drag pivot from mouse position" msgstr "Arrastrar pivote desde la posición del ratón" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Set pivot at mouse position" -msgstr "Establecer pos. de salida de curva" +msgstr "Establecer punto de pivotado en la posición del ratón" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Multiply grid step by 2" -msgstr "Multiplicar paso de cuadÅ•icula por 2" +msgstr "Multiplicar paso de cuadrÃcula por 2" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Divide grid step by 2" msgstr "Dividir paso de cuadrÃcula por 2" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Add %s" -msgstr "Añadir todos" +msgstr "Añadir %s" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Adding %s..." msgstr "Añadiendo %s..." @@ -3894,7 +3801,7 @@ msgstr "Aceptar" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Cannot instantiate multiple nodes without root." -msgstr "" +msgstr "No se pueden instanciar varios nodos sin un nodo raÃz." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp @@ -3907,18 +3814,16 @@ msgid "Error instancing scene from %s" msgstr "Error al instanciar escena desde %s" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Change default type" -msgstr "Cambiar Valor por Defecto" +msgstr "Cambiar tipo por defecto" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "" "Drag & drop + Shift : Add node as sibling\n" "Drag & drop + Alt : Change node type" msgstr "" -"Arrastrar y soltar + Mayús: Añadir nodo como hermano\n" -"Arrastrar y soltar + Alt: Cambiar tipo de nodo" +"Arrastrar y soltar + Shift : Añadir nodo como hermano\n" +"Arrastrar y soltar + Alt : Cambiar tipo de nodo" #: editor/plugins/collision_polygon_editor_plugin.cpp msgid "Create Poly3D" @@ -3952,88 +3857,75 @@ msgstr "Actualizar desde escena" #: editor/plugins/curve_editor_plugin.cpp msgid "Flat0" -msgstr "Flat0" +msgstr "Plana0" #: editor/plugins/curve_editor_plugin.cpp msgid "Flat1" -msgstr "Flat1" +msgstr "Plana1" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Ease in" -msgstr "Transición entrada" +msgstr "Transición de entrada" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Ease out" -msgstr "Transición salida" +msgstr "Transición de salida" #: editor/plugins/curve_editor_plugin.cpp msgid "Smoothstep" -msgstr "" +msgstr "Paso suavizado" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Modify Curve Point" -msgstr "Modificar Mapa de Curvas" +msgstr "Modificar punto de la curva" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Modify Curve Tangent" -msgstr "Modificar Mapa de Curvas" +msgstr "Modificar tangente de la curva" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Load Curve Preset" -msgstr "Cargar recurso" +msgstr "Cargar ajuste predeterminado de curva" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Add point" -msgstr "Añadir entrada" +msgstr "Añadir punto" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Remove point" -msgstr "Quitar Punto de ruta" +msgstr "Quitar punto" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Left linear" -msgstr "Lineal" +msgstr "Izquierda lineal" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Right linear" -msgstr "Vista derecha" +msgstr "Derecha lineal" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Load preset" -msgstr "Cargar recurso" +msgstr "Cargar ajuste predeterminado" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Remove Curve Point" -msgstr "Quitar Punto de ruta" +msgstr "Quitar punto de la curva" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Toggle Curve Linear Tangent" -msgstr "Cambiar tangente de curva lineal" +msgstr "Alternar curva de tangente lineal" #: editor/plugins/curve_editor_plugin.cpp msgid "Hold Shift to edit tangents individually" -msgstr "Mantén Mayus para editar las tangentes individualmente" +msgstr "Mantén Mayús para editar las tangentes individualmente" #: editor/plugins/gi_probe_editor_plugin.cpp msgid "Bake GI Probe" -msgstr "" +msgstr "Precalcular GI Probe" #: editor/plugins/gradient_editor_plugin.cpp -#, fuzzy msgid "Add/Remove Color Ramp Point" -msgstr "Añadir/quitar punto de rampa de color" +msgstr "Añadir/quitar punto en la rampa del degradado" #: editor/plugins/gradient_editor_plugin.cpp #: editor/plugins/shader_graph_editor_plugin.cpp @@ -4086,15 +3978,15 @@ msgstr "Clic derecho: Borrar punto." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh is empty!" -msgstr "¡El modelo está vacÃo!" +msgstr "¡La malla está vacÃa!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Static Trimesh Body" -msgstr "Crear colisión estática triangular" +msgstr "Crear cuerpo estático \"Trimesh\"" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Static Convex Body" -msgstr "Crear colisión estática convexa" +msgstr "Crear cuerpo estático convexo" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "This doesn't work on scene root!" @@ -4110,31 +4002,33 @@ msgstr "Crear forma convexa" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Navigation Mesh" -msgstr "Crear modelo de navegación 3D" +msgstr "Crear malla de navegación" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Contained Mesh is not of type ArrayMesh." -msgstr "" +msgstr "La malla que contiene no es del tipo ArrayMesh." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "UV Unwrap failed, mesh may not be manifold?" msgstr "" +"Falló el procedimiento de Unwrapping, ¿Tal vez la malla contenga geometrÃa " +"múltiple o desajustada?" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "No mesh to debug." -msgstr "" +msgstr "No hay malla que depurar." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Model has no UV in this layer" -msgstr "" +msgstr "El modelo no tiene UV en esta capa" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "MeshInstance lacks a Mesh!" -msgstr "¡A MeshInstance le falta un modelo 3D!" +msgstr "¡MeshInstance no tiene malla!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh has not surface to create outlines from!" -msgstr "¡El modelo 3D no tiene una superficie en la que crear contornos!" +msgstr "¡La malla no tiene superficie de la que crear contornos!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Could not create outline!" @@ -4146,15 +4040,15 @@ msgstr "Crear contorno" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "Modelos 3D" +msgstr "Malla" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" -msgstr "Crear colisión estática triangular" +msgstr "Crear cuerpo estático triangular" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Convex Static Body" -msgstr "Crear colisión estática convexa" +msgstr "Crear cuerpo estático convexo" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Collision Sibling" @@ -4166,25 +4060,23 @@ msgstr "Crear colisión hermanada convexa" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh.." -msgstr "Crear modelo 3D de contorno.." +msgstr "Crear contorno de malla.." #: editor/plugins/mesh_instance_editor_plugin.cpp -#, fuzzy msgid "View UV1" -msgstr "Ver" +msgstr "Ver UV1" #: editor/plugins/mesh_instance_editor_plugin.cpp -#, fuzzy msgid "View UV2" -msgstr "Ver" +msgstr "Ver UV2" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Unwrap UV2 for Lightmap/AO" -msgstr "" +msgstr "Desenvuelva UV2 para Lightmap/AO" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh" -msgstr "Crear modelo 3D de contorno" +msgstr "Crear contorno de malla" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Outline Size:" @@ -4193,42 +4085,40 @@ msgstr "Tamaño del contorno:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and no MultiMesh set in node)." msgstr "" -"No se especificó ningún modelo 3D de origen (y no se ha establecido ningún " -"MultiMesh en el nodo)." +"No se especificó malla de origen (y no hay MultiMesh establecido en el nodo)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and MultiMesh contains no Mesh)." msgstr "" -"No se especificó ningún modelo de origen (y MultiMesh no contiene ningún " -"Mesh)." +"No se especificó malla de origen (y MultiMesh no contiene ningún Mesh)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (invalid path)." -msgstr "El origen del modelo es incorrecto (ruta incorrecta)." +msgstr "El origen de la malla es inválido (ruta inválida)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (not a MeshInstance)." -msgstr "El modelo elegido no es correcto (al no ser un MeshInstance)." +msgstr "La malla elegida no es correcta (no es un MeshInstance)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (contains no Mesh resource)." -msgstr "El modelo elegido no es correcto (no contiene ningún recurso Mesh)." +msgstr "La malla elegida no es correcta (no contiene ningún recurso Mesh)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "No surface source specified." -msgstr "Ninguna superficie de origen especificada." +msgstr "Ningún origen para la superficie especificado." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Surface source is invalid (invalid path)." -msgstr "La superficie de origen es incorrecta (ruta inválida)." +msgstr "El origen de la superficie es incorrecto (ruta inválida)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Surface source is invalid (no geometry)." -msgstr "La superficie de origen es inválida (sin geometrÃa)." +msgstr "El origen de la superficie no es correcto (sin geometrÃa)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Surface source is invalid (no faces)." -msgstr "La superficie de origen es inválida (sin caras)." +msgstr "El origen de la superficie no es correcto (sin caras)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Parent has no solid faces to populate." @@ -4236,15 +4126,15 @@ msgstr "La superficie padre no tiene caras solidas para poblar." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Couldn't map area." -msgstr "No se pudo mapear el area." +msgstr "No se pudo mapear el área." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Select a Source Mesh:" -msgstr "Elige un modelo 3D:" +msgstr "Elige un origen de malla:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Select a Target Surface:" -msgstr "Seleccioná una Superficie Objetivo:" +msgstr "Selecciona una Superficie Objetivo:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Populate Surface" @@ -4276,7 +4166,7 @@ msgstr "Eje Z" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh Up Axis:" -msgstr "Eje vertical del modelo:" +msgstr "Eje vertical de la malla:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Random Rotation:" @@ -4296,76 +4186,63 @@ msgstr "Rellenar" #: editor/plugins/navigation_mesh_editor_plugin.cpp msgid "Bake!" -msgstr "¡Quemar!" +msgstr "¡Calcular!" #: editor/plugins/navigation_mesh_editor_plugin.cpp -#, fuzzy msgid "Bake the navigation mesh." -msgstr "Crear modelo de navegación 3D" +msgstr "Pre-calcular la malla de navegación 3D." #: editor/plugins/navigation_mesh_editor_plugin.cpp -#, fuzzy msgid "Clear the navigation mesh." -msgstr "Crear modelo de navegación 3D" +msgstr "Vaciar malla de navegación 3D." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Setting up Configuration..." msgstr "Estableciendo la Configuración..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Calculating grid size..." msgstr "Calculando tamaño de cuadrÃcula..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Creating heightfield..." -msgstr "Creando octree de luces" +msgstr "Creando octree de luces (\"heigfield\")..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Marking walkable triangles..." -msgstr "Cadenas traducibles…" +msgstr "Marcando triángulos transitables..." #: editor/plugins/navigation_mesh_generator.cpp msgid "Constructing compact heightfield..." -msgstr "" +msgstr "Construyendo heightfield compacto..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Eroding walkable area..." -msgstr "Erosión del área transitable..." +msgstr "Erosionando área transitable..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Partitioning..." -msgstr "Advertencia" +msgstr "Particionando..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Creating contours..." -msgstr "Creando octree de texturas" +msgstr "Creando contornos..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Creating polymesh..." -msgstr "Crear modelo 3D de contorno.." +msgstr "Crear malla 3D de contorno (\"polymesh\")..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Converting to native navigation mesh..." -msgstr "Crear modelo de navegación 3D" +msgstr "Convirtiendo a malla de navegación nativa..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Navigation Mesh Generator Setup:" -msgstr "Configuración del Generador de Malla de Navegación:" +msgstr "Configuración del Generador de Mallas de Navegación:" #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Parsing Geometry..." -msgstr "Leyendo geometrÃa" +msgstr "Analizando geometrÃa..." #: editor/plugins/navigation_mesh_generator.cpp msgid "Done!" @@ -4377,25 +4254,21 @@ msgstr "Crear polÃgono de navegación" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Generating AABB" -msgstr "Generar AABB" +msgstr "Generando AABB" #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "Can only set point into a ParticlesMaterial process material" msgstr "" -"Solo se puede asignar el punto a un material procesado del tipo " -"ParticlesMaterial." +"Solo se puede asignar un punto a un material de procesado ParticlesMaterial" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Error loading image:" msgstr "Error al cargar la imagen:" #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "No pixels with transparency > 128 in image.." -msgstr "No hay pÃxeles con una transparencia mayor que 128 en la imagen.." +msgstr "No hay pÃxeles con transparencia > 128 en la imagen.." #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Generate Visibility Rect" @@ -4411,9 +4284,8 @@ msgstr "Borrar máscara de emisión" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Particles" -msgstr "Vértice" +msgstr "PartÃculas" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Generated Point Count:" @@ -4421,24 +4293,20 @@ msgstr "Conteo de puntos generados:" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Generation Time (sec):" -msgstr "Tiempo promedio (seg)" +msgstr "Tiempo de generación (seg):" #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "Emission Mask" -msgstr "Establecer máscara de emisión" +msgstr "Máscara de emisión" #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "Capture from Pixel" -msgstr "Crear desde escena" +msgstr "Capturar desde pÃxel" #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "Emission Colors" -msgstr "Posiciones de emisión:" +msgstr "Colores de emisión" #: editor/plugins/particles_editor_plugin.cpp msgid "Node does not contain geometry." @@ -4465,65 +4333,55 @@ msgid "Generate AABB" msgstr "Generar AABB" #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Create Emission Points From Mesh" -msgstr "Crear emisor a partir de modelo" +msgstr "Crear puntos de emisión desde malla" #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Create Emission Points From Node" -msgstr "Crear emisor a partir de nodo" +msgstr "Crear puntos de emisión desde el nodo" #: editor/plugins/particles_editor_plugin.cpp msgid "Create Emitter" msgstr "Crear emisor" #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Emission Points:" -msgstr "Posiciones de emisión:" +msgstr "Puntos de emisión:" #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Surface Points" -msgstr "Superficie %d" +msgstr "Puntos de la superficie" #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Surface Points+Normal (Directed)" -msgstr "Puntos de superficio + Normal (Dirigida)" +msgstr "Puntos de la superficie + Normal (Dirigida)" #: editor/plugins/particles_editor_plugin.cpp msgid "Volume" msgstr "Volumen" #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Emission Source: " -msgstr "Relleno de emisión:" +msgstr "Fuente de emisión: " #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Generate Visibility AABB" -msgstr "Generar AABB" +msgstr "Generar AABB de visibilidad" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove Point from Curve" -msgstr "Borrar punto de curva" +msgstr "Borrar punto de la curva" #: editor/plugins/path_2d_editor_plugin.cpp -#, fuzzy msgid "Remove Out-Control from Curve" -msgstr "Mover Out-Control en Curva" +msgstr "Eliminar \"Out-Control\" de la Curva" #: editor/plugins/path_2d_editor_plugin.cpp -#, fuzzy msgid "Remove In-Control from Curve" -msgstr "Borrar punto de curva" +msgstr "Eliminar \"In-Control\" de la curva" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp -#, fuzzy msgid "Add Point to Curve" msgstr "Añadir punto a curva" @@ -4551,9 +4409,8 @@ msgstr "Mayús + arrastrar: Seleccionar puntos de control" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp -#, fuzzy msgid "Click: Add Point" -msgstr "Clic: Añadir punto" +msgstr "Click: Añadir punto" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp @@ -4586,22 +4443,19 @@ msgstr "Cerrar curva" #: editor/plugins/path_editor_plugin.cpp msgid "Curve Point #" -msgstr "Nº de punto en curva" +msgstr "Punto de curva #" #: editor/plugins/path_editor_plugin.cpp -#, fuzzy msgid "Set Curve Point Position" -msgstr "Establecer pos. de punto de curva" +msgstr "Establecer posición de punto de curva" #: editor/plugins/path_editor_plugin.cpp -#, fuzzy msgid "Set Curve In Position" -msgstr "Establecer pos. de entrada de curva" +msgstr "Establecer posición de entrada de curva" #: editor/plugins/path_editor_plugin.cpp -#, fuzzy msgid "Set Curve Out Position" -msgstr "Establecer pos. de salida de curva" +msgstr "Establecer posición de salida de curva" #: editor/plugins/path_editor_plugin.cpp msgid "Split Path" @@ -4609,17 +4463,15 @@ msgstr "Dividir ruta" #: editor/plugins/path_editor_plugin.cpp msgid "Remove Path Point" -msgstr "Quitar Punto de ruta" +msgstr "Quitar punto de ruta" #: editor/plugins/path_editor_plugin.cpp -#, fuzzy msgid "Remove Out-Control Point" -msgstr "Mover Out-Control en Curva" +msgstr "Eliminar punto \"Out-Control\"" #: editor/plugins/path_editor_plugin.cpp -#, fuzzy msgid "Remove In-Control Point" -msgstr "Mover In-Control en Curva" +msgstr "Eliminar punto \"In-Control\"" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create UV Map" @@ -4684,11 +4536,11 @@ msgstr "Limpiar UV" #: editor/plugins/polygon_2d_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap" -msgstr "Adherir a cuadrÃcula" +msgstr "Ajustar a cuadrÃcula" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Enable Snap" -msgstr "Adherir a cuadrÃcula" +msgstr "Habilitar fijado" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid" @@ -4716,6 +4568,22 @@ msgid "Resource clipboard is empty!" msgstr "¡El portapapeles de recursos está vacÃo!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Abrir en el editor" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Instancia:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Tipo:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Cargar recurso" @@ -4728,21 +4596,16 @@ msgid "Paste" msgstr "Pegar" #: editor/plugins/resource_preloader_editor_plugin.cpp -#, fuzzy msgid "ResourcePreloader" -msgstr "Ruta de recursos" +msgstr "Pre-cargador de Recursos (ResourcePreloader)" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Clear Recent Files" -msgstr "Reestablecer huesos" +msgstr "Limpiar lista archivos recientes" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Close and save changes?" -msgstr "" -"¿Cerrar y guardar cambios?\n" -"\"" +msgstr "¿Cerrar y guardar cambios?" #: editor/plugins/script_editor_plugin.cpp msgid "Error while saving theme" @@ -4773,9 +4636,8 @@ msgid " Class Reference" msgstr " Referencia de clase" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Sort" -msgstr "Ordenar:" +msgstr "Ordenar" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp @@ -4814,14 +4676,12 @@ msgid "Soft Reload Script" msgstr "Recargar parcialmente el script" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Copy Script Path" -msgstr "Copiar ruta" +msgstr "Copiar ruta del script" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Show In File System" -msgstr "SistDeArchivos" +msgstr "Mostrar en sistema de archivos" #: editor/plugins/script_editor_plugin.cpp msgid "History Prev" @@ -4848,9 +4708,8 @@ msgid "Close Docs" msgstr "Cerrar documentación" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Close All" -msgstr "Cerrar" +msgstr "Cerrar todo" #: editor/plugins/script_editor_plugin.cpp msgid "Close Other Tabs" @@ -4861,9 +4720,8 @@ msgid "Run" msgstr "Ejecutar" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Toggle Scripts Panel" -msgstr "Añadir/quitar favorito" +msgstr "Alternar panel de scripts" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp @@ -4897,14 +4755,12 @@ msgid "Keep Debugger Open" msgstr "Mantener el depurador abierto" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Debug with external editor" -msgstr "Abrir en el editor" +msgstr "Depurar en editor externo" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Open Godot online documentation" -msgstr "Buscar en la documentación de referencia." +msgstr "Abrir documentación online de Godot" #: editor/plugins/script_editor_plugin.cpp msgid "Search the class hierarchy." @@ -4923,9 +4779,8 @@ msgid "Go to next edited document." msgstr "Ir a siguiente documento editado." #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Discard" -msgstr "Discreto" +msgstr "Descartar" #: editor/plugins/script_editor_plugin.cpp msgid "Create Script" @@ -4959,19 +4814,16 @@ msgstr "" "pertenecen está cargada" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Only resources from filesystem can be dropped." -msgstr "Solo se pueden soltar recursos del sistema." +msgstr "Sólo se pueden arrastrar/soltar recursos del sistema de archivos." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Pick Color" -msgstr "Color" +msgstr "Seleccionar color" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Convert Case" -msgstr "Convirtiendo imágenes" +msgstr "Convertir Máy/Min" #: editor/plugins/script_text_editor.cpp msgid "Uppercase" @@ -5002,9 +4854,8 @@ msgid "Select All" msgstr "Seleccionar todo" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Delete Line" -msgstr "Eliminar punto" +msgstr "Eliminar lÃnea" #: editor/plugins/script_text_editor.cpp msgid "Indent Left" @@ -5019,23 +4870,20 @@ msgid "Toggle Comment" msgstr "Des/activar comentario" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Clonar hacia abajo" - -#: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Fold/Unfold Line" -msgstr "Desplegar LÃnea" +msgstr "Plegar/Desplegar lÃnea" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Fold All Lines" -msgstr "Plegar Todas las LÃneas" +msgstr "Plegar todas las lÃneas" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Unfold All Lines" -msgstr "Desplegar Todas las LÃneas" +msgstr "Desplegar todas las lÃneas" + +#: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Clonar hacia abajo" #: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" @@ -5050,9 +4898,8 @@ msgid "Convert Indent To Spaces" msgstr "Convertir Indentación a Espacios" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Convert Indent To Tabs" -msgstr "Convertir Indentación a Tabuladores" +msgstr "Convertir indentación a tabuladores" #: editor/plugins/script_text_editor.cpp msgid "Auto Indent" @@ -5065,7 +4912,7 @@ msgstr "Des/activar «breakpoint»" #: editor/plugins/script_text_editor.cpp msgid "Remove All Breakpoints" -msgstr "Desactivar todos los «breakpoints»" +msgstr "Borrar todos los «breakpoints»" #: editor/plugins/script_text_editor.cpp msgid "Goto Next Breakpoint" @@ -5076,14 +4923,12 @@ msgid "Goto Previous Breakpoint" msgstr "Ir al «breakpoint» anterior" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Convert To Uppercase" -msgstr "Convertir a…" +msgstr "Convertir a mayúsculas" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Convert To Lowercase" -msgstr "Convertir a…" +msgstr "Convertir a minúsculas" #: editor/plugins/script_text_editor.cpp msgid "Find Previous" @@ -5107,7 +4952,7 @@ msgstr "Ayuda contextual" #: editor/plugins/shader_editor_plugin.cpp msgid "Shader" -msgstr "Shader" +msgstr "\"Shader\"" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Change Scalar Constant" @@ -5182,9 +5027,8 @@ msgid "Change Comment" msgstr "Cambiar ComentarÃo" #: editor/plugins/shader_graph_editor_plugin.cpp -#, fuzzy msgid "Add/Remove to Color Ramp" -msgstr "Añadir/quitar a/de rampa de color" +msgstr "Añadir/quitar de rampa de color" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Add/Remove to Curve Map" @@ -5200,40 +5044,39 @@ msgstr "Cambiar Nombre de Entrada" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Connect Graph Nodes" -msgstr "Conectar Nodos de Gráfico" +msgstr "Conectar Nodos Gráficos" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Disconnect Graph Nodes" -msgstr "Desconectar Nodo de Gráfico" +msgstr "Desconectar Nodos Gráficos" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Remove Shader Graph Node" -msgstr "Quitar Nodo de Gráfico de Shaders" +msgstr "Borrar Nodo Gráfico de Shader" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Move Shader Graph Node" -msgstr "Mover Nodo de Gráfico de Shaders" +msgstr "Mover Nodo Gráfico de Shader" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Duplicate Graph Node(s)" -msgstr "Duplicar Nodo(s) de Gráfico" +msgstr "Duplicar Nodo(s) Gráfico" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Delete Shader Graph Node(s)" -msgstr "Quitar Nodo(s) de Gráfico de Shaders" +msgstr "Borrar Nodo(s) Gráfico(s) de Shader" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Error: Cyclic Connection Link" -msgstr "Error: Link de Conección CÃclico" +msgstr "Error: Link de Conexión CÃclico" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Error: Missing Input Connections" -msgstr "Error: Conecciones de Entrada Faltantes" +msgstr "Error: Conexiones de Entrada Faltantes" #: editor/plugins/shader_graph_editor_plugin.cpp -#, fuzzy msgid "Add Shader Graph Node" -msgstr "Añadir nodo de gráficos de sombreador" +msgstr "Añadir nodo gráfico de Shader" #: editor/plugins/spatial_editor_plugin.cpp msgid "Orthogonal" @@ -5264,14 +5107,12 @@ msgid "View Plane Transform." msgstr "Ver transformación en plano." #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Scaling: " -msgstr "Escala:" +msgstr "Escalado: " #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Translating: " -msgstr "Traducciones:" +msgstr "Traduciendo: " #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotating %s degrees." @@ -5279,41 +5120,35 @@ msgstr "Girando %s grados." #: editor/plugins/spatial_editor_plugin.cpp msgid "Keying is disabled (no key inserted)." -msgstr "Poner claves está desactivado (no se insertaron claves)." +msgstr "Insertar claves está desactivado (no se insertaron claves)." #: editor/plugins/spatial_editor_plugin.cpp msgid "Animation Key Inserted." msgstr "Clave de animación insertada." #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Objects Drawn" msgstr "Objetos dibujados" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Material Changes" -msgstr "Actualizar cambios" +msgstr "Cambios del material" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Shader Changes" -msgstr "Actualizar cambios" +msgstr "Cambios del shader" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Surface Changes" -msgstr "Actualizar cambios" +msgstr "Cambios de superficie" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Draw Calls" msgstr "Llamadas de dibujado" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Vertices" -msgstr "Vértice" +msgstr "Vértices" #: editor/plugins/spatial_editor_plugin.cpp msgid "FPS" @@ -5392,94 +5227,82 @@ msgid "Display Overdraw" msgstr "Mostrar superposiciones" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Display Unshaded" -msgstr "Mostrar sin sombras" +msgstr "Mostrar sin sombra" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "View Environment" -msgstr "Entorno" +msgstr "Ver entorno" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "View Gizmos" -msgstr "Gizmos" +msgstr "Ver gizmos" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Information" msgstr "Ver información" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "View FPS" -msgstr "Ver Archivos" +msgstr "Ver FPS" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Half Resolution" -msgstr "Escalar selección" +msgstr "Media resolución" #: editor/plugins/spatial_editor_plugin.cpp msgid "Audio Listener" msgstr "Oyente de Audio" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Doppler Enable" -msgstr "Activar" +msgstr "Activar Doppler" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Freelook Left" msgstr "Vista libre izquierda" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Freelook Right" msgstr "Vista libre derecha" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Freelook Forward" -msgstr "Avanzar" +msgstr "Vista libre frente" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Freelook Backwards" -msgstr "Hacia atrás" +msgstr "Vista libre atrás" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Freelook Up" -msgstr "Vista libre superior" +msgstr "Vista libre arriba" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Freelook Down" -msgstr "Rueda hacia abajo." +msgstr "Vista libre abajo" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Freelook Speed Modifier" -msgstr "Modificador de velocidad de la vista libre" +msgstr "Modificador de velocidad de \"vista libre\"" #: editor/plugins/spatial_editor_plugin.cpp msgid "XForm Dialog" msgstr "Ventana de transformación" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Select Mode (Q)" -msgstr "Modo de selección" +msgstr "Modo de selección (Q)" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "" "Drag: Rotate\n" "Alt+Drag: Move\n" "Alt+RMB: Depth list selection" -msgstr "Alt+Click Der.: Selección en depth list" +msgstr "" +"Arrastrar: Rotar\n" +"Alt + Arrastrar: Mover\n" +"Alt + Click derecho: Selección en la lista de superposición" #: editor/plugins/spatial_editor_plugin.cpp msgid "Move Mode (W)" @@ -5498,14 +5321,12 @@ msgid "Local Coords" msgstr "Coordenadas locales" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Local Space Mode (%s)" -msgstr "Modo escalado (R)" +msgstr "Modo de espacio local (%s)" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Snap Mode (%s)" -msgstr "Modo de fijado:" +msgstr "Modo de ajuste (%s)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" @@ -5540,42 +5361,36 @@ msgid "Insert Animation Key" msgstr "Insertar clave de animación" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Focus Origin" -msgstr "Ver origen" +msgstr "Enfocar origen" #: editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" -msgstr "Seleccionar" +msgstr "Enfocar selección" #: editor/plugins/spatial_editor_plugin.cpp msgid "Align Selection With View" msgstr "Alinear selección con visor" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Tool Select" msgstr "Seleccionar" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Tool Move" msgstr "Mover" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Tool Rotate" -msgstr "Ctrl: Rotar" +msgstr "Rotar" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Tool Scale" -msgstr "Escala:" +msgstr "Escalar" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Toggle Freelook" -msgstr "Modo pantalla completa" +msgstr "Alternar vista libre" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform" @@ -5583,7 +5398,7 @@ msgstr "Transformar" #: editor/plugins/spatial_editor_plugin.cpp msgid "Configure Snap.." -msgstr "Configurar fijado.." +msgstr "Configurar ajuste.." #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog.." @@ -5628,23 +5443,23 @@ msgstr "Ajustes" #: editor/plugins/spatial_editor_plugin.cpp msgid "Skeleton Gizmo visibility" -msgstr "" +msgstr "Visibilidad de Gizmo esqueleto" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Settings" -msgstr "Ajustes de fijado" +msgstr "Configuración de fijado" #: editor/plugins/spatial_editor_plugin.cpp msgid "Translate Snap:" -msgstr "Fijar desplazamiento:" +msgstr "Ajuste de desplazamiento:" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Snap (deg.):" -msgstr "Fijar rotación (grados):" +msgstr "Ajuste de rotación (grados):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale Snap (%):" -msgstr "Fijar escala (%):" +msgstr "Ajuste de escala (%):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Viewport Settings" @@ -5692,11 +5507,11 @@ msgstr "Posterior" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "ERROR: Couldn't load frame resource!" -msgstr "ERROR: ¡No se pudo cargar el recurso de cuadros!" +msgstr "ERROR: ¡No se pudo cargar el recurso de fotogramas!" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Frame" -msgstr "Añadir cuadro" +msgstr "Añadir fotograma" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Resource clipboard is empty or not a texture!" @@ -5704,7 +5519,7 @@ msgstr "¡El portapapeles de recursos esta vacÃo o no es una textura!" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Paste Frame" -msgstr "Pegar cuadro" +msgstr "Pegar fotograma" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Empty" @@ -5736,7 +5551,7 @@ msgstr "Repetir" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Animation Frames" -msgstr "Cuadros de animación" +msgstr "Fotogramas de animación" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -5747,33 +5562,28 @@ msgid "Insert Empty (After)" msgstr "Insertar vacÃo (después)" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Move (Before)" -msgstr "Borrar nodos" +msgstr "Mover (Antes)" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Move (After)" -msgstr "Mover a la izquierda" +msgstr "Mover (Después)" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "SpriteFrames" -msgstr "Frames del Stack" +msgstr "Fotogramas del sprite" #: editor/plugins/style_box_editor_plugin.cpp msgid "StyleBox Preview:" msgstr "Vista previa de StyleBox:" #: editor/plugins/style_box_editor_plugin.cpp -#, fuzzy msgid "StyleBox" -msgstr "Estilo" +msgstr "Caja de estilos" #: editor/plugins/texture_region_editor_plugin.cpp -#, fuzzy msgid "Set Region Rect" -msgstr "Setear region_rect" +msgstr "Establecer rectángulo de región" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Snap Mode:" @@ -5785,11 +5595,11 @@ msgstr "<Ninguno>" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Pixel Snap" -msgstr "Adherir a pÃxeles" +msgstr "Ajustar a pÃxeles" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Grid Snap" -msgstr "Adherir a cuadrÃcula" +msgstr "Ajustar a cuadrÃcula" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Auto Slice" @@ -5836,14 +5646,12 @@ msgid "Remove Item" msgstr "Remover Item" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove All Items" -msgstr "Quitar elementos de clases" +msgstr "Quitar todos los elementos" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Remove All" -msgstr "Quitar" +msgstr "Quitar todos" #: editor/plugins/theme_editor_plugin.cpp msgid "Edit theme.." @@ -5870,9 +5678,8 @@ msgid "Create Empty Editor Template" msgstr "Crear plantilla de editor vacÃa" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Create From Current Editor Theme" -msgstr "Crear plantilla de editor vacÃa" +msgstr "Crear desde el tema actual del editor" #: editor/plugins/theme_editor_plugin.cpp msgid "CheckBox Radio1" @@ -5922,11 +5729,6 @@ msgstr "Tab 2" msgid "Tab 3" msgstr "Tab 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Tipo:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Tipo de datos:" @@ -5948,33 +5750,28 @@ msgid "Color" msgstr "Color" #: editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Theme" -msgstr "Guardar tema" +msgstr "Tema" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Erase Selection" -msgstr "Eliminar selección" +msgstr "Borrar selección" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Paint TileMap" -msgstr "Pintar TileMap" +msgstr "Dibujar TileMap" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Line Draw" -msgstr "Lineal" +msgstr "Dibujar lÃnea" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Rectangle Paint" -msgstr "Rectángulo de pintura" +msgstr "Dibujar Rectángulo" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Bucket Fill" -msgstr "Cubo" +msgstr "Cubo de relleno" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Erase TileMap" @@ -6001,9 +5798,8 @@ msgid "Mirror Y" msgstr "Voltear verticalmente" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Paint Tile" -msgstr "Pintar TileMap" +msgstr "Dibujar Tile" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Pick Tile" @@ -6039,12 +5835,11 @@ msgstr "¿Crear desde escena?" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Merge from scene?" -msgstr "¿Mergear desde escena?" +msgstr "¿Mezclar desde escena?" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tile Set" -msgstr "TileSet.." +msgstr "\"Tile Set\"" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create from Scene" @@ -6059,59 +5854,57 @@ msgid "Error" msgstr "Error" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Autotiles" -msgstr "Autotrocear" +msgstr "\"Autotiles\"" #: editor/plugins/tile_set_editor_plugin.cpp msgid "" "Select sub-tile to use as icon, this will be also used on invalid autotile " "bindings." msgstr "" +"Seleccione sub-tile para utilizar como icono, éste se utilizará también en " +"enlazados automáticos no válidos." #: editor/plugins/tile_set_editor_plugin.cpp msgid "" "LMB: set bit on.\n" "RMB: set bit off." msgstr "" +"Click izquierdo: habilitar bit.\n" +"Click derecho: deshabilitar bit." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Select current edited sub-tile." -msgstr "Guardar el recurso editado actualmente." +msgstr "Guardar el sub-tile editado actualmente." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Select sub-tile to change its priority." -msgstr "" +msgstr "Selecciona sub-tile para cambiar su prioridad." #: editor/progress_dialog.cpp scene/gui/dialogs.cpp msgid "Cancel" msgstr "Cancelar" #: editor/project_export.cpp -#, fuzzy msgid "Runnable" -msgstr "Activar" +msgstr "Ejecutable" #: editor/project_export.cpp -#, fuzzy msgid "Delete patch '%s' from list?" -msgstr "Eliminar entrada" +msgstr "¿Eliminar patch '%s' de la lista?" #: editor/project_export.cpp -#, fuzzy msgid "Delete preset '%s'?" -msgstr "¿Quieres eliminar los archivos seleccionados?" +msgstr "¿Eliminar preajuste '%s'?" #: editor/project_export.cpp -#, fuzzy msgid "Export templates for this platform are missing/corrupted: " -msgstr "Faltan las siguientes plantillas de exportación para esta plataforma:" +msgstr "" +"Las plantillas de exportación para esta plataforma faltan/están corruptas: " #: editor/project_export.cpp -#, fuzzy msgid "Presets" -msgstr "Ajuste…" +msgstr "Preajustes" #: editor/project_export.cpp editor/project_settings_editor.cpp msgid "Add.." @@ -6122,121 +5915,99 @@ msgid "Resources" msgstr "Recursos" #: editor/project_export.cpp -#, fuzzy msgid "Export all resources in the project" -msgstr "Exportar todos los recursos en el proyecto." +msgstr "Exportar todos los recursos del proyecto" #: editor/project_export.cpp -#, fuzzy msgid "Export selected scenes (and dependencies)" -msgstr "Exportar los recursos seleccionado (incluyendo dependencias)." +msgstr "Exportar las escenas seleccionadas (incluyendo dependencias)" #: editor/project_export.cpp -#, fuzzy msgid "Export selected resources (and dependencies)" -msgstr "Exportar los recursos seleccionado (incluyendo dependencias)." +msgstr "Exportar los recursos seleccionado (incluyendo dependencias)" #: editor/project_export.cpp msgid "Export Mode:" msgstr "Modo de exportación:" #: editor/project_export.cpp -#, fuzzy msgid "Resources to export:" msgstr "Recursos a exportar:" #: editor/project_export.cpp -#, fuzzy msgid "" "Filters to export non-resource files (comma separated, e.g: *.json, *.txt)" msgstr "" "Filtros para exportar archivos que no son recursos (separados por comas, ej: " -"*.json, *.txt):" +"*.json, *.txt)" #: editor/project_export.cpp -#, fuzzy msgid "" "Filters to exclude files from project (comma separated, e.g: *.json, *.txt)" msgstr "" "Filtros para excluir de la exportación (separados por comas, ej: *.json, *." -"txt):" +"txt)" #: editor/project_export.cpp -#, fuzzy msgid "Patches" -msgstr "Coincidencias:" +msgstr "Exportaciones previas" #: editor/project_export.cpp -#, fuzzy msgid "Make Patch" -msgstr "Ruta de destino:" +msgstr "Hacer \"Patch\"" #: editor/project_export.cpp -#, fuzzy msgid "Features" -msgstr "Textura" +msgstr "CaracterÃsticas" #: editor/project_export.cpp -#, fuzzy msgid "Custom (comma-separated):" msgstr "Personalizado (separado por comas):" #: editor/project_export.cpp -#, fuzzy msgid "Feature List:" -msgstr "Lista de métodos:" +msgstr "Lista de caracterÃsticas:" #: editor/project_export.cpp msgid "Export PCK/Zip" msgstr "Exportar PCK/Zip" #: editor/project_export.cpp -#, fuzzy msgid "Export templates for this platform are missing:" -msgstr "Faltan las siguientes plantillas de exportación para esta plataforma:" +msgstr "Faltan plantillas de exportación para esta plataforma:" #: editor/project_export.cpp -#, fuzzy msgid "Export templates for this platform are missing/corrupted:" -msgstr "Faltan las siguientes plantillas de exportación para esta plataforma:" +msgstr "" +"Las plantillas de exportación para esta plataforma faltan/están corruptas:" #: editor/project_export.cpp -#, fuzzy msgid "Export With Debug" -msgstr "Exportar Tile Set" +msgstr "Exportar con depuración" #: editor/project_manager.cpp -#, fuzzy msgid "The path does not exist." -msgstr "El archivo existe." +msgstr "La ruta no existe." #: editor/project_manager.cpp -#, fuzzy msgid "Please choose a 'project.godot' file." -msgstr "¡Prueba exportando fuera de la carpeta del proyecto!" +msgstr "Por favor elija un archivo 'project.godot'." #: editor/project_manager.cpp -#, fuzzy msgid "Please choose an empty folder." -msgstr "¡Prueba exportando fuera de la carpeta del proyecto!" - -#: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" -"Por favor, elige un directorio que no contenga un archivo 'project.godot'." +msgstr "Por favor elija una carpeta vacÃa." #: editor/project_manager.cpp msgid "Imported Project" msgstr "Proyecto importado" #: editor/project_manager.cpp -#, fuzzy msgid "Couldn't create folder." msgstr "No se pudo crear la carpeta." #: editor/project_manager.cpp msgid "There is already a folder in this path with the specified name." -msgstr "" +msgstr "Ya hay una carpeta en esta ruta con ese nombre." #: editor/project_manager.cpp msgid "It would be a good idea to name your project." @@ -6247,33 +6018,28 @@ msgid "Invalid project path (changed anything?)." msgstr "La ruta del proyecto no es correcta (¿has cambiado algo?)." #: editor/project_manager.cpp -#, fuzzy -msgid "Couldn't get project.godot in project path." -msgstr "No se pudo crear engine.cfg en la ruta de proyecto." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"No se pudo cargar project.godot desde la ruta de proyecto (error %d). La " +"ruta no existe o está corrupta." #: editor/project_manager.cpp -#, fuzzy msgid "Couldn't edit project.godot in project path." -msgstr "No se pudo crear engine.cfg en la ruta de proyecto." +msgstr "No se pudo editar project.godot en la ruta del proyecto." #: editor/project_manager.cpp -#, fuzzy msgid "Couldn't create project.godot in project path." -msgstr "No se pudo crear engine.cfg en la ruta de proyecto." +msgstr "No se pudo crear project.godot en la ruta del proyecto." #: editor/project_manager.cpp msgid "The following files failed extraction from package:" msgstr "Los siguientes archivos no se pudieron extraer del paquete:" #: editor/project_manager.cpp -#, fuzzy msgid "Rename Project" -msgstr "Proyecto sin nombre" - -#: editor/project_manager.cpp -#, fuzzy -msgid "Couldn't get project.godot in the project path." -msgstr "No se pudo crear engine.cfg en la ruta de proyecto." +msgstr "Renombrar proyecto" #: editor/project_manager.cpp msgid "New Game Project" @@ -6284,34 +6050,30 @@ msgid "Import Existing Project" msgstr "Importar proyecto existente" #: editor/project_manager.cpp -#, fuzzy msgid "Import & Edit" -msgstr "Importar y abrir" +msgstr "Importar y editar" #: editor/project_manager.cpp msgid "Create New Project" msgstr "Crear proyecto nuevo" #: editor/project_manager.cpp -#, fuzzy msgid "Create & Edit" -msgstr "Crear emisor" +msgstr "Crear y editar" #: editor/project_manager.cpp msgid "Install Project:" msgstr "Instalar proyecto:" #: editor/project_manager.cpp -#, fuzzy msgid "Install & Edit" -msgstr "Instalar" +msgstr "Instalar y editar" #: editor/project_manager.cpp msgid "Project Name:" msgstr "Nombre del proyecto:" #: editor/project_manager.cpp -#, fuzzy msgid "Create folder" msgstr "Crear carpeta" @@ -6328,32 +6090,29 @@ msgid "Unnamed Project" msgstr "Proyecto sin nombre" #: editor/project_manager.cpp -#, fuzzy msgid "Can't open project" -msgstr "Conectar.." +msgstr "No se puede abrir proyecto" #: editor/project_manager.cpp msgid "Are you sure to open more than one project?" msgstr "¿Seguro que quieres abrir más de un proyecto?" #: editor/project_manager.cpp -#, fuzzy msgid "" "Can't run project: no main scene defined.\n" "Please edit the project and set the main scene in \"Project Settings\" under " "the \"Application\" category." msgstr "" -"No se ha definido ninguna escena principal, ¿quieres elegir alguna?\n" -"Es posible cambiarla más tarde en «Ajustes del proyecto» bajo la categorÃa " -"«aplicación»." +"No hay una escena principal definida para ejecutar el proyecto.\n" +"Por favor elija la escena principal en \"Ajustes del proyecto\" en la " +"categorÃa \"Aplicación\"." #: editor/project_manager.cpp -#, fuzzy msgid "" "Can't run project: Assets need to be imported.\n" "Please edit the project to trigger the initial import." msgstr "" -"No se puede ejecutar el proyecto: Los assets necesitan ser importados.\n" +"No se puede ejecutar el proyecto: los assets necesitan ser importados.\n" "Por favor, edita el proyecto para activar el importado inicial." #: editor/project_manager.cpp @@ -6404,31 +6163,27 @@ msgid "New Project" msgstr "Proyecto nuevo" #: editor/project_manager.cpp -#, fuzzy msgid "Templates" -msgstr "Remover Item" +msgstr "Plantillas" #: editor/project_manager.cpp msgid "Exit" msgstr "Salir" #: editor/project_manager.cpp -#, fuzzy msgid "Restart Now" -msgstr "Reiniciar (s):" +msgstr "Reiniciar ahora" #: editor/project_manager.cpp -#, fuzzy msgid "Can't run project" -msgstr "Conectar.." +msgstr "No se puede ejecutar el proyecto" #: editor/project_manager.cpp -#, fuzzy msgid "" "You don't currently have any projects.\n" "Would you like to explore the official example projects in the Asset Library?" msgstr "" -"Actualmente no tiene ningún proyecto.\n" +"Ahora mismo no tiene ningún proyecto.\n" "¿Le gustarÃa explorar los proyectos ejemplo oficiales del Asset Library?" #: editor/project_settings_editor.cpp @@ -6520,32 +6275,28 @@ msgid "Button 9" msgstr "Botón 9" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Joypad Axis Index:" -msgstr "Ãndice de ejes del mando:" +msgstr "Ãndice de eje del mando:" #: editor/project_settings_editor.cpp msgid "Axis" msgstr "Eje" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Joypad Button Index:" -msgstr "Ãndice de botones del mando:" +msgstr "Ãndice de boton del mando:" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Erase Input Action" -msgstr "Borrar evento de acción de entrada" +msgstr "Borrar \"Input Action\"" #: editor/project_settings_editor.cpp msgid "Erase Input Action Event" msgstr "Borrar evento de acción de entrada" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Add Event" -msgstr "Añadir elemento vacÃo" +msgstr "Añadir evento" #: editor/project_settings_editor.cpp msgid "Device" @@ -6576,38 +6327,32 @@ msgid "Wheel Down." msgstr "Rueda hacia abajo." #: editor/project_settings_editor.cpp -#, fuzzy msgid "Add Global Property" -msgstr "Añadir propiedad «Getter»" +msgstr "Añadir propiedad global" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Select a setting item first!" -msgstr "¡Selecciona un item primero!" +msgstr "¡Selecciona un Ãtem primero!" #: editor/project_settings_editor.cpp -#, fuzzy msgid "No property '%s' exists." -msgstr "Propiedad:" +msgstr "No existe la propiedad '%s'." #: editor/project_settings_editor.cpp msgid "Setting '%s' is internal, and it can't be deleted." msgstr "El ajuste '%s' es interno y no puede ser eliminado." #: editor/project_settings_editor.cpp -#, fuzzy msgid "Delete Item" -msgstr "Eliminar entrada" +msgstr "Eliminar elemento" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Can't contain '/' or ':'" -msgstr "No se puede conectar al host:" +msgstr "No puede contener '/' o ':'" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Already existing" -msgstr "Des/activar persistencia" +msgstr "Ya existe" #: editor/project_settings_editor.cpp msgid "Add Input Action" @@ -6622,7 +6367,6 @@ msgid "Settings saved OK." msgstr "Los ajustes se han guardado correctamente." #: editor/project_settings_editor.cpp -#, fuzzy msgid "Override for Feature" msgstr "Sobreescribir para esta caracterÃstica" @@ -6655,19 +6399,16 @@ msgid "Remove Resource Remap Option" msgstr "Quitar opción de remapeo de recursos" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Changed Locale Filter" -msgstr "Cambiar tiempo de mezcla" +msgstr "Cambiar filtro de localización" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Changed Locale Filter Mode" -msgstr "Modo de Filtro del Locale Cambiado" +msgstr "Modo de filtro de localización cambiado" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Project Settings (project.godot)" -msgstr "Ajustes de proyecto (engine.cfg)" +msgstr "Ajustes del proyecto (project.godot)" #: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp msgid "General" @@ -6678,9 +6419,8 @@ msgid "Property:" msgstr "Propiedad:" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Override For.." -msgstr "Sobreescribir para.." +msgstr "Sobre escribir por.." #: editor/project_settings_editor.cpp msgid "Input Map" @@ -6727,38 +6467,32 @@ msgid "Locale" msgstr "Idioma" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Locales Filter" -msgstr "Filtrado de imágenes:" +msgstr "Filtro de localizaciones" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Show all locales" -msgstr "Crear huesos" +msgstr "Mostrar todas las localizaciones" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Show only selected locales" -msgstr "Mostrar solo Las Configuraciones Regionales Seleccionadas" +msgstr "Mostrar solo las configuraciones regionales seleccionadas" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Filter mode:" -msgstr "Filtros" +msgstr "Modo de filtrado:" #: editor/project_settings_editor.cpp -#, fuzzy msgid "Locales:" -msgstr "Idioma" +msgstr "Idiomas:" #: editor/project_settings_editor.cpp msgid "AutoLoad" msgstr "AutoLoad" #: editor/property_editor.cpp -#, fuzzy msgid "Pick a Viewport" -msgstr "1 visor" +msgstr "Selecciona un visor" #: editor/property_editor.cpp msgid "Ease In" @@ -6793,45 +6527,38 @@ msgid "Assign" msgstr "Asignar" #: editor/property_editor.cpp -#, fuzzy msgid "Select Node" -msgstr "Selecciona un nodo" +msgstr "Seleccionar nodo" #: editor/property_editor.cpp -#, fuzzy msgid "New Script" -msgstr "Script siguiente" +msgstr "Nuevo script" #: editor/property_editor.cpp msgid "New %s" -msgstr "" +msgstr "Nuevo %s" #: editor/property_editor.cpp -#, fuzzy msgid "Make Unique" -msgstr "Crear huesos" +msgstr "Hacer único" #: editor/property_editor.cpp -#, fuzzy msgid "Show in File System" -msgstr "SistDeArchivos" +msgstr "Mostrar en el sistema de archivos" #: editor/property_editor.cpp -#, fuzzy msgid "Convert To %s" -msgstr "Convertir a.." +msgstr "Convertir a %s" #: editor/property_editor.cpp msgid "Error loading file: Not a resource!" msgstr "Error al cargar el archivo: ¡No es un recurso!" #: editor/property_editor.cpp -#, fuzzy msgid "Selected node is not a Viewport!" -msgstr "Selecciona nodos a importar" +msgstr "¡El nodo seleccionado no es un visor!" #: editor/property_editor.cpp -#, fuzzy msgid "Pick a Node" msgstr "Selecciona un nodo" @@ -6844,9 +6571,8 @@ msgid "On" msgstr "Activado" #: editor/property_editor.cpp -#, fuzzy msgid "[Empty]" -msgstr "Añadir elemento vacÃo" +msgstr "[VacÃo]" #: editor/property_editor.cpp modules/visual_script/visual_script_editor.cpp msgid "Set" @@ -6861,14 +6587,12 @@ msgid "Select Property" msgstr "Seleccionar Propiedad" #: editor/property_selector.cpp -#, fuzzy msgid "Select Virtual Method" -msgstr "Modo de selección" +msgstr "Seleccionar método virtual" #: editor/property_selector.cpp -#, fuzzy msgid "Select Method" -msgstr "Modo de selección" +msgstr "Seleccionar método" #: editor/pvrtc_compress.cpp msgid "Could not execute PVRTC tool:" @@ -6961,7 +6685,6 @@ msgid "Delete Node(s)?" msgstr "¿Quieres borrar los nodos?" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Can not perform with the root node." msgstr "No se puede efectuar con el nodo raÃz." @@ -7018,18 +6741,13 @@ msgid "Error duplicating scene to save it." msgstr "Error al duplicar escena para guardarla." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Sub-Resources" -msgstr "Recursos:" +msgstr "Sub-recursos" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance" msgstr "Limpiar heredado" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Abrir en el editor" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Borrar nodos" @@ -7047,14 +6765,12 @@ msgid "Change Type" msgstr "Cambiar tipo" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach Script" -msgstr "Añadir script" +msgstr "Adjuntar script" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Clear Script" -msgstr "Crear script" +msgstr "Quitar script" #: editor/scene_tree_dock.cpp msgid "Merge From Scene" @@ -7065,9 +6781,8 @@ msgid "Save Branch as Scene" msgstr "Guardar Rama como Escena" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Copy Node Path" -msgstr "Copiar ruta" +msgstr "Copiar ruta del nodo" #: editor/scene_tree_dock.cpp msgid "Delete (No Confirm)" @@ -7086,29 +6801,24 @@ msgstr "" "existe ningún nodo raÃz." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Filter nodes" -msgstr "Filtros" +msgstr "Filtrar nodos" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script for the selected node." -msgstr "Crear un nuevo script para el nodo seleccionado." +msgstr "Adjuntar un script nuevo o existente al nodo seleccionado." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Clear a script for the selected node." -msgstr "Crear un nuevo script para el nodo seleccionado." +msgstr "Borra el script del nodo seleccionado." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Remote" -msgstr "Quitar" +msgstr "Remoto" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Local" -msgstr "Idioma" +msgstr "Local" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance? (No Undo!)" @@ -7131,16 +6841,14 @@ msgid "Node configuration warning:" msgstr "Alerta de configuración de nodos:" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "" "Node has connection(s) and group(s)\n" "Click to show signals dock." msgstr "" -"El nodo tiene conexion(es) y grupo(s)\n" +"El nodo tiene conexión/es y grupo/s\n" "Haz click para mostrar el panel de señales." #: editor/scene_tree_editor.cpp -#, fuzzy msgid "" "Node has connections.\n" "Click to show signals dock." @@ -7157,13 +6865,8 @@ msgstr "" "Click para mostrar el panel de grupos." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Instancia:" - -#: editor/scene_tree_editor.cpp -#, fuzzy msgid "Open script" -msgstr "Script siguiente" +msgstr "Abrir script" #: editor/scene_tree_editor.cpp msgid "" @@ -7182,9 +6885,8 @@ msgstr "" "Haz click para hacerlos seleccionables" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "Toggle Visibility" -msgstr "Act/Desact. Espacial Visible" +msgstr "Alternar visibilidad" #: editor/scene_tree_editor.cpp msgid "Invalid node name, the following characters are not allowed:" @@ -7208,19 +6910,16 @@ msgid "Select a Node" msgstr "Selecciona un nodo" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Error loading template '%s'" -msgstr "Error al cargar la imagen:" +msgstr "Error al cargar la plantilla '%s'" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Error - Could not create script in filesystem." -msgstr "No se puede crear el script en el sistema de archivos." +msgstr "Error - No se pudo crear script en el sistema." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Error loading script from %s" -msgstr "Error al cargar escena desde %s" +msgstr "Error al cargar script desde %s" #: editor/script_create_dialog.cpp msgid "N/A" @@ -7243,90 +6942,76 @@ msgid "Directory of the same name exists" msgstr "Ya existe un directorio con el mismo nombre" #: editor/script_create_dialog.cpp -#, fuzzy msgid "File exists, will be reused" -msgstr "El archivo ya existe, ¿quieres sobreescribirlo?" +msgstr "El archivo ya existe, será reutilizado" #: editor/script_create_dialog.cpp msgid "Invalid extension" msgstr "La extensión no es correcta" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Wrong extension chosen" msgstr "Extensión seleccionada errónea" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Invalid Path" -msgstr "Ruta incorrecta." +msgstr "Ruta inválida" #: editor/script_create_dialog.cpp msgid "Invalid class name" msgstr "El nombre de clase no es correcto" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Invalid inherited parent name or path" -msgstr "El nombre de la propiedad Ãndice no es correcto." +msgstr "Nombre heredado o ruta inválida" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Script valid" -msgstr "Script" +msgstr "Script válido" #: editor/script_create_dialog.cpp msgid "Allowed: a-z, A-Z, 0-9 and _" msgstr "Permitido: a-z, A-Z, 0-9 y _" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Built-in script (into scene file)" msgstr "Script integrado (en el archivo de escena)" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Create new script file" -msgstr "Crear script" +msgstr "Crear nuevo archivo de script" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Load existing script file" -msgstr "Script siguiente" +msgstr "Cargar archivo de script existente" #: editor/script_create_dialog.cpp msgid "Language" msgstr "Idioma" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Inherits" -msgstr "Hereda:" +msgstr "Hereda" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Class Name" -msgstr "Nombre de clase:" +msgstr "Nombre de clase" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Template" -msgstr "Remover Item" +msgstr "Plantilla" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Built-in Script" msgstr "Script integrado" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Attach Node Script" -msgstr "Crear script de nodo" +msgstr "Adjuntar script de nodo" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Remote " -msgstr "Quitar" +msgstr "Remoto " #: editor/script_editor_debugger.cpp msgid "Bytes:" @@ -7361,9 +7046,8 @@ msgid "Child Process Connected" msgstr "Proceso Hijo Conectado" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Copy Error" -msgstr "Errores de carga" +msgstr "Error de copia" #: editor/script_editor_debugger.cpp msgid "Inspect Previous Instance" @@ -7459,7 +7143,7 @@ msgstr "Atajos" #: editor/settings_config_dialog.cpp msgid "Binding" -msgstr "" +msgstr "Asignación" #: editor/spatial_editor_gizmos.cpp msgid "Change Light Radius" @@ -7506,59 +7190,52 @@ msgid "Change Particles AABB" msgstr "Cambiar partÃculas AABB" #: editor/spatial_editor_gizmos.cpp -#, fuzzy msgid "Change Probe Extents" -msgstr "Cambiar Alcances de Notificadores" +msgstr "Cambiar Alcance de la Sonda" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Select the dynamic library for this entry" -msgstr "" +msgstr "Selecciona la librerÃa dinámica para esta entrada" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Select dependencies of the library for this entry" -msgstr "" +msgstr "Selecciona las dependencias de la librerÃa para esta entrada" #: modules/gdnative/gdnative_library_editor_plugin.cpp -#, fuzzy msgid "Remove current entry" -msgstr "Quitar Punto de ruta" +msgstr "Borrar entrada actual" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Double click to create a new entry" -msgstr "" +msgstr "Doble click para crear una nueva entrada" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Platform:" -msgstr "" +msgstr "Plataforma:" #: modules/gdnative/gdnative_library_editor_plugin.cpp -#, fuzzy msgid "Platform" -msgstr "Copiar a plataforma…" +msgstr "Plataforma" #: modules/gdnative/gdnative_library_editor_plugin.cpp -#, fuzzy msgid "Dynamic Library" -msgstr "MeshLibrary.." +msgstr "LibrerÃa dinámica" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Add an architecture entry" -msgstr "" +msgstr "Añadir entrada de arquitectura" #: modules/gdnative/gdnative_library_editor_plugin.cpp -#, fuzzy msgid "GDNativeLibrary" -msgstr "GDNative" +msgstr "\"GDNativeLibrary\"" #: modules/gdnative/gdnative_library_singleton_editor.cpp -#, fuzzy msgid "Library" -msgstr "MeshLibrary.." +msgstr "Biblioteca" #: modules/gdnative/gdnative_library_singleton_editor.cpp -#, fuzzy msgid "Status" -msgstr "Estado:" +msgstr "Estado" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Libraries: " @@ -7566,7 +7243,7 @@ msgstr "Bibliotecas: " #: modules/gdnative/register_types.cpp msgid "GDNative" -msgstr "GDNative" +msgstr "\"GDNative\"" #: modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -7623,54 +7300,56 @@ msgid "Object can't provide a length." msgstr "El objeto no puede proporcionar una longitud." #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "GridMap Delete Selection" -msgstr "Quitar seleccionados" +msgid "Next Plane" +msgstr "Plano siguiente" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "Duplicar selección" +msgid "Previous Plane" +msgstr "Plano anterior" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "Plano:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Suelo Posterior" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Suelo Anterior" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Floor:" -msgstr "Piso:" +msgstr "Suelo:" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "Grid Map" -msgstr "Adherir a cuadrÃcula" +msgid "GridMap Delete Selection" +msgstr "GridMap Quitar seleccionados" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "Snap View" -msgstr "Vista superior" +msgid "GridMap Duplicate Selection" +msgstr "GridMap Duplicar selección" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "Previous Floor" -msgstr "Pestaña anterior" +msgid "Grid Map" +msgstr "Rejilla" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "Next Floor" -msgstr "Próximo Piso" +msgid "Snap View" +msgstr "Fijar Vista" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Clip Disabled" -msgstr "Desactivado" +msgstr "Clip Deshabilitado" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Clip Above" -msgstr "Clip superior" +msgstr "Clip Arriba" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Clip Below" -msgstr "Clip inferior" +msgstr "Clip Debajo" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Edit X Axis" @@ -7685,122 +7364,108 @@ msgid "Edit Z Axis" msgstr "Editar eje Z" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Cursor Rotate X" -msgstr "Ctrl: Rotar" +msgstr "Rotar cursor X" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Cursor Rotate Y" -msgstr "Ctrl: Rotar" +msgstr "Rotar cursor Y" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Cursor Rotate Z" -msgstr "Ctrl: Rotar" +msgstr "Rotar cursor Z" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Cursor Back Rotate X" msgstr "Rotar cursor trasero X" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Cursor Back Rotate Y" msgstr "Rotar cursor trasero Y" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Cursor Back Rotate Z" msgstr "Rotar cursor trasero Z" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Cursor Clear Rotation" msgstr "Quitar rotación del cursor" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Create Area" -msgstr "Crear nuevo" +msgstr "Crear area" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Create Exterior Connector" -msgstr "Crear proyecto nuevo" +msgstr "Crear conector exterior" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Erase Area" -msgstr "Borrar TileMap" +msgstr "Borrar area" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Clear Selection" -msgstr "Centrar selección" +msgstr "Deseleccionar" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "GridMap Settings" -msgstr "Ajustes de fijado" +msgstr "Ajustes del GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Pick Distance:" -msgstr "Instancia:" +msgstr "Seleccionar distancia:" #: modules/mono/editor/godotsharp_editor.cpp -#, fuzzy msgid "Generating solution..." -msgstr "Creando octree de texturas" +msgstr "Generando solución..." #: modules/mono/editor/godotsharp_editor.cpp msgid "Generating C# project..." -msgstr "" +msgstr "Generando proyecto C#..." #: modules/mono/editor/godotsharp_editor.cpp -#, fuzzy msgid "Failed to create solution." -msgstr "¡No se pudo crear el contorno!" +msgstr "Fallo al crear solución." #: modules/mono/editor/godotsharp_editor.cpp -#, fuzzy msgid "Failed to save solution." -msgstr "Hubo un problema al cargar el recurso." +msgstr "Fallo al guardar solución." #: modules/mono/editor/godotsharp_editor.cpp -#, fuzzy msgid "Done" -msgstr "¡Hecho!" +msgstr "Hecho" #: modules/mono/editor/godotsharp_editor.cpp -#, fuzzy msgid "Failed to create C# project." -msgstr "Hubo un problema al cargar el recurso." +msgstr "Fallo al crear proyecto C#." #: modules/mono/editor/godotsharp_editor.cpp msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp -#, fuzzy +msgid "About C# support" +msgstr "Sobre el soporte de C#" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" -msgstr "Crear contorno" +msgstr "Crear solución C#" #: modules/mono/editor/mono_bottom_panel.cpp -#, fuzzy msgid "Builds" msgstr "Compilaciones" #: modules/mono/editor/mono_bottom_panel.cpp -#, fuzzy msgid "Build Project" -msgstr "Proyecto" +msgstr "Compilar proyecto" #: modules/mono/editor/mono_bottom_panel.cpp -#, fuzzy msgid "Warnings" -msgstr "Advertencia" +msgstr "Advertencias" + +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" #: modules/visual_script/visual_script.cpp msgid "" @@ -7841,29 +7506,24 @@ msgid "Stack overflow with stack depth: " msgstr "Desbordamiento de pila en el nivel: " #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Signal Arguments" -msgstr "Editar argumentos de señal:" +msgstr "Cambiar argumentos de la señal" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Argument Type" -msgstr "Cambiar tipo de valor del «array»" +msgstr "Cambiar tipo del argumento" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Argument name" -msgstr "Cambiar Nombre de Entrada" +msgstr "Cambiar nombre del argumento" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Set Variable Default Value" -msgstr "Cambiar Valor por Defecto" +msgstr "Establecer valor por defecto de la variable" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Set Variable Type" -msgstr "Editar variable:" +msgstr "Establecer tipo de la variable" #: modules/visual_script/visual_script_editor.cpp msgid "Functions:" @@ -7906,54 +7566,48 @@ msgid "Add Signal" msgstr "Añadir señal" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Expression" -msgstr "Cambiar tipo" +msgstr "Cambiar expresión" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node" msgstr "Añadir nodo" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Remove VisualScript Nodes" -msgstr "Quitar claves incorrectas" +msgstr "Quitar nodos de VisualScript" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Duplicate VisualScript Nodes" -msgstr "Duplicar Nodo(s) de Gráfico" +msgstr "Duplicar nodos de VisualScript" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Hold %s to drop a Getter. Hold Shift to drop a generic signature." msgstr "" -"Mantén pulsado Meta para quitar un «Setter». Mantén pulsado Mayús para " -"quitar una firma genérica." +"Mantén pulsado %s para soltar un «Getter». Mantén pulsado Shift para soltar " +"una signatura genérica." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" -"Mantén pulsado Ctrl para quitar un «Getter». Mantén pulsado Mayús para " -"quitar una firma genérica." +"Mantén pulsado Ctrl para soltar un «Getter». Mantén pulsado Mayús para " +"soltar una signatura genérica." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Hold %s to drop a simple reference to the node." -msgstr "Mantén pulsado Meta para quitar una referencia simple del nodo." +msgstr "Mantén pulsado %s para quitar una referencia simple del nodo." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "Mantén pulsado Ctrl para quitar una referencia simple del nodo." +msgstr "Mantén pulsado Ctrl para soltar una referencia al nodo." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Hold %s to drop a Variable Setter." -msgstr "Mantén pulsado Meta para quitar un «Setter» de variable." +msgstr "Mantén pulsado %s para quitar un «Setter» de variable." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." -msgstr "Mantén pulsado Ctrl para quitar un «Setter» de variable." +msgstr "Mantén pulsado Ctrl para soltar un «Setter» de variable." #: modules/visual_script/visual_script_editor.cpp msgid "Add Preload Node" @@ -7972,39 +7626,32 @@ msgid "Add Setter Property" msgstr "Añadir propiedad «Setter»" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Base Type" -msgstr "Cambiar tipo" +msgstr "Cambiar tipo base" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Move Node(s)" -msgstr "Borrar nodos" +msgstr "Mover nodo/s" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Remove VisualScript Node" -msgstr "Quitar Nodo de Gráfico de Shaders" +msgstr "Quitar nodo de VisualScript" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Connect Nodes" -msgstr "Conectar a nodo:" +msgstr "Conectar nodos" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Condition" -msgstr "Copiar animación" +msgstr "Condición" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Sequence" msgstr "Secuencia" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Switch" -msgstr "Altura" +msgstr "Interruptor" #: modules/visual_script/visual_script_editor.cpp msgid "Iterator" @@ -8012,61 +7659,55 @@ msgstr "Iterador" #: modules/visual_script/visual_script_editor.cpp msgid "While" -msgstr "Mientras" +msgstr "Mientras (\"While\")" #: modules/visual_script/visual_script_editor.cpp msgid "Return" -msgstr "Devuelve" +msgstr "Devuelve (\"Return\")" #: modules/visual_script/visual_script_editor.cpp msgid "Call" -msgstr "Llamada" +msgstr "Llamada (\"Call\")" #: modules/visual_script/visual_script_editor.cpp msgid "Get" -msgstr "Obtener" +msgstr "Obtener (\"Get\")" #: modules/visual_script/visual_script_editor.cpp msgid "Script already has function '%s'" msgstr "El script ya contiene la función '%s'" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Input Value" -msgstr "Cambiar Nombre de Entrada" +msgstr "Cambiar valor de entrada" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Can't copy the function node." -msgstr "No se puede operar en «…»" +msgstr "No se puede copiar el nodo de función." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Clipboard is empty!" -msgstr "¡El portapapeles de recursos está vacÃo!" +msgstr "¡El portapapeles está vacÃo!" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Paste VisualScript Nodes" -msgstr "Pegar pose" +msgstr "Pegar nodos de VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Function" msgstr "Quitar función" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Edit Variable" -msgstr "Editar variable:" +msgstr "Editar variable" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Variable" msgstr "Quitar variable" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Edit Signal" -msgstr "Editando señal:" +msgstr "Editar señal" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Signal" @@ -8090,11 +7731,11 @@ msgstr "Nodos disponibles:" #: modules/visual_script/visual_script_editor.cpp msgid "Select or create a function to edit graph" -msgstr "Selecciona o crea una función para editar el grafo" +msgstr "Selecciona o crea una función para editar el gráfico" #: modules/visual_script/visual_script_editor.cpp msgid "Edit Signal Arguments:" -msgstr "Editar argumentos de señal:" +msgstr "Editar argumentos de la señal:" #: modules/visual_script/visual_script_editor.cpp msgid "Edit Variable:" @@ -8105,24 +7746,20 @@ msgid "Delete Selected" msgstr "Quitar seleccionados" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Find Node Type" -msgstr "Buscar por tipo de nodo" +msgstr "Buscar tipo de nodo" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Copy Nodes" -msgstr "Copiar pose" +msgstr "Copiar nodos" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Cut Nodes" -msgstr "Crear nodo" +msgstr "Cortar nodos" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Paste Nodes" -msgstr "Pegar pose" +msgstr "Pegar nodos" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -8138,7 +7775,7 @@ msgstr "El iterador ya no es correcto: " #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name." -msgstr "El nombre de la propiedad Ãndice no es correcto." +msgstr "Ãndice del nombre de la propiedad inválido." #: modules/visual_script/visual_script_func_nodes.cpp msgid "Base object is not a Node!" @@ -8150,7 +7787,7 @@ 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." -msgstr "El nombre de la propiedad Ãndice en el nodo %s no es correcto." +msgstr "Ãndice inválido de nombre de propiedad '%s' en el nodo %s." #: modules/visual_script/visual_script_nodes.cpp msgid ": Invalid argument of type: " @@ -8172,7 +7809,7 @@ msgstr "VariableSet no encontrado en el script: " msgid "Custom node has no _step() method, can't process graph." msgstr "" "El nodo personalizado no tiene ningún método _step(), no se puede procesar " -"el grafo." +"el gráfico." #: modules/visual_script/visual_script_nodes.cpp msgid "" @@ -8183,51 +7820,44 @@ msgstr "" "o string/cadena (error)." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Run in Browser" -msgstr "Examinar" +msgstr "Ejecutar en navegador" #: platform/javascript/export/export.cpp msgid "Run exported HTML in the system's default browser." msgstr "Ejecutar HTML exportado en el navegador por defecto del sistema." #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not write file:" -msgstr "No se pudo cargar el tile:" +msgstr "No se puede escribir en el archivo:" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not open template for export:" -msgstr "No se pudo crear la carpeta." +msgstr "No se pudo abrir la plantilla para exportar:" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Invalid export template:" -msgstr "Instalar plantillas de exportación" +msgstr "Plantilla de exportación inválida:" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not read custom HTML shell:" -msgstr "No se pudo cargar el tile:" +msgstr "No se puede leer shell HTML personalizada:" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Could not read boot splash image file:" -msgstr "No se pudo cargar el tile:" +msgstr "No se pudo leer la imagen de carga:" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Using default boot splash image." -msgstr "No se pudo cargar el tile:" +msgstr "Usando la imagen de carga por defecto." #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " "order for AnimatedSprite to display frames." msgstr "" -"Un recurso SpriteFrames debe ser creado o seteado en la propiedad 'Frames' " -"para que AnimatedSprite pueda mostrar frames." +"Se debe crear un recurso \"SpriteFrames\" o asignar uno en la propiedad " +"'Frames' para que AnimatedSprite pueda mostrar fotogramas." #: scene/2d/canvas_modulate.cpp msgid "" @@ -8235,8 +7865,8 @@ msgid "" "scenes). The first created one will work, while the rest will be ignored." msgstr "" "Solo se permite un CanvasModulate visible por escena (o set de escenas " -"instanciadas). El primero creado va a funcionar, mientras que el resto van a " -"ser ignorados." +"instanciadas). El primero en crearse es el que va a funcionar, mientras que " +"el resto van a ser ignorados." #: scene/2d/collision_object_2d.cpp msgid "" @@ -8244,6 +7874,10 @@ msgid "" "Consider adding CollisionShape2D or CollisionPolygon2D children nodes to " "define its shape." msgstr "" +"Este nodo no tiene formas hijas, por lo que no puede interactuar con el " +"espacio.\n" +"Considere añadir CollisionShape2D o CollisionPolygon2D como hijo para " +"definir su forma." #: scene/2d/collision_polygon_2d.cpp msgid "" @@ -8251,13 +7885,14 @@ msgid "" "CollisionObject2D derived node. Please only use it as a child of Area2D, " "StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." msgstr "" -"CollisionPolylgon2D solo sirve para proveer de un collision shape a un nodo " -"derivado de CollisionObject2D. Favor de usarlo solo como un hijo de Area2D, " -"StaticBody2D, RigidBody2D, KinematicBody2D, etc. para darles un shape." +"CollisionPolygon2D solo sirve para proveer de una forma de colisión a un " +"nodo derivado de CollisionObject2D. Por favor, úsalo solo como hijo de " +"Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. para dotarlos de " +"una forma." #: scene/2d/collision_polygon_2d.cpp msgid "An empty CollisionPolygon2D has no effect on collision." -msgstr "Un CollisionPolygon2D vacÃo no tiene efecto en la colisión." +msgstr "Un CollisionPolygon2D vacÃo no tiene ningún efecto en las colisiones." #: scene/2d/collision_shape_2d.cpp msgid "" @@ -8265,24 +7900,25 @@ msgid "" "CollisionObject2D derived node. Please only use it as a child of Area2D, " "StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." msgstr "" -"CollisionShape2D solo sirve para proveer de un collision shape a un nodo " -"derivado de CollisionObject2D. Favor de usarlo solo como un hijo de Area2D, " -"StaticBody2D, RigidBody2D, KinematicBody2D, etc. para darles un shape." +"CollisionShape2D solo sirve para proveer de una forma de colisión a un nodo " +"derivado de \"CollisionObject2D\". Por favor, úsalo solo como hijo de " +"Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc... para dotarlos de " +"forma." #: scene/2d/collision_shape_2d.cpp msgid "" "A shape must be provided for CollisionShape2D to function. Please create a " "shape resource for it!" msgstr "" -"Se debe proveer un shape para que CollisionShape2D funcione. Creale un " -"recurso shape!" +"Se debe de proveer de forma a CollisionShape2D para que funcione. ¡Creale un " +"recurso \"shape\"!" #: scene/2d/light_2d.cpp msgid "" "A texture with the shape of the light must be supplied to the 'texture' " "property." msgstr "" -"Se debe proveer una textura con la forma de la luz a la propiedad 'texture'." +"Se debe asignar una textura con la forma de la luz a la propiedad 'texture'." #: scene/2d/light_occluder_2d.cpp msgid "" @@ -8293,55 +7929,57 @@ msgstr "" #: scene/2d/light_occluder_2d.cpp msgid "The occluder polygon for this occluder is empty. Please draw a polygon!" -msgstr "El polÃgono de este oclusor esta vacÃo. Dibujá un polÃgono!" +msgstr "" +"El polÃgono oclusor para este oclusor esta vacÃo. Por favor, ¡dibuja un " +"polÃgono!" #: scene/2d/navigation_polygon.cpp msgid "" "A NavigationPolygon resource must be set or created for this node to work. " "Please set a property or draw a polygon." msgstr "" -"Se debe crear o establecer un recurso NavigationPolygon para que este nodo " -"funcione. Prueba estableciendo una propiedad o dibuja un polÃgono." +"Se debe crear o asignar un recurso NavigationPolygon a este nodo para que " +"funcione. Por favor, establece la propiedad o dibuja un polÃgono." #: scene/2d/navigation_polygon.cpp msgid "" "NavigationPolygonInstance must be a child or grandchild to a Navigation2D " "node. It only provides navigation data." msgstr "" -"NavigationPolygonInstance debe ser un hijo o nieto de un nodo Navigation2D. " +"NavigationPolygonInstance debe ser hijo o nieto de un nodo \"Navigation2D\". " "Solo provee datos de navegación." #: scene/2d/parallax_layer.cpp msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" -"ParallaxLayer node solo funciona cuando esta seteado como hijo de un nodo " -"ParallaxBackground." +"En nodo \"ParallaxLayer\" solo funciona cuando esta posicionado como hijo de " +"un nodo \"ParallaxBackground\"." #: scene/2d/particles_2d.cpp scene/3d/particles.cpp -#, fuzzy msgid "" "A material to process the particles is not assigned, so no behavior is " "imprinted." msgstr "" "No se ha asignado un material para procesar las partÃculas, por lo que no se " -"ha grabado ningún comportamiento." +"muestra ningún comportamiento." #: scene/2d/path_2d.cpp msgid "PathFollow2D only works when set as a child of a Path2D node." msgstr "" -"PathFollow2D solo funciona cuando está seteado como hijo de un nodo Path2D." +"\"PathFollow2D\" solo funciona cuando está posicionado como hijo de un nodo " +"\"Path2D\"." #: scene/2d/physics_body_2d.cpp -#, fuzzy msgid "" "Size changes to RigidBody2D (in character or rigid modes) will be overridden " "by the physics engine when running.\n" "Change the size in children collision shapes instead." msgstr "" -"Los cambios en el tamaño del RigidBody2D (en el personaje o modos rÃgidos) " -"serán sobreescritas por el engine de fÃsicas cuando se ejecute.\n" -"En vez de eso, cambia el tamaño en las formas de colisión hijas." +"Los cambios en el tamaño del RigidBody2D (en los modos \"character\" o " +"\"rigid\") serán sobre-escritos por el motor de fÃsicas cuando éste se " +"ejecute.\n" +"En lugar de esto, cambie el tamaño en las formas de colisión hijas." #: scene/2d/remote_transform_2d.cpp msgid "Path property must point to a valid Node2D node to work." @@ -8352,8 +7990,8 @@ msgid "" "VisibilityEnable2D works best when used with the edited scene root directly " "as parent." msgstr "" -"VisibilityEnable2D funciona mejor cuando se usa con la raÃz de escena " -"editada directamente como padre." +"VisibilityEnable2D funciona mejor cuando se usa directamente con la raÃz de " +"la escena editada como padre." #: scene/3d/arvr_nodes.cpp msgid "ARVRCamera must have an ARVROrigin node as its parent" @@ -8364,49 +8002,52 @@ msgid "ARVRController must have an ARVROrigin node as its parent" msgstr "ARVRController tiene que tener un nodo ARVROrigin como padre" #: scene/3d/arvr_nodes.cpp -#, fuzzy msgid "" "The controller id must not be 0 or this controller will not be bound to an " "actual controller" msgstr "" -"El id del controlador no puede ser 0 o este controlador no se asignará a un " -"controlador de verdad." +"El id del controlador no puede ser 0 o este controlador no será asignado a " +"un controlador de verdad" #: scene/3d/arvr_nodes.cpp msgid "ARVRAnchor must have an ARVROrigin node as its parent" msgstr "ARVRAnchor tiene que tener un nodo ARVROrigin como padre" #: scene/3d/arvr_nodes.cpp -#, fuzzy msgid "" "The anchor id must not be 0 or this anchor will not be bound to an actual " "anchor" msgstr "" -"El id del ancla no puede ser 0 o este ancla no se asignará a un ancla de " +"El id del ancla no puede ser 0 o este ancla no será asignada a un ancla de " "verdad" #: scene/3d/arvr_nodes.cpp msgid "ARVROrigin requires an ARVRCamera child node" -msgstr "ARVROrigin necesita un nodo ARVCamera hijo" +msgstr "ARVROrigin necesita un nodo ARVRCamera hijo" + +#: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(Tiempo restante: %d:%02d s)" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Plotting Meshes: " -msgstr "Copiando datos de imágenes" +msgstr "Trazando mallas: " #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Plotting Lights:" -msgstr "Copiando datos de imágenes" +msgstr "Trazando Iluminación:" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp msgid "Finishing Plot" -msgstr "" +msgstr "Desentramado final" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Lighting Meshes: " -msgstr "Copiando datos de imágenes" +msgstr "Iluminando Mallas: " #: scene/3d/collision_object.cpp msgid "" @@ -8414,6 +8055,10 @@ msgid "" "Consider adding CollisionShape or CollisionPolygon children nodes to define " "its shape." msgstr "" +"Este nodo no tiene formas hijas, por lo que no puede interactuar con el " +"espacio.\n" +"Considera añadir un \"CollisionShape\" o \"CollisionPolygon\" como hijos de " +"este nodo para dotarlo de una forma." #: scene/3d/collision_polygon.cpp msgid "" @@ -8421,9 +8066,9 @@ msgid "" "CollisionObject derived node. Please only use it as a child of Area, " "StaticBody, RigidBody, KinematicBody, etc. to give them a shape." msgstr "" -"CollisionPolygon solo sirve para proveer un collision shape a un nodo " -"derivado de un CollisionObject. Favor de usarlo solo como hijo de Area, " -"StaticBody, RigidBody, KinematicBody, etc. para darles un shape." +"CollisionPolygon solo sirve para proveer de una forma de colisión a un nodo " +"derivado de un CollisionObject. Por favor, úselo solo como hijo de Area, " +"StaticBody, RigidBody, KinematicBody, etc. para darles dicha forma." #: scene/3d/collision_polygon.cpp msgid "An empty CollisionPolygon has no effect on collision." @@ -8435,22 +8080,21 @@ msgid "" "derived node. Please only use it as a child of Area, StaticBody, RigidBody, " "KinematicBody, etc. to give them a shape." msgstr "" -"CollisionShape solo sirve para proveer un collision shape a un nodo derivado " -"de un CollisionObject. Favor de usarlo solo como hijo de Area, StaticBody, " -"RigidBody, KinematicBody, etc. para darles un shape." +"CollisionShape solo sirve para proveer de una forma a un nodo derivado de un " +"CollisionObject. Por favor, úsalo solo como hijo de \"Area\", \"StaticBody" +"\", \"RigidBody\", \"KinematicBody\", etc. para darles dicha forma." #: scene/3d/collision_shape.cpp msgid "" "A shape must be provided for CollisionShape to function. Please create a " "shape resource for it!" msgstr "" -"Se debe proveer un shape para que CollisionShape funcione. Creale un recurso " -"shape!" +"Se debe proveer de una forma a CollisionShape para que funcione. Por favor, " +"¡crea un recurso \"shape\"!" #: scene/3d/gi_probe.cpp -#, fuzzy msgid "Plotting Meshes" -msgstr "Copiando datos de imágenes" +msgstr "Trazando Mallas" #: scene/3d/navigation_mesh.cpp msgid "A NavigationMesh resource must be set or created for this node to work." @@ -8463,33 +8107,29 @@ msgid "" "NavigationMeshInstance must be a child or grandchild to a Navigation node. " "It only provides navigation data." msgstr "" -"NavigationMeshInstance debe ser un hijo o nieto de un nodo Navigation. Ya " -"que sólo proporciona los datos de navegación." +"NavigationMeshInstance debe ser hijo o nieto de un nodo Navigation. Ya que " +"sólo proporciona los datos de navegación." #: scene/3d/particles.cpp -#, fuzzy msgid "" "Nothing is visible because meshes have not been assigned to draw passes." msgstr "" -"Nada es visible porque los modelos 3D no se han asignado a las pasadas de " -"dibujo." +"Nada es visible porque las mallas no se han asignado a los pases de dibujo." #: scene/3d/physics_body.cpp -#, fuzzy msgid "" "Size changes to RigidBody (in character or rigid modes) will be overridden " "by the physics engine when running.\n" "Change the size in children collision shapes instead." msgstr "" -"Los cambios en el tamaño del RigidBody (en el personaje o modos rÃgidos) " -"serán sobreescritas por el engine de fÃsicas cuando se ejecute.\n" -"En vez de eso, cambia el tamaño en las formas de colisión hijas." +"Los cambios en el tamaño del RigidBody (en los modos \"character\" o \"rigid" +"\") serán sobre-escritos por el motor de fÃsicas cuando se ejecute.\n" +"En lugar de esto, cambie el tamaño en las formas de colisión hijas." #: scene/3d/remote_transform.cpp -#, fuzzy msgid "Path property must point to a valid Spatial node to work." msgstr "" -"La propiedad Path debe apuntar a un nodo Particles2D valido para funcionar." +"La propiedad Path debe apuntar a un nodo Spatial válido para funcionar." #: scene/3d/scenario_fx.cpp msgid "" @@ -8503,22 +8143,20 @@ msgid "" "A SpriteFrames resource must be created or set in the 'Frames' property in " "order for AnimatedSprite3D to display frames." msgstr "" -"Un recurso SpriteFrames debe ser creado o asignado en la propiedad 'Frames' " -"para que AnimatedSprite3D pueda mostrar frames." +"Se debe crear un recurso \"SpriteFrames\" y asignarlo en la propiedad " +"'Frames' para que AnimatedSprite3D pueda mostrar fotogramas." #: scene/3d/vehicle_body.cpp -#, fuzzy msgid "" "VehicleWheel serves to provide a wheel system to a VehicleBody. Please use " "it as a child of a VehicleBody." msgstr "" "VehicleWheel sirve para proporcionar un sistema de ruedas a un VehicleBody. " -"Úselo como un hijo de un VehicleBody." +"Por favor, úselo como hijo de un VehicleBody." #: scene/gui/color_picker.cpp -#, fuzzy msgid "Raw Mode" -msgstr "Modo desplazamiento lateral" +msgstr "Modo Raw" #: scene/gui/color_picker.cpp msgid "Add current color as a preset" @@ -8526,16 +8164,15 @@ msgstr "Añadir el color actual como predefinido" #: scene/gui/dialogs.cpp msgid "Alert!" -msgstr "Alerta!" +msgstr "¡Alerta!" #: scene/gui/dialogs.cpp msgid "Please Confirm..." msgstr "Confirmar decisión…" #: scene/gui/file_dialog.cpp -#, fuzzy msgid "Select this Folder" -msgstr "Modo de selección" +msgstr "Seleccionar esta carpeta" #: scene/gui/popup.cpp msgid "" @@ -8548,27 +8185,25 @@ msgstr "" "hacerlos visibles para editar, aunque se esconderán al ejecutar." #: scene/gui/scroll_container.cpp -#, fuzzy msgid "" "ScrollContainer is intended to work with a single child control.\n" "Use a container as child (VBox,HBox,etc), or a Control and set the custom " "minimum size manually." msgstr "" -"ScrollContainer debe funcionar con un único control de hijos.\n" -"Usa un container como hijo (VBox,HBox,etc), o un Control y ajusta el tamaño " -"mÃnimo personalizado manualmente." +"ScrollContainer está pensado para funcionar con un control hijo únicamente.\n" +"Usa un contenedor como hijo (VBox,HBox,etc), o un Control y ajusta el tamaño " +"mÃnimo manualmente." #: scene/gui/tree.cpp msgid "(Other)" msgstr "(Otros)" #: scene/main/scene_tree.cpp -#, fuzzy msgid "" "Default Environment as specified in Project Settings (Rendering -> " "Environment -> Default Environment) could not be loaded." msgstr "" -"El entorno por defecto especificado en los Ajustes del Proyecto (Renderizado " +"El entorno especificado por defecto en los Ajustes del Proyecto (Renderizado " "-> Ventana -> Entorno por Defecto) no se ha podido cargar." #: scene/main/viewport.cpp @@ -8578,10 +8213,10 @@ msgid "" "obtain a size. Otherwise, make it a RenderTarget and assign its internal " "texture to some node for display." msgstr "" -"Este viewport no está seteado como render target. Si tienes intención de que " -"muestre contenidos directo a la pantalla, hacelo un hijo de un Control para " -"que pueda obtener un tamaño. Alternativamente, hacelo un RenderTarget y " -"asigná su textura interna a algún otro nodo para mostrar." +"Este viewport no está configurado como \"render target\". Si tienes " +"intención de que muestre su contenido directamente en la pantalla, hazlo " +"hijo de un Control para que pueda obtener un tamaño. Alternativamente, hazlo " +"un RenderTarget y asigna su textura interna a algún otro nodo para mostrar." #: scene/resources/dynamic_font.cpp msgid "Error initializing FreeType." @@ -8599,6 +8234,26 @@ msgstr "Error al cargar la tipografÃa." msgid "Invalid font size." msgstr "Tamaño de tipografÃa incorrecto." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "El archivo \"version.txt\" que hay dentro de las plantillas tiene un " +#~ "formato inválido. \"Revisión\" no es un identificador válido." + +#~ msgid "Can't write file." +#~ msgstr "No se puede escribir el archivo." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "Por favor, elige un directorio que no contenga un archivo 'project.godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "No se encontró project.godot en la ruta del proyecto." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "No se encontró project.godot en la ruta del proyecto." + #~ msgid "Next" #~ msgstr "Siguiente" diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index 55a1953d34..f2d6508201 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-01-24 20:49+0000\n" +"PO-Revision-Date: 2018-02-24 21:43+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" @@ -21,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: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -2464,14 +2464,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Formato de version.txt invalido dentro de plantillas." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Formato de version.txt invalido dentro de plantillas. Revision no es un " -"identificador valido." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "No se encontro ningún version.txt dentro de las plantillas." @@ -2526,10 +2518,6 @@ msgid "Failed:" msgstr "Fallido:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "No se puede escribir el archivo." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Descarga Completa." @@ -3717,15 +3705,15 @@ msgid "Show Grid" msgstr "Mostrar la Grilla" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Mostrar ayudantes" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Mostrar reglas" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Mostrar guÃas" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4554,6 +4542,22 @@ msgid "Resource clipboard is empty!" msgstr "Clipboard de Recursos vacÃo!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Abrir en Editor" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Instancia:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Tipo:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Cargar Recurso" @@ -4840,10 +4844,6 @@ msgid "Toggle Comment" msgstr "Act/Desact. Comentario" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Clonar hacia Abajo" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Expandir/Colapsar LÃnea" @@ -4856,6 +4856,10 @@ msgid "Unfold All Lines" msgstr "Expandir Totas las LÃneas" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Clonar hacia Abajo" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Completar SÃmbolo" @@ -5699,11 +5703,6 @@ msgstr "Tab 2" msgid "Tab 3" msgstr "Tab 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Tipo:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Tipo de Datos:" @@ -5975,11 +5974,6 @@ msgid "Please choose an empty folder." msgstr "Por favor elegà una carpeta vacÃa." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" -"Por favor elegà una carpeta que no contenga un archivo 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Proyecto Importado" @@ -6000,8 +5994,12 @@ msgid "Invalid project path (changed anything?)." msgstr "Ruta de proyecto inválida (cambiaste algo?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "No se pudo obtener project.godot en la ruta de proyecto." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"No se pudo cargar project.godot desde la ruta de proyecto (error %d). La " +"ruta no existe o está corrupta." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6020,10 +6018,6 @@ msgid "Rename Project" msgstr "Renombrar Proyecto" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "No se pudo obtener project.godot en la ruta de proyecto." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Nuevo Proyecto de Juego" @@ -6732,10 +6726,6 @@ msgstr "Sub-Recursos" msgid "Clear Inheritance" msgstr "Limpiar Herencia" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Abrir en Editor" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Eliminar Nodo(s)" @@ -6853,10 +6843,6 @@ msgstr "" "Click para mostrar el panel de grupos." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Instancia:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Abrir script" @@ -7288,32 +7274,44 @@ msgid "Object can't provide a length." msgstr "El objeto no puede proveer un largo." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "Eliminar Seleccionados en GridMap" +msgid "Next Plane" +msgstr "Plano siguiente" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "Duplicar Selección en GridMap" +msgid "Previous Plane" +msgstr "Plano anterior" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "Plano:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Piso Siguiente" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Piso Anterior" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Piso:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Mapa de Grilla" +msgid "GridMap Delete Selection" +msgstr "Eliminar Seleccionados en GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "Anclar Vista" +msgid "GridMap Duplicate Selection" +msgstr "Duplicar Selección en GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Piso Anterior" +msgid "Grid Map" +msgstr "Mapa de Grilla" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Piso Siguiente" +msgid "Snap View" +msgstr "Anclar Vista" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7420,6 +7418,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "Sobre el soporte de C#" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "Crear solución en C#" @@ -7435,6 +7437,10 @@ msgstr "Construir Proyecto" msgid "Warnings" msgstr "Advertencias" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7987,6 +7993,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin requiere un nodo hijo ARVRCamera" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(Tiempo Restante: %d:%02d s)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "Ploteando Meshes: " @@ -8185,6 +8199,26 @@ msgstr "Error cargando tipografÃa." msgid "Invalid font size." msgstr "Tamaño de tipografÃa inválido." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Formato de version.txt invalido dentro de plantillas. Revision no es un " +#~ "identificador valido." + +#~ msgid "Can't write file." +#~ msgstr "No se puede escribir el archivo." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "Por favor elegà una carpeta que no contenga un archivo 'project.godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "No se pudo obtener project.godot en la ruta de proyecto." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "No se pudo obtener project.godot en la ruta de proyecto." + #~ msgid "Next" #~ msgstr "Siguiente" diff --git a/editor/translations/extract.py b/editor/translations/extract.py index bbc157788d..4b3f416343 100755 --- a/editor/translations/extract.py +++ b/editor/translations/extract.py @@ -52,11 +52,7 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\\n" """ -print("Updating the editor.pot template...") - -for fname in matches: - - f = open(fname, "rb") +def process_file(f, fname): l = f.readline() lc = 1 @@ -100,12 +96,14 @@ for fname in matches: l = f.readline() lc += 1 - f.close() +print("Updating the editor.pot template...") +for fname in matches: + with open(fname, "rb") as f: + process_file(f, fname) -f = open("editor.pot", "wb") -f.write(main_po) -f.close() +with open("editor.pot", "wb") as f: + f.write(main_po) if (os.name == "posix"): print("Wrapping template at 79 characters for compatibility with Weblate.") diff --git a/editor/translations/fa.po b/editor/translations/fa.po index 3d6b98f49d..7bcbeb15f0 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -2399,12 +2399,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2459,10 +2453,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "ناتوان در نوشتن پرونده." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "دانلود کامل." @@ -3644,15 +3634,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4484,6 +4474,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "گشودن در ویرایشگر" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4774,10 +4780,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "برو به خط" @@ -4791,6 +4793,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5644,11 +5650,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5917,10 +5918,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "پروژه واردشده" @@ -5942,7 +5939,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5962,10 +5961,6 @@ msgid "Rename Project" msgstr "تغییر نام پروژه" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "پروژه بازی جدید" @@ -6665,10 +6660,6 @@ msgstr "زیرمنبع‌ها:" msgid "Clear Inheritance" msgstr "پاک کردن ارث‌بری" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "گشودن در ویرایشگر" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Øذ٠گره(ها)" @@ -6779,10 +6770,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "باز کردن Ùˆ اجرای یک اسکریپت" @@ -7231,33 +7218,47 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "انتخاب شده را ØØ°Ù Ú©Ù†" +msgid "Next Plane" +msgstr "زبانه بعدی" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "انتخاب شده را به دو تا تکثیر Ú©Ù†" +msgid "Previous Plane" +msgstr "زبانه قبلی" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +#, fuzzy +msgid "Previous Floor" +msgstr "زبانه قبلی" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Previous Floor" -msgstr "زبانه قبلی" +msgid "GridMap Delete Selection" +msgstr "انتخاب شده را ØØ°Ù Ú©Ù†" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Duplicate Selection" +msgstr "انتخاب شده را به دو تا تکثیر Ú©Ù†" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7370,6 +7371,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "انتخاب شده را تغییر مقیاس بده" @@ -7387,6 +7392,10 @@ msgstr "پروژه" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7942,6 +7951,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8128,6 +8145,9 @@ msgstr "خطای بارگذاری قلم." msgid "Invalid font size." msgstr "اندازهٔ قلم نامعتبر." +#~ msgid "Can't write file." +#~ msgstr "ناتوان در نوشتن پرونده." + #~ msgid "Next" #~ msgstr "بعدی" diff --git a/editor/translations/fi.po b/editor/translations/fi.po index 8e8636973e..efc69a02bb 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -7,12 +7,13 @@ # Bastian Salmela <bastian.salmela@gmail.com>, 2017. # ekeimaja <ekeimaja@gmail.com>, 2017-2018. # Jarmo Riikonen <amatrelan@gmail.com>, 2017. +# Sami Lehtilä <sami.lehtila@gmail.com>, 2018. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-24 12:10+0000\n" -"Last-Translator: ekeimaja <ekeimaja@gmail.com>\n" +"PO-Revision-Date: 2018-01-31 04:36+0000\n" +"Last-Translator: Sami Lehtilä <sami.lehtila@gmail.com>\n" "Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/" "godot/fi/>\n" "Language: fi\n" @@ -159,9 +160,8 @@ msgid "Linear" msgstr "Lineaarinen" #: editor/animation_editor.cpp editor/plugins/theme_editor_plugin.cpp -#, fuzzy msgid "Constant" -msgstr "Jatkuva" +msgstr "Muuttumaton" #: editor/animation_editor.cpp msgid "In" @@ -192,9 +192,8 @@ msgid "Clean-Up Animation" msgstr "Siivoa animaatio" #: editor/animation_editor.cpp -#, fuzzy msgid "Create NEW track for %s and insert key?" -msgstr "Luo uusi raita %s ja lisää avain?" +msgstr "Luo UUSI raita %lle ja lisää avain?" #: editor/animation_editor.cpp msgid "Create %d NEW tracks and insert keys?" @@ -225,14 +224,12 @@ msgid "Change Anim Len" msgstr "Vaihda animaation pituutta" #: editor/animation_editor.cpp -#, fuzzy msgid "Change Anim Loop" -msgstr "Vaihda animaation toistoa" +msgstr "Vaihda animaation kierto" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Create Typed Value Key" -msgstr "Animaatio: Luo tyyppipohjainen arvo avain" +msgstr "Animaatio: Luo tyypitetty arvoavain" #: editor/animation_editor.cpp msgid "Anim Insert" @@ -243,9 +240,8 @@ msgid "Anim Scale Keys" msgstr "Animaatio: Skaalaa avaimia" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Add Call Track" -msgstr "Animaatio: Lisää kutsu raita" +msgstr "Animaatio: Lisää kutsuraita" #: editor/animation_editor.cpp msgid "Animation zoom." @@ -264,9 +260,8 @@ msgid "Step (s):" msgstr "Askellus:" #: editor/animation_editor.cpp -#, fuzzy msgid "Cursor step snap (in seconds)." -msgstr "Kohdistimen tarttuminen (sekunneissa)." +msgstr "Kohdistimen askelrajoitin (sekunneissa)." #: editor/animation_editor.cpp msgid "Enable/Disable looping in animation." @@ -302,15 +297,15 @@ msgstr "Animaation optimoija" #: editor/animation_editor.cpp msgid "Max. Linear Error:" -msgstr "" +msgstr "Max. lineaarinen virhe:" #: editor/animation_editor.cpp msgid "Max. Angular Error:" -msgstr "" +msgstr "Max. Kulmavirhe:" #: editor/animation_editor.cpp msgid "Max Optimizable Angle:" -msgstr "" +msgstr "Max. Optimoitava kulma:" #: editor/animation_editor.cpp msgid "Optimize" @@ -504,9 +499,8 @@ msgid "Connecting Signal:" msgstr "Yhdistävä signaali:" #: editor/connections_dialog.cpp -#, fuzzy msgid "Disconnect '%s' from '%s'" -msgstr "Yhdistä '%s' '%s':n" +msgstr "Katkaise yhteys '%s' '%s':n" #: editor/connections_dialog.cpp msgid "Connect.." @@ -522,9 +516,8 @@ msgid "Signals" msgstr "Signaalit" #: editor/create_dialog.cpp -#, fuzzy msgid "Change %s Type" -msgstr "Muuta tyyppiä" +msgstr "Muuta %s:n tyyppi" #: editor/create_dialog.cpp editor/project_settings_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -532,9 +525,8 @@ msgid "Change" msgstr "Muuta" #: editor/create_dialog.cpp -#, fuzzy msgid "Create New %s" -msgstr "Luo uusi" +msgstr "Luo uusi %s" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp @@ -648,7 +640,7 @@ msgstr "" #: editor/dependency_editor.cpp #, fuzzy msgid "Cannot remove:" -msgstr "Ei voida poistaa:\n" +msgstr "Ei voida poistaa:" #: editor/dependency_editor.cpp msgid "Error loading:" @@ -2513,14 +2505,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Paketti sisältää viallisen version.txt tiedoston." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Paketti sisältää viallisen version.txt tiedoston. 'Revision' ei ole " -"hyväksytty tunniste." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "version.txt -tiedostoa ei löytynyt." @@ -2578,11 +2562,6 @@ msgstr "Epäonnistui:" #: editor/export_template_manager.cpp #, fuzzy -msgid "Can't write file." -msgstr "Ei voitu kirjoittaa tiedostoa:\n" - -#: editor/export_template_manager.cpp -#, fuzzy msgid "Download Complete." msgstr "Lataa" @@ -3820,15 +3799,15 @@ msgstr "Näytä ruudukko" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show helpers" +msgid "Show Helpers" msgstr "Näytä luut" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Näytä viivaimet" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Näytä apuviivat" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4678,6 +4657,22 @@ msgid "Resource clipboard is empty!" msgstr "Resurssien leikepöytä on tyhjä!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Avaa editorissa" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Tyyppi:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Lataa resurssi" @@ -4975,10 +4970,6 @@ msgid "Toggle Comment" msgstr "Näytä/Piilota kommentit" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Kloonaa alas" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Avaa rivi" @@ -4992,6 +4983,10 @@ msgid "Unfold All Lines" msgstr "Avaa kaikki rivit" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Kloonaa alas" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Täydennä symbooli" @@ -5868,11 +5863,6 @@ msgstr "Välilehti 2" msgid "Tab 3" msgstr "Välilehti 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Tyyppi:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Tietotyyppi:" @@ -6144,10 +6134,6 @@ msgid "Please choose an empty folder." msgstr "Ole hyvä ja valitse 'project.godot' tiedosto." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "Ole hyvä ja valitse hakemisto jossa ei ole 'project.godot' tiedostoa." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Tuotu projekti" @@ -6170,7 +6156,9 @@ msgstr "Virheellinen projektin polku (muuttuiko mikään?)." #: editor/project_manager.cpp #, fuzzy -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "Ei voitu luoda godot.cfg -tiedostoa projektin polkuun." #: editor/project_manager.cpp @@ -6192,11 +6180,6 @@ msgid "Rename Project" msgstr "Nimetä projekti" #: editor/project_manager.cpp -#, fuzzy -msgid "Couldn't get project.godot in the project path." -msgstr "Ei voitu luoda godot.cfg -tiedostoa projektin polkuun." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Uusi peliprojekti" @@ -6911,10 +6894,6 @@ msgstr "Resurssit" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Avaa editorissa" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Poista Node(t)" @@ -7027,10 +7006,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "Seuraava skripti" @@ -7472,13 +7447,26 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "Poista valitut" +msgid "Next Plane" +msgstr "Seuraava välilehti" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "Monista valinta" +msgid "Previous Plane" +msgstr "Edellinen välilehti" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Floor" +msgstr "Edellinen välilehti" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" @@ -7486,22 +7474,23 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Grid Map" -msgstr "Ruudukko" +msgid "GridMap Delete Selection" +msgstr "Poista valitut" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Snap View" -msgstr "Huippunäkymä" +msgid "GridMap Duplicate Selection" +msgstr "Monista valinta" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Previous Floor" -msgstr "Edellinen välilehti" +msgid "Grid Map" +msgstr "Ruudukko" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "" +#, fuzzy +msgid "Snap View" +msgstr "Huippunäkymä" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy @@ -7621,6 +7610,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Luo ääriviivat" @@ -7639,6 +7632,10 @@ msgstr "Uusi projekti" msgid "Warnings" msgstr "Varoitus" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8158,6 +8155,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8334,6 +8339,29 @@ msgstr "Virhe fontin latauksessa." msgid "Invalid font size." msgstr "Virheellinen fonttikoko." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Paketti sisältää viallisen version.txt tiedoston. 'Revision' ei ole " +#~ "hyväksytty tunniste." + +#, fuzzy +#~ msgid "Can't write file." +#~ msgstr "Ei voitu kirjoittaa tiedostoa:\n" + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "Ole hyvä ja valitse hakemisto jossa ei ole 'project.godot' tiedostoa." + +#, fuzzy +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "Ei voitu luoda godot.cfg -tiedostoa projektin polkuun." + +#, fuzzy +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "Ei voitu luoda godot.cfg -tiedostoa projektin polkuun." + #~ msgid "Next" #~ msgstr "Seuraava" diff --git a/editor/translations/fr.po b/editor/translations/fr.po index 7bb65f8056..d9fd96081f 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -8,10 +8,11 @@ # Arthur Templé <tuturtemple@gmail.com>, 2018. # Brice <bbric@free.fr>, 2016. # Chenebel Dorian <LoubiTek54@gmail.com>, 2016-2017. +# Cindy Dallaire <c.dallaire93@gmail.com>, 2018. # derderder77 <derderder77380@gmail.com>, 2016. # finkiki <specialpopol@gmx.fr>, 2016. # Gilles Roudiere <gilles.roudiere@gmail.com>, 2017-2018. -# Hugo Locurcio <hugo.l@openmailbox.org>, 2016-2017. +# Hugo Locurcio <hugo.l@openmailbox.org>, 2016-2018. # Kanabenki <lucien.menassol@gmail.com>, 2017. # keltwookie <keltwookie@protonmail.com>, 2017. # Luc Stepniewski <lior@gradstein.info>, 2017. @@ -35,8 +36,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-01-22 08:08+0000\n" -"Last-Translator: Gilles Roudiere <gilles.roudiere@gmail.com>\n" +"PO-Revision-Date: 2018-02-24 02:36+0000\n" +"Last-Translator: Cindy Dallaire <c.dallaire93@gmail.com>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" "Language: fr\n" @@ -44,7 +45,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 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -1363,14 +1364,14 @@ msgid "Online Tutorials:" msgstr "Tutoriels en ligne :" #: editor/editor_help.cpp -#, fuzzy msgid "" "There are currently no tutorials for this class, you can [color=$color][url=" "$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/" "url][/color]." msgstr "" -"Pas de description disponible pour cette méthode. [color=$color][url=" -"$url]Contribuez[/url][/color] pour nous aider!" +"Pas de tutoriels disponibles pour cette classe, vous pouvez [color=$color]" +"[url=$url]en contribuer un[/url][/color] ou [color=$color][url=$url2]en " +"demander un[/url][/color]." #: editor/editor_help.cpp msgid "Properties" @@ -1424,7 +1425,6 @@ msgid "Clear" msgstr "Effacer" #: editor/editor_log.cpp -#, fuzzy msgid "Clear Output" msgstr "Effacer la sortie" @@ -2497,14 +2497,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Format de version.txt invalide dans les modèles." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Format de version.txt invalide dans les modèles. Revision n'est pas un " -"identifiant valide." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Aucun version.txt n'a été trouvé dans les modèles." @@ -2560,10 +2552,6 @@ msgid "Failed:" msgstr "Échec:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Impossible d'écrire le fichier." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Téléchargement terminé." @@ -2585,7 +2573,7 @@ msgstr "Résolution" #: editor/export_template_manager.cpp msgid "Can't Resolve" -msgstr "Impossible à résoudre." +msgstr "Impossible à résoudre" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -2762,9 +2750,8 @@ msgid "View Owners.." msgstr "Voir les propriétaires…" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicate.." -msgstr "Dupliquer" +msgstr "Dupliquer…" #: editor/filesystem_dock.cpp msgid "Previous Directory" @@ -3129,7 +3116,6 @@ msgid "Directions" msgstr "Directions" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Past" msgstr "Passé" @@ -3754,15 +3740,15 @@ msgid "Show Grid" msgstr "Afficher la grille" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Afficher les aides" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Afficher les règles" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Montrer les guides" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -3826,7 +3812,6 @@ msgid "Ok" msgstr "OK" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Cannot instantiate multiple nodes without root." msgstr "Impossible d'instancier plusieurs nÅ“uds sans nÅ“ud racine." @@ -4088,12 +4073,10 @@ msgid "Create Outline Mesh.." msgstr "Créer un maillage de contour…" #: editor/plugins/mesh_instance_editor_plugin.cpp -#, fuzzy msgid "View UV1" msgstr "Afficher l'UV1" #: editor/plugins/mesh_instance_editor_plugin.cpp -#, fuzzy msgid "View UV2" msgstr "Afficher l'UV2" @@ -4235,9 +4218,8 @@ msgid "Calculating grid size..." msgstr "Calcul de la taille de la grille..." #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Creating heightfield..." -msgstr "Création de la heightmap..." +msgstr "Création de la heightmap…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Marking walkable triangles..." @@ -4264,9 +4246,8 @@ msgid "Creating polymesh..." msgstr "Création d'un maillage de contour…" #: editor/plugins/navigation_mesh_generator.cpp -#, fuzzy msgid "Converting to native navigation mesh..." -msgstr "Conversion en maillage de navigation natif..." +msgstr "Conversion en maillage de navigation natif…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Navigation Mesh Generator Setup:" @@ -4600,6 +4581,22 @@ msgid "Resource clipboard is empty!" msgstr "Le presse-papiers des ressources est vide !" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Ouvrir dans l'éditeur" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Instance :" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Type :" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Charger une ressource" @@ -4612,9 +4609,8 @@ msgid "Paste" msgstr "Coller" #: editor/plugins/resource_preloader_editor_plugin.cpp -#, fuzzy msgid "ResourcePreloader" -msgstr "Chemin de la ressource" +msgstr "ResourcePreloader" #: editor/plugins/script_editor_plugin.cpp msgid "Clear Recent Files" @@ -4887,10 +4883,6 @@ msgid "Toggle Comment" msgstr "Commenter/décommenter" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Cloner en dessous" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Réduire/Développer la ligne" @@ -4903,6 +4895,10 @@ msgid "Unfold All Lines" msgstr "Dérouler toutes les lignes" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Cloner en dessous" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Compléter le symbole" @@ -5581,27 +5577,24 @@ msgid "Insert Empty (After)" msgstr "Insérer vide (après)" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "Move (Before)" -msgstr "Déplacer le(s) nÅ“ud(s)" +msgstr "Déplacer avant" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Move (After)" msgstr "Déplacer (Après)" #: editor/plugins/sprite_frames_editor_plugin.cpp -#, fuzzy msgid "SpriteFrames" -msgstr "Images du sprite" +msgstr "SpriteFrames" #: editor/plugins/style_box_editor_plugin.cpp msgid "StyleBox Preview:" msgstr "Aperçu de la StyleBox :" #: editor/plugins/style_box_editor_plugin.cpp -#, fuzzy msgid "StyleBox" -msgstr "Style Box" +msgstr "StyleBox" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Set Region Rect" @@ -5751,11 +5744,6 @@ msgstr "Onglet 2" msgid "Tab 3" msgstr "Onglet 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Type :" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Type de données :" @@ -5825,9 +5813,8 @@ msgid "Mirror Y" msgstr "Miroir Y" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Paint Tile" -msgstr "Peindre sur la TileMap" +msgstr "Peindre la case" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Pick Tile" @@ -5866,9 +5853,8 @@ msgid "Merge from scene?" msgstr "Fusionner depuis la scène ?" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Tile Set" -msgstr "TileSet…" +msgstr "Ensemble de cases" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create from Scene" @@ -5883,7 +5869,6 @@ msgid "Error" msgstr "Erreur" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Autotiles" msgstr "Coupe automatique" @@ -6024,11 +6009,6 @@ msgid "Please choose an empty folder." msgstr "Veuillez choisir un fichier 'project.godot'." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" -"Veuillez choisir un dossier qui ne contient pas de fichier 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Projet importé" @@ -6039,7 +6019,7 @@ msgstr "Impossible de créer le dossier." #: editor/project_manager.cpp msgid "There is already a folder in this path with the specified name." -msgstr "" +msgstr "Un dossier avec le nom spécifié existe déjà dans ce chemin." #: editor/project_manager.cpp msgid "It would be a good idea to name your project." @@ -6050,9 +6030,12 @@ msgid "Invalid project path (changed anything?)." msgstr "Chemin de projet non valide (avez-vous changé quelque chose ?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +#, fuzzy +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" -"Impossible de trouver le fichier project.godot dans le chemin du projet." +"Impossible de modifier le fichier project.godot dans le chemin du projet." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6072,11 +6055,6 @@ msgid "Rename Project" msgstr "Renommer le projet" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" -"Impossible de trouver le fichier project.godot dans le chemin du projet." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Nouveau projet de jeu" @@ -6790,10 +6768,6 @@ msgstr "Ressources secondaires :" msgid "Clear Inheritance" msgstr "Effacer l'héritage" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Ouvrir dans l'éditeur" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Supprimer nÅ“ud(s)" @@ -6912,10 +6886,6 @@ msgstr "" "Cliquez pour montrer l'arrimage de goupes." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Instance :" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Ouvrir script" @@ -7356,33 +7326,47 @@ msgid "Object can't provide a length." msgstr "L'objet ne peut fournir une longueur." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "Sélection de la supression de GridMap" +#, fuzzy +msgid "Next Plane" +msgstr "Onglet suivant" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "Sélection de la duplication de GridMap" +#, fuzzy +msgid "Previous Plane" +msgstr "Onglet precedent" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "Onglet :" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Étage suivant" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Floor" +msgstr "Onglet précédent" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Étage :" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Grille" +msgid "GridMap Delete Selection" +msgstr "Sélection de la supression de GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "Vue instantanée" +msgid "GridMap Duplicate Selection" +msgstr "Sélection de la duplication de GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "Previous Floor" -msgstr "Onglet précédent" +msgid "Grid Map" +msgstr "Grille" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Étage suivant" +msgid "Snap View" +msgstr "Vue instantanée" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7467,7 +7451,7 @@ msgstr "Création des coutours..." #: modules/mono/editor/godotsharp_editor.cpp msgid "Generating C# project..." -msgstr "" +msgstr "Création du projet C# ..." #: modules/mono/editor/godotsharp_editor.cpp #, fuzzy @@ -7494,6 +7478,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "À propos du support C#" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Créer le contour" @@ -7512,6 +7500,10 @@ msgstr "Projet" msgid "Warnings" msgstr "Avertissement" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8073,6 +8065,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin requiert un nÅ“ud enfant ARVRCamera" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp #, fuzzy msgid "Plotting Meshes: " msgstr "Tracer les maillages" @@ -8273,6 +8273,29 @@ msgstr "Erreur lors du chargement de la police." msgid "Invalid font size." msgstr "Taille de police invalide." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Format de version.txt invalide dans les modèles. Revision n'est pas un " +#~ "identifiant valide." + +#~ msgid "Can't write file." +#~ msgstr "Impossible d'écrire le fichier." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "Veuillez choisir un dossier qui ne contient pas de fichier 'project." +#~ "godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "" +#~ "Impossible de trouver le fichier project.godot dans le chemin du projet." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "" +#~ "Impossible de trouver le fichier project.godot dans le chemin du projet." + #~ msgid "Next" #~ msgstr "Suivant" diff --git a/editor/translations/he.po b/editor/translations/he.po index 57ec12e002..a5f727b8ee 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -10,15 +10,16 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-25 22:27+0000\n" +"PO-Revision-Date: 2018-02-22 12:37+0000\n" "Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n" "Language-Team: Hebrew <https://hosted.weblate.org/projects/godot-engine/" "godot/he/>\n" "Language: he\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.19-dev\n" +"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && " +"n % 10 == 0) ? 2 : 3));\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -70,7 +71,7 @@ msgstr "" #: editor/animation_editor.cpp msgid "Set Transitions to:" -msgstr "" +msgstr "הגדרת ×ž×¢×‘×¨×•× ×™× ×ל:" #: editor/animation_editor.cpp msgid "Anim Track Rename" @@ -143,11 +144,11 @@ msgstr "" #: editor/animation_editor.cpp msgid "Goto Next Step" -msgstr "" +msgstr "מעבר לצעד הב×" #: editor/animation_editor.cpp msgid "Goto Prev Step" -msgstr "" +msgstr "מעבר לצעד הקוד×" #: editor/animation_editor.cpp editor/plugins/curve_editor_plugin.cpp #: editor/property_editor.cpp @@ -192,7 +193,7 @@ msgstr "" #: editor/animation_editor.cpp msgid "Create %d NEW tracks and insert keys?" -msgstr "" +msgstr "ליצור %d רצועות חדשות ×•×œ×”×›× ×™×¡ מפתחות?" #: editor/animation_editor.cpp editor/create_dialog.cpp #: editor/editor_audio_buses.cpp editor/plugins/abstract_polygon_2d_editor.cpp @@ -240,7 +241,7 @@ msgstr "" #: editor/animation_editor.cpp msgid "Animation zoom." -msgstr "" +msgstr "תקריב ×”× ×¤×©×”." #: editor/animation_editor.cpp msgid "Length (s):" @@ -2373,74 +2374,64 @@ msgid "Invalid version.txt format inside templates." msgstr "×ª×‘× ×™×ª ×”Ö¾version.txt שגויה בתוך ×”×ª×‘× ×™×•×ª." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." -msgstr "" +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" -msgstr "" +msgstr "×ª×‘× ×™×•×ª ×”×™×™×¦×•× ×ž×—×•×œ×¦×•×ª" #: editor/export_template_manager.cpp msgid "Importing:" -msgstr "" +msgstr "ייבו×:" #: editor/export_template_manager.cpp msgid "" "No download links found for this version. Direct download is only available " "for official releases." -msgstr "" +msgstr "×œ× × ×ž×¦×ו קישורי הורדה לגרסה זו. הורדה ישירה ×–×ž×™× ×” רק במהדורות הרשמיות." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't resolve." -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ לפתור." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't connect." -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ להתחבר." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "No response." -msgstr "" +msgstr "×ין תגובה." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request Failed." -msgstr "" +msgstr "הבקשה × ×›×©×œ×”." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Redirect Loop." -msgstr "" +msgstr "לול×ת ×”×¤× ×™×•×ª." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed:" -msgstr "" - -#: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" +msgstr "× ×›×©×œ:" #: editor/export_template_manager.cpp msgid "Download Complete." -msgstr "" +msgstr "ההורדה הושלמה." #: editor/export_template_manager.cpp msgid "Error requesting url: " -msgstr "" +msgstr "שגי××” בבקשת כתובת: " #: editor/export_template_manager.cpp msgid "Connecting to Mirror.." @@ -2448,205 +2439,206 @@ msgstr "" #: editor/export_template_manager.cpp msgid "Disconnected" -msgstr "" +msgstr "×ž× ×•×ª×§" #: editor/export_template_manager.cpp msgid "Resolving" -msgstr "" +msgstr "פותר" #: editor/export_template_manager.cpp msgid "Can't Resolve" -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ לפתור" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Connecting.." -msgstr "" +msgstr "מתבצעת התחברות…" #: editor/export_template_manager.cpp msgid "Can't Connect" -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ להתחבר" #: editor/export_template_manager.cpp msgid "Connected" -msgstr "" +msgstr "מחובר" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Requesting.." -msgstr "" +msgstr "מוגשת בקשה…" #: editor/export_template_manager.cpp msgid "Downloading" -msgstr "" +msgstr "מתבצעת הורדה" #: editor/export_template_manager.cpp msgid "Connection Error" -msgstr "" +msgstr "שגי×ת חיבור" #: editor/export_template_manager.cpp msgid "SSL Handshake Error" -msgstr "" +msgstr "שגי×ת לחיצת יד SSL" #: editor/export_template_manager.cpp msgid "Current Version:" -msgstr "" +msgstr "גרסה × ×•×›×—×™×ª:" #: editor/export_template_manager.cpp msgid "Installed Versions:" -msgstr "" +msgstr "גרס×ות ×ž×•×ª×§× ×•×ª:" #: editor/export_template_manager.cpp msgid "Install From File" -msgstr "" +msgstr "×”×ª×§× ×” מקובץ" #: editor/export_template_manager.cpp msgid "Remove Template" -msgstr "" +msgstr "הסרת ×ª×‘× ×™×ª" #: editor/export_template_manager.cpp msgid "Select template file" -msgstr "" +msgstr "בחירת קובץ ×ª×‘× ×™×ª" #: editor/export_template_manager.cpp msgid "Export Template Manager" -msgstr "" +msgstr "×ž× ×”×œ ×™×™×¦×•× ×ª×‘× ×™×•×ª" #: editor/export_template_manager.cpp msgid "Download Templates" -msgstr "" +msgstr "הורדת ×ª×‘× ×™×•×ª" #: editor/export_template_manager.cpp msgid "Select mirror from list: " -msgstr "" +msgstr "בחירת ×תר מר××” מהרשימה: " #: editor/file_type_cache.cpp msgid "Can't open file_type_cache.cch for writing, not saving file type cache!" msgstr "" +"×œ× × ×™×ª×Ÿ לפתוח ×ת file_type_cache.cch לכתיבה, מטמון סוג ×”×§×‘×¦×™× ×œ× ×™×™×©×ž×¨!" #: editor/filesystem_dock.cpp msgid "Cannot navigate to '%s' as it has not been found in the file system!" -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ ×œ× ×•×•×˜ ×ל ‚%s’ כיוון ×©×œ× × ×ž×¦× ×‘×ž×¢×¨×›×ª הקבצי×!" #: editor/filesystem_dock.cpp msgid "View items as a grid of thumbnails" -msgstr "" +msgstr "צפייה ×‘×¤×¨×™×˜×™× ×›×¨×©×ª של ×ª×ž×•× ×•×ª ממוזערות" #: editor/filesystem_dock.cpp msgid "View items as a list" -msgstr "" +msgstr "הצגת ×¤×¨×™×˜×™× ×›×¨×©×™×ž×”" #: editor/filesystem_dock.cpp msgid "Status: Import of file failed. Please fix file and reimport manually." -msgstr "" +msgstr "מצב: ×™×™×‘×•× ×”×§×•×‘×¥ × ×›×©×œ. × × ×œ×ª×§×Ÿ ×ת הקובץ ×•×œ×™×™×‘× ×ž×—×“×© ×™×“× ×™×ª." #: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ להעביר/×œ×©× ×•×ª ×©× ×œ×ž×§×•×¨ של מש×בי×." #: editor/filesystem_dock.cpp msgid "Cannot move a folder into itself." -msgstr "" +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:" -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ לעדכן ×ת התלויות:" #: editor/filesystem_dock.cpp msgid "No name provided" -msgstr "" +msgstr "×œ× ×¦×•×™×Ÿ ש×" #: editor/filesystem_dock.cpp msgid "Provided name contains invalid characters" -msgstr "" +msgstr "×”×©× ×©×¡×•×¤×§ מכיל ×ª×•×•×™× ×©×’×•×™×™×" #: editor/filesystem_dock.cpp msgid "No name provided." -msgstr "" +msgstr "×œ× ×¦×•×™×Ÿ ש×." #: editor/filesystem_dock.cpp msgid "Name contains invalid characters." -msgstr "" +msgstr "×”×©× ×ž×›×™×œ ×ª×•×•×™× ×©×’×•×™×™×." #: editor/filesystem_dock.cpp msgid "A file or folder with this name already exists." -msgstr "" +msgstr "כבר ×§×™×™×ž×™× ×§×•×‘×¥ ×ו תיקייה ×‘×©× ×”×–×”." #: editor/filesystem_dock.cpp msgid "Renaming file:" -msgstr "" +msgstr "×©×™× ×•×™ ×©× ×”×§×•×‘×¥:" #: editor/filesystem_dock.cpp msgid "Renaming folder:" -msgstr "" +msgstr "×©×™× ×•×™ ×©× ×”×ª×™×§×™×™×”:" #: editor/filesystem_dock.cpp msgid "Duplicating file:" -msgstr "" +msgstr "קובץ משוכפל:" #: editor/filesystem_dock.cpp msgid "Duplicating folder:" -msgstr "" +msgstr "תיקייה משוכפלת:" #: editor/filesystem_dock.cpp msgid "Expand all" -msgstr "" +msgstr "להרחיב הכול" #: editor/filesystem_dock.cpp msgid "Collapse all" -msgstr "" +msgstr "×œ×¦×ž×¦× ×”×›×•×œ" #: editor/filesystem_dock.cpp msgid "Rename.." -msgstr "" +msgstr "×©×™× ×•×™ ש×…" #: editor/filesystem_dock.cpp msgid "Move To.." -msgstr "" +msgstr "העברה ×ל…" #: editor/filesystem_dock.cpp msgid "Open Scene(s)" -msgstr "" +msgstr "פתיחת ×¡×¦× ×•×ª" #: editor/filesystem_dock.cpp msgid "Instance" -msgstr "" +msgstr "עותק" #: editor/filesystem_dock.cpp msgid "Edit Dependencies.." -msgstr "" +msgstr "עריכת תלויות…" #: editor/filesystem_dock.cpp msgid "View Owners.." -msgstr "" +msgstr "צפייה בבעלי×…" #: editor/filesystem_dock.cpp msgid "Duplicate.." -msgstr "" +msgstr "שכפול…" #: editor/filesystem_dock.cpp msgid "Previous Directory" -msgstr "" +msgstr "התיקייה הקודמת" #: editor/filesystem_dock.cpp msgid "Next Directory" -msgstr "" +msgstr "התיקייה הב××”" #: editor/filesystem_dock.cpp msgid "Re-Scan Filesystem" -msgstr "" +msgstr "סריקת מערכת ×”×§×‘×¦×™× ×ž×—×“×©" #: editor/filesystem_dock.cpp msgid "Toggle folder status as Favorite" -msgstr "" +msgstr "החלפת מצב התיקייה כמועדפת" #: editor/filesystem_dock.cpp msgid "Instance the selected scene(s) as child of the selected node." @@ -2657,76 +2649,78 @@ msgid "" "Scanning Files,\n" "Please Wait.." msgstr "" +"×”×§×‘×¦×™× × ×¡×¨×§×™×,\n" +"× × ×œ×”×ž×ª×™×Ÿâ€¦" #: editor/filesystem_dock.cpp msgid "Move" -msgstr "" +msgstr "העברה" #: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp #: editor/project_manager.cpp msgid "Rename" -msgstr "" +msgstr "×©×™× ×•×™ ש×" #: editor/groups_editor.cpp msgid "Add to Group" -msgstr "" +msgstr "הוספה לקבוצה" #: editor/groups_editor.cpp msgid "Remove from Group" -msgstr "" +msgstr "הסרה מקבוצה" #: editor/import/resource_importer_scene.cpp msgid "Import as Single Scene" -msgstr "" +msgstr "×™×™×‘×•× ×›×¡×¦× ×” בודדת" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Animations" -msgstr "" +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" -msgstr "" +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" -msgstr "" +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" -msgstr "" +msgstr "×™×™×‘×•× ×›×ž×¡×¤×¨ ×¡×¦× ×•×ª" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes+Materials" -msgstr "" +msgstr "×™×™×‘×•× ×›×ž×¡×¤×¨ ×¡×¦× ×•×ª+חומרי×" #: editor/import/resource_importer_scene.cpp #: editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Import Scene" -msgstr "" +msgstr "×™×™×‘×•× ×¡×¦× ×”" #: editor/import/resource_importer_scene.cpp msgid "Importing Scene.." -msgstr "" +msgstr "×¡×¦× ×” מיוב×ת…" #: editor/import/resource_importer_scene.cpp msgid "Generating Lightmaps" -msgstr "" +msgstr "× ×•×¦×¨×•×ª מפות ת×ורה" #: editor/import/resource_importer_scene.cpp msgid "Generating for Mesh: " @@ -2734,11 +2728,11 @@ msgstr "" #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script.." -msgstr "" +msgstr "מופעל סקריפט מות×× ×ישית…" #: editor/import/resource_importer_scene.cpp msgid "Couldn't load post-import script:" -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ לטעון סקריפט של×חר ייבו×:" #: editor/import/resource_importer_scene.cpp msgid "Invalid/broken script for post-import (check console):" @@ -2750,31 +2744,31 @@ msgstr "" #: editor/import/resource_importer_scene.cpp msgid "Saving.." -msgstr "" +msgstr "שמירה…" #: editor/import_dock.cpp msgid "Set as Default for '%s'" -msgstr "" +msgstr "הגדרה כבררת מחדל עבור ‚%s’" #: editor/import_dock.cpp msgid "Clear Default for '%s'" -msgstr "" +msgstr "מחיקת בררת מחדל עבור ‚%s’" #: editor/import_dock.cpp msgid " Files" -msgstr "" +msgstr " קבצי×" #: editor/import_dock.cpp msgid "Import As:" -msgstr "" +msgstr "×™×™×‘×•× ×‘×ª×•×¨:" #: editor/import_dock.cpp editor/property_editor.cpp msgid "Preset.." -msgstr "" +msgstr "ערכה מוגדרת…" #: editor/import_dock.cpp msgid "Reimport" -msgstr "" +msgstr "×™×™×‘×•× ×ž×—×“×©" #: editor/multi_node_edit.cpp msgid "MultiNode Set" @@ -2782,40 +2776,40 @@ msgstr "" #: editor/node_dock.cpp msgid "Groups" -msgstr "" +msgstr "קבוצות" #: editor/node_dock.cpp msgid "Select a Node to edit Signals and Groups." -msgstr "" +msgstr "יש לבחור מפרק כדי לערוך ×ותות וקבוצות." #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Create Poly" -msgstr "" +msgstr "יצירת מצולע" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/collision_polygon_editor_plugin.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Edit Poly" -msgstr "" +msgstr "עריכת מצולע" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Insert Point" -msgstr "" +msgstr "הוספת × ×§×•×“×”" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/collision_polygon_editor_plugin.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Edit Poly (Remove Point)" -msgstr "" +msgstr "עריכת מצולע (הסרת × ×§×•×“×”)" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Remove Poly And Point" -msgstr "" +msgstr "הסרת מצולע ×•× ×§×•×“×”" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Create a new polygon from scratch" -msgstr "" +msgstr "יצירת מצולע חדש מ×פס" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "" @@ -2827,7 +2821,7 @@ msgstr "" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Delete points" -msgstr "" +msgstr "מחיקת × ×§×•×“×•×ª" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Toggle Autoplay" @@ -2835,7 +2829,7 @@ msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Animation Name:" -msgstr "" +msgstr "×©× ×”× ×¤×©×” חדשה:" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Anim" @@ -3597,15 +3591,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4294,7 +4288,7 @@ msgstr "" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Delete Point" -msgstr "" +msgstr "מחיקת × ×§×•×“×”" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp @@ -4319,11 +4313,11 @@ msgstr "" #: editor/plugins/path_editor_plugin.cpp msgid "Split Path" -msgstr "" +msgstr "פיצול × ×ª×™×‘" #: editor/plugins/path_editor_plugin.cpp msgid "Remove Path Point" -msgstr "" +msgstr "הסרת × ×§×•×“×” ×‘× ×ª×™×‘" #: editor/plugins/path_editor_plugin.cpp msgid "Remove Out-Control Point" @@ -4347,31 +4341,31 @@ msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Move Point" -msgstr "" +msgstr "הזזת × ×§×•×“×”" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Ctrl: Rotate" -msgstr "" +msgstr "Ctrl: הטייה" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift: Move All" -msgstr "" +msgstr "Shift: הזזת הכול" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift+Ctrl: Scale" -msgstr "" +msgstr "Shift+Ctrl: ×§× ×” מידה" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Move Polygon" -msgstr "" +msgstr "הזזת מצולע" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Rotate Polygon" -msgstr "" +msgstr "הטיית מצולע" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Scale Polygon" -msgstr "" +msgstr "×©×™× ×•×™ ×§× ×” מידה של מצולע" #: editor/plugins/polygon_2d_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp @@ -4379,7 +4373,7 @@ msgstr "" #: editor/project_settings_editor.cpp editor/property_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Edit" -msgstr "" +msgstr "עריכה" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Polygon->UV" @@ -4396,48 +4390,64 @@ msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap" -msgstr "" +msgstr "הצמדה" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Enable Snap" -msgstr "" +msgstr "הפעלת הצמדה" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid" -msgstr "" +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" -msgstr "" +msgstr "הוספת מש×ב" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Rename Resource" -msgstr "" +msgstr "×©×™× ×•×™ ×©× ×ž×©×ב" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Delete Resource" -msgstr "" +msgstr "מחיקת מש×ב" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Resource clipboard is empty!" +msgstr "לוח גזירי המש××‘×™× ×¨×™×§!" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" -msgstr "" +msgstr "×˜×¢×™× ×ª מש×ב" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Paste" -msgstr "" +msgstr "הדבקה" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ResourcePreloader" @@ -4445,35 +4455,35 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Clear Recent Files" -msgstr "" +msgstr "מחיקת ×§×‘×¦×™× ××—×¨×•× ×™×" #: editor/plugins/script_editor_plugin.cpp msgid "Close and save changes?" -msgstr "" +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 "Error importing theme" -msgstr "" +msgstr "שגי××” ×‘×™×™×‘×•× ×¢×¨×›×ª ×”× ×•×©×" #: editor/plugins/script_editor_plugin.cpp msgid "Error importing" -msgstr "" +msgstr "שגי××” בייבו×" #: editor/plugins/script_editor_plugin.cpp msgid "Import Theme" -msgstr "" +msgstr "×™×™×‘×•× ×¢×¨×›×ª עיצוב" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme As.." -msgstr "" +msgstr "שמירת ערכת עיצוב בש×…" #: editor/plugins/script_editor_plugin.cpp msgid " Class Reference" @@ -4481,134 +4491,134 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Sort" -msgstr "" +msgstr "מיון" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Move Up" -msgstr "" +msgstr "העברה למעלה" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Move Down" -msgstr "" +msgstr "העברה למטה" #: editor/plugins/script_editor_plugin.cpp msgid "Next script" -msgstr "" +msgstr "הסקריפט הב×" #: editor/plugins/script_editor_plugin.cpp msgid "Previous script" -msgstr "" +msgstr "הסקריפט הקוד×" #: editor/plugins/script_editor_plugin.cpp msgid "File" -msgstr "" +msgstr "קובץ" #: editor/plugins/script_editor_plugin.cpp msgid "New" -msgstr "" +msgstr "חדש" #: editor/plugins/script_editor_plugin.cpp msgid "Save All" -msgstr "" +msgstr "לשמור הכול" #: editor/plugins/script_editor_plugin.cpp msgid "Soft Reload Script" -msgstr "" +msgstr "סקריפט ×¨×¢× ×•×Ÿ רך" #: editor/plugins/script_editor_plugin.cpp msgid "Copy Script Path" -msgstr "" +msgstr "העתקת × ×ª×™×‘ הסקריפט" #: editor/plugins/script_editor_plugin.cpp msgid "Show In File System" -msgstr "" +msgstr "הצגה במערכת הקבצי×" #: editor/plugins/script_editor_plugin.cpp msgid "History Prev" -msgstr "" +msgstr "×”×§×•×“× ×‘×”×™×¡×˜×•×¨×™×”" #: editor/plugins/script_editor_plugin.cpp msgid "History Next" -msgstr "" +msgstr "×”×‘× ×‘×”×™×¡×˜×•×¨×™×”" #: editor/plugins/script_editor_plugin.cpp msgid "Reload Theme" -msgstr "" +msgstr "×¨×¢× ×•×Ÿ ערכת העיצוב" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme" -msgstr "" +msgstr "שמירת ערכת העיצוב" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme As" -msgstr "" +msgstr "שמירת ערכת העיצוב בש×" #: editor/plugins/script_editor_plugin.cpp msgid "Close Docs" -msgstr "" +msgstr "סגירת מסמכי×" #: editor/plugins/script_editor_plugin.cpp msgid "Close All" -msgstr "" +msgstr "לסגור הכול" #: editor/plugins/script_editor_plugin.cpp msgid "Close Other Tabs" -msgstr "" +msgstr "לסגור ×œ×©×•× ×™×•×ª ×חרות" #: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp msgid "Run" -msgstr "" +msgstr "הרצה" #: editor/plugins/script_editor_plugin.cpp msgid "Toggle Scripts Panel" -msgstr "" +msgstr "החלפת תצוגת ×—×œ×•× ×™×ª סקריפטי×" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find.." -msgstr "" +msgstr "×יתור…" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find Next" -msgstr "" +msgstr "×יתור הב×" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Step Over" -msgstr "" +msgstr "לצעוד מעל" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Step Into" -msgstr "" +msgstr "לצעוד לתוך" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Break" -msgstr "" +msgstr "עצירה" #: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp #: editor/script_editor_debugger.cpp msgid "Continue" -msgstr "" +msgstr "המשך" #: editor/plugins/script_editor_plugin.cpp msgid "Keep Debugger Open" -msgstr "" +msgstr "להש×יר ×ת ×ž× ×¤×” השגי×ות פתוח" #: editor/plugins/script_editor_plugin.cpp msgid "Debug with external editor" -msgstr "" +msgstr "× ×™×¤×•×™ שגי×ות ×¢× ×¢×•×¨×š ×—×™×¦×•× ×™" #: editor/plugins/script_editor_plugin.cpp msgid "Open Godot online documentation" -msgstr "" +msgstr "פתיחת התיעוד המקוון של Godot" #: editor/plugins/script_editor_plugin.cpp msgid "Search the class hierarchy." -msgstr "" +msgstr "חיפוש בהיררכיית המחלקות." #: editor/plugins/script_editor_plugin.cpp msgid "Search the reference documentation." @@ -4616,114 +4626,116 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Go to previous edited document." -msgstr "" +msgstr "מעבר למסמך ×”×§×•×“× ×©× ×¢×¨×š." #: editor/plugins/script_editor_plugin.cpp msgid "Go to next edited document." -msgstr "" +msgstr "מעבר למסמך ×”×‘× ×©× ×¢×¨×š." #: editor/plugins/script_editor_plugin.cpp msgid "Discard" -msgstr "" +msgstr "התעלמות" #: editor/plugins/script_editor_plugin.cpp msgid "Create Script" -msgstr "" +msgstr "יצירת סקריפט" #: editor/plugins/script_editor_plugin.cpp msgid "" "The following files are newer on disk.\n" "What action should be taken?:" msgstr "" +"×”×§×‘×¦×™× ×”×‘××™× ×”× ×—×“×©×™× ×‘×›×•× ×Ÿ.\n" +"ב×ילו פעולות ×œ× ×§×•×˜?:" #: editor/plugins/script_editor_plugin.cpp msgid "Reload" -msgstr "" +msgstr "×¨×¢× ×•×Ÿ" #: editor/plugins/script_editor_plugin.cpp msgid "Resave" -msgstr "" +msgstr "שמירה מחדש" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Debugger" -msgstr "" +msgstr "×ž× ×¤×” שגי×ות" #: editor/plugins/script_editor_plugin.cpp msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" -msgstr "" +msgstr "× ×™×ª×Ÿ לערוך ×¡×§×¨×™×¤×˜×™× ×ž×•×‘× ×™× ×¨×§ ×›×שר ×”×¡×¦× ×” ××œ×™×”× ×”× ×©×™×™×›×™× × ×˜×¢× ×”" #: editor/plugins/script_text_editor.cpp msgid "Only resources from filesystem can be dropped." -msgstr "" +msgstr "× ×™×ª×Ÿ להשמיט מש××‘×™× ×ž×ž×¢×¨×›×ª ×”×§×‘×¦×™× ×‘×œ×‘×“." #: editor/plugins/script_text_editor.cpp msgid "Pick Color" -msgstr "" +msgstr "בחירת צבע" #: editor/plugins/script_text_editor.cpp msgid "Convert Case" -msgstr "" +msgstr "החלפת מצב רשיות" #: editor/plugins/script_text_editor.cpp msgid "Uppercase" -msgstr "" +msgstr "×ותיות גדולות" #: editor/plugins/script_text_editor.cpp msgid "Lowercase" -msgstr "" +msgstr "×ותיות ×§×˜× ×•×ª" #: editor/plugins/script_text_editor.cpp msgid "Capitalize" -msgstr "" +msgstr "הגדלת ×ות ר××©×•× ×”" #: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp msgid "Cut" -msgstr "" +msgstr "גזירה" #: editor/plugins/script_text_editor.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Copy" -msgstr "" +msgstr "העתקה" #: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp msgid "Select All" -msgstr "" +msgstr "לבחור הכול" #: editor/plugins/script_text_editor.cpp msgid "Delete Line" -msgstr "" +msgstr "מחיקת שורה" #: editor/plugins/script_text_editor.cpp msgid "Indent Left" -msgstr "" +msgstr "×”×–×—×” משמ×ל" #: editor/plugins/script_text_editor.cpp msgid "Indent Right" -msgstr "" +msgstr "×”×–×—×” מימין" #: editor/plugins/script_text_editor.cpp msgid "Toggle Comment" -msgstr "" - -#: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" +msgstr "החלפת מצב הערה" #: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" -msgstr "" +msgstr "צמצו×/הרחבה של שורה" #: editor/plugins/script_text_editor.cpp msgid "Fold All Lines" -msgstr "" +msgstr "×¦×ž×¦×•× ×›×œ השורות" #: editor/plugins/script_text_editor.cpp msgid "Unfold All Lines" -msgstr "" +msgstr "הרחבת כל השורות" + +#: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "לשכפל למטה" #: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" @@ -4735,60 +4747,60 @@ msgstr "" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent To Spaces" -msgstr "" +msgstr "המרת הזחות לרווחי×" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent To Tabs" -msgstr "" +msgstr "המרת הזחות לט×בי×" #: editor/plugins/script_text_editor.cpp msgid "Auto Indent" -msgstr "" +msgstr "×”×–×—×” ×וטומטית" #: editor/plugins/script_text_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Toggle Breakpoint" -msgstr "" +msgstr "החלפת מצב × ×§×•×“×ª עצירה" #: editor/plugins/script_text_editor.cpp msgid "Remove All Breakpoints" -msgstr "" +msgstr "הסרת כל × ×§×•×“×•×ª העצירה" #: editor/plugins/script_text_editor.cpp msgid "Goto Next Breakpoint" -msgstr "" +msgstr "מעבר ×œ× ×§×•×“×ª העצירה הב××”" #: editor/plugins/script_text_editor.cpp msgid "Goto Previous Breakpoint" -msgstr "" +msgstr "מעבר ×œ× ×§×•×“×ª העצירה הקודמת" #: editor/plugins/script_text_editor.cpp msgid "Convert To Uppercase" -msgstr "" +msgstr "המרה ל×ותיות גדולות" #: editor/plugins/script_text_editor.cpp msgid "Convert To Lowercase" -msgstr "" +msgstr "המרה ל×ותיות ×§×˜× ×•×ª" #: editor/plugins/script_text_editor.cpp msgid "Find Previous" -msgstr "" +msgstr "×יתור הקוד×" #: editor/plugins/script_text_editor.cpp msgid "Replace.." -msgstr "" +msgstr "החלפה…" #: editor/plugins/script_text_editor.cpp msgid "Goto Function.." -msgstr "" +msgstr "מעבר ×œ×¤×•× ×§×¦×™×”â€¦" #: editor/plugins/script_text_editor.cpp msgid "Goto Line.." -msgstr "" +msgstr "מעבר לשורה…" #: editor/plugins/script_text_editor.cpp msgid "Contextual Help" -msgstr "" +msgstr "עזרה תלוית הקשר" #: editor/plugins/shader_editor_plugin.cpp msgid "Shader" @@ -4848,7 +4860,7 @@ msgstr "" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Change Default Value" -msgstr "" +msgstr "×©×™× ×•×™ ערך בררת המחדל" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Change XForm Uniform" @@ -4864,7 +4876,7 @@ msgstr "" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Change Comment" -msgstr "" +msgstr "×©×™× ×•×™ הערה" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Add/Remove to Color Ramp" @@ -4880,7 +4892,7 @@ msgstr "" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Change Input Name" -msgstr "" +msgstr "×©×™× ×•×™ ×©× ×§×œ×˜" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Connect Graph Nodes" @@ -4912,7 +4924,7 @@ msgstr "" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Error: Missing Input Connections" -msgstr "" +msgstr "שגי××”: ×—×¡×¨×™× ×—×™×‘×•×¨×™ קלט" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Add Shader Graph Node" @@ -4956,7 +4968,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotating %s degrees." -msgstr "" +msgstr "הטיה של %s מעלות." #: editor/plugins/spatial_editor_plugin.cpp msgid "Keying is disabled (no key inserted)." @@ -4972,7 +4984,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Material Changes" -msgstr "" +msgstr "×©×™× ×•×™×™ חומרי×" #: editor/plugins/spatial_editor_plugin.cpp msgid "Shader Changes" @@ -4988,7 +5000,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Vertices" -msgstr "" +msgstr "קודקודי×" #: editor/plugins/spatial_editor_plugin.cpp msgid "FPS" @@ -4996,55 +5008,55 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Top View." -msgstr "" +msgstr "מבט על." #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View." -msgstr "" +msgstr "מבט מתחת." #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom" -msgstr "" +msgstr "מתחת" #: editor/plugins/spatial_editor_plugin.cpp msgid "Left View." -msgstr "" +msgstr "מבט משמ×ל." #: editor/plugins/spatial_editor_plugin.cpp msgid "Left" -msgstr "" +msgstr "שמ×ל" #: editor/plugins/spatial_editor_plugin.cpp msgid "Right View." -msgstr "" +msgstr "מבט מימין." #: editor/plugins/spatial_editor_plugin.cpp msgid "Right" -msgstr "" +msgstr "ימין" #: editor/plugins/spatial_editor_plugin.cpp msgid "Front View." -msgstr "" +msgstr "מבט קדמי." #: editor/plugins/spatial_editor_plugin.cpp msgid "Front" -msgstr "" +msgstr "קדמי" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rear View." -msgstr "" +msgstr "מבט ×חורי." #: editor/plugins/spatial_editor_plugin.cpp msgid "Rear" -msgstr "" +msgstr "×חורי" #: editor/plugins/spatial_editor_plugin.cpp msgid "Align with view" -msgstr "" +msgstr "יישור ×¢× ×”×ª×¦×•×’×”" #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "OK :(" -msgstr "" +msgstr "בסדר :(" #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "No parent to instance a child at." @@ -5056,15 +5068,15 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Display Normal" -msgstr "" +msgstr "הצגה × ×•×¨×ž×œ×™×ª" #: editor/plugins/spatial_editor_plugin.cpp msgid "Display Wireframe" -msgstr "" +msgstr "הצגת מסגרת קווי×" #: editor/plugins/spatial_editor_plugin.cpp msgid "Display Overdraw" -msgstr "" +msgstr "הצגת שכבת פירוט" #: editor/plugins/spatial_editor_plugin.cpp msgid "Display Unshaded" @@ -5072,7 +5084,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Environment" -msgstr "" +msgstr "צפייה בסביבה" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Gizmos" @@ -5080,7 +5092,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Information" -msgstr "" +msgstr "הצגת מידע" #: editor/plugins/spatial_editor_plugin.cpp msgid "View FPS" @@ -5088,11 +5100,11 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Half Resolution" -msgstr "" +msgstr "חצי רזולוציה" #: editor/plugins/spatial_editor_plugin.cpp msgid "Audio Listener" -msgstr "" +msgstr "מ×זין לשמע" #: editor/plugins/spatial_editor_plugin.cpp msgid "Doppler Enable" @@ -5132,7 +5144,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Select Mode (Q)" -msgstr "" +msgstr "בחירת מצב (Q)" #: editor/plugins/spatial_editor_plugin.cpp msgid "" @@ -5140,58 +5152,61 @@ msgid "" "Alt+Drag: Move\n" "Alt+RMB: Depth list selection" msgstr "" +"גרירה: הטיה\n" +"Alt+גרירה: ×”×–×–×”\n" +"Alt+כפתור ×™×ž× ×™: בחירת רשימת עומק" #: editor/plugins/spatial_editor_plugin.cpp msgid "Move Mode (W)" -msgstr "" +msgstr "מצב ×”×–×–×” (W)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Mode (E)" -msgstr "" +msgstr "מצב הטיה (E)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale Mode (R)" -msgstr "" +msgstr "מצב ×©×™× ×•×™ ×§× ×” מידה (R)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Local Coords" -msgstr "" +msgstr "× ×§×•×“×•×ª ציון מקומיות" #: editor/plugins/spatial_editor_plugin.cpp msgid "Local Space Mode (%s)" -msgstr "" +msgstr "מצב מרחב מקומי (%s)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Mode (%s)" -msgstr "" +msgstr "מצב הצמדה (%s)" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" -msgstr "" +msgstr "מבט תחתי" #: editor/plugins/spatial_editor_plugin.cpp msgid "Top View" -msgstr "" +msgstr "מבט על" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rear View" -msgstr "" +msgstr "מבט ×חורי" #: editor/plugins/spatial_editor_plugin.cpp msgid "Front View" -msgstr "" +msgstr "מבט קדמי" #: editor/plugins/spatial_editor_plugin.cpp msgid "Left View" -msgstr "" +msgstr "מבט שמ×לי" #: editor/plugins/spatial_editor_plugin.cpp msgid "Right View" -msgstr "" +msgstr "מבט ×™×ž× ×™" #: editor/plugins/spatial_editor_plugin.cpp msgid "Switch Perspective/Orthogonal view" -msgstr "" +msgstr "החלפה בין תצוגה פרספקטיבה/×× ×›×™×ª" #: editor/plugins/spatial_editor_plugin.cpp msgid "Insert Animation Key" @@ -5203,7 +5218,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" -msgstr "" +msgstr "בחירת מיקוד" #: editor/plugins/spatial_editor_plugin.cpp msgid "Align Selection With View" @@ -5227,15 +5242,15 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Toggle Freelook" -msgstr "" +msgstr "החלפת מצב מבט חופשי" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform" -msgstr "" +msgstr "התמרה" #: editor/plugins/spatial_editor_plugin.cpp msgid "Configure Snap.." -msgstr "" +msgstr "הגדרת הצמדה…" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog.." @@ -5276,7 +5291,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Settings" -msgstr "" +msgstr "הגדרות" #: editor/plugins/spatial_editor_plugin.cpp msgid "Skeleton Gizmo visibility" @@ -5284,7 +5299,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Settings" -msgstr "" +msgstr "הגדרות הצמדה" #: editor/plugins/spatial_editor_plugin.cpp msgid "Translate Snap:" @@ -5324,11 +5339,11 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate (deg.):" -msgstr "" +msgstr "הטיה (מעלות):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale (ratio):" -msgstr "" +msgstr "×©×™× ×•×™ ×§× ×” מידה (יחס):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Type" @@ -5376,19 +5391,19 @@ msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Animations" -msgstr "" +msgstr "×”× ×¤×©×•×ª" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Speed (FPS):" -msgstr "" +msgstr "מהירות (FPS):" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Loop" -msgstr "" +msgstr "לול××”" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Animation Frames" -msgstr "" +msgstr "שקופיות ×”×”× ×¤×©×”" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Insert Empty (Before)" @@ -5566,11 +5581,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5830,10 +5840,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5854,7 +5860,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5874,10 +5882,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6565,10 +6569,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6678,10 +6678,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7104,11 +7100,25 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +#, fuzzy +msgid "Next Plane" +msgstr "×”×œ×©×•× ×™×ª הב××”" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Plane" +msgstr "×”×œ×©×•× ×™×ª הקודמת" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7116,19 +7126,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7145,59 +7155,59 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Edit X Axis" -msgstr "" +msgstr "עריכת ציר X" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Edit Y Axis" -msgstr "" +msgstr "עריכת ציר Y" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Edit Z Axis" -msgstr "" +msgstr "עריכת ציר Z" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Cursor Rotate X" -msgstr "" +msgstr "הטיית מצביע ב־X" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Cursor Rotate Y" -msgstr "" +msgstr "הטיית מצביע ב־Y" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Cursor Rotate Z" -msgstr "" +msgstr "הטיית מצביע ב־Z" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Cursor Back Rotate X" -msgstr "" +msgstr "הטיית מצביע הפוכה ב־X" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Cursor Back Rotate Y" -msgstr "" +msgstr "הטיית מצביע הפוכה ב־Y" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Cursor Back Rotate Z" -msgstr "" +msgstr "הטיית מצביע הפוכה ב־Z" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Cursor Clear Rotation" -msgstr "" +msgstr "מחיקת הטיית מצביע" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Create Area" -msgstr "" +msgstr "יצירת שטח" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Create Exterior Connector" -msgstr "" +msgstr "יצירת מחבר ×—×™×¦×•× ×™" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Erase Area" -msgstr "" +msgstr "מחיקת שטח" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clear Selection" -msgstr "" +msgstr "ביטול הבחירה" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "GridMap Settings" @@ -7205,40 +7215,44 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Pick Distance:" -msgstr "" +msgstr "בחירת מרחק:" #: modules/mono/editor/godotsharp_editor.cpp msgid "Generating solution..." -msgstr "" +msgstr "הפתרון × ×•×¦×¨â€¦" #: modules/mono/editor/godotsharp_editor.cpp msgid "Generating C# project..." -msgstr "" +msgstr "× ×•×¦×¨ ×ž×™×–× C#‎…" #: modules/mono/editor/godotsharp_editor.cpp msgid "Failed to create solution." -msgstr "" +msgstr "יצירת הפתרון × ×›×©×œ×”." #: modules/mono/editor/godotsharp_editor.cpp msgid "Failed to save solution." -msgstr "" +msgstr "שמירת הפתרון × ×›×©×œ×”." #: modules/mono/editor/godotsharp_editor.cpp msgid "Done" -msgstr "" +msgstr "בוצע" #: modules/mono/editor/godotsharp_editor.cpp msgid "Failed to create C# project." -msgstr "" +msgstr "יצירת ×ž×™×–× C#‎ × ×›×©×œ×”." #: modules/mono/editor/godotsharp_editor.cpp msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp -msgid "Create C# solution" +msgid "About C# support" msgstr "" +#: modules/mono/editor/godotsharp_editor.cpp +msgid "Create C# solution" +msgstr "יצירת פתרון C#‎" + #: modules/mono/editor/mono_bottom_panel.cpp msgid "Builds" msgstr "" @@ -7249,6 +7263,10 @@ msgstr "" #: modules/mono/editor/mono_bottom_panel.cpp msgid "Warnings" +msgstr "×זהרות" + +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" msgstr "" #: modules/visual_script/visual_script.cpp @@ -7751,6 +7769,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin דורש מפרק צ××¦× ×ž×¡×•×’ ARVRCamera" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -7912,6 +7938,9 @@ msgstr "שגי××” ×‘×˜×¢×™× ×ª הגופן." msgid "Invalid font size." msgstr "גודל הגופן שגוי." +#~ msgid "Can't write file." +#~ msgstr "×œ× × ×™×ª×Ÿ לכתוב קובץ." + #~ msgid "Next" #~ msgstr "הב×" diff --git a/editor/translations/hi.po b/editor/translations/hi.po index c124727d74..cba5b3059b 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -2405,12 +2405,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2463,10 +2457,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3637,15 +3627,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4468,6 +4458,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4751,10 +4757,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4767,6 +4769,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5607,11 +5613,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5871,10 +5872,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5895,7 +5892,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5915,10 +5914,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6609,10 +6604,6 @@ msgstr "संसाधन" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6722,10 +6713,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7148,11 +7135,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7160,19 +7159,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7280,6 +7279,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "सदसà¥à¤¯à¤¤à¤¾ बनाà¤à¤‚" @@ -7296,6 +7299,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7795,6 +7802,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/hu.po b/editor/translations/hu.po index 9d89e98f7e..3b728caafc 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-20 08:54+0000\n" +"PO-Revision-Date: 2018-02-24 12:37+0000\n" "Last-Translator: Varga Dániel <danikah.danikah@gmail.com>\n" "Language-Team: Hungarian <https://hosted.weblate.org/projects/godot-engine/" "godot/hu/>\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -26,7 +26,7 @@ msgstr "Tiltva" #: editor/animation_editor.cpp msgid "All Selection" -msgstr "Mind kiválasztva" +msgstr "Minden Kiválasztás" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Time" @@ -143,7 +143,7 @@ msgstr "Ãtméretezés A Kurzortól" #: editor/animation_editor.cpp msgid "Goto Next Step" -msgstr "Ugrás A következÅ‘ lépésre" +msgstr "Ugrás A KövetkezÅ‘ Lépésre" #: editor/animation_editor.cpp msgid "Goto Prev Step" @@ -152,7 +152,7 @@ msgstr "Ugrás Az ElÅ‘zÅ‘ Lépésre" #: editor/animation_editor.cpp editor/plugins/curve_editor_plugin.cpp #: editor/property_editor.cpp msgid "Linear" -msgstr "Egyenes irányú" +msgstr "Lineáris" #: editor/animation_editor.cpp editor/plugins/theme_editor_plugin.cpp msgid "Constant" @@ -188,7 +188,7 @@ msgstr "Animáció MegtisztÃtása" #: editor/animation_editor.cpp msgid "Create NEW track for %s and insert key?" -msgstr "Létrehoz ÚJ útvonalat %s -hez és beilleszti a kulcsot?" +msgstr "Létrehoz ÚJ nyomvonalat %s -hez és beilleszti a kulcsot?" #: editor/animation_editor.cpp msgid "Create %d NEW tracks and insert keys?" @@ -208,7 +208,7 @@ msgstr "Animáció Létrehozása És Beillesztése" #: editor/animation_editor.cpp msgid "Anim Insert Track & Key" -msgstr "Animáció Útvonal És Kulcs Beillesztése" +msgstr "Animáció Nyomvonal És Kulcs Beillesztése" #: editor/animation_editor.cpp msgid "Anim Insert Key" @@ -216,7 +216,7 @@ msgstr "Animáció Kulcs Beillesztése" #: editor/animation_editor.cpp msgid "Change Anim Len" -msgstr "Csak Animáció változtatása" +msgstr "Animáció Hossz Változtatása" #: editor/animation_editor.cpp msgid "Change Anim Loop" @@ -426,7 +426,7 @@ msgid "" "Node." msgstr "" "Nem található a cél metódus! Nevezzen meg egy érvényes metódust, vagy " -"csatoljon egy scriptet a cél Node-hoz." +"csatoljon egy szkriptet a cél Node-hoz." #: editor/connections_dialog.cpp msgid "Connect To Node:" @@ -519,7 +519,7 @@ msgstr "%s TÃpusának Megváltoztatása" #: editor/create_dialog.cpp editor/project_settings_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Change" -msgstr "Megváltoztatás" +msgstr "Változtatás" #: editor/create_dialog.cpp msgid "Create New %s" @@ -633,7 +633,6 @@ msgstr "" "EltávolÃtja Å‘ket ennek ellenére? (nem visszavonható)" #: editor/dependency_editor.cpp -#, fuzzy msgid "Cannot remove:" msgstr "Nem eltávolÃtható:" @@ -719,7 +718,7 @@ msgstr "VezetÅ‘ FejlesztÅ‘" #: editor/editor_about.cpp msgid "Project Manager " -msgstr "Projekt Menedzser " +msgstr "Projekt KezelÅ‘ " #: editor/editor_about.cpp msgid "Developers" @@ -828,9 +827,8 @@ msgid "Rename Audio Bus" msgstr "Hangbusz Ãtnevezése" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Change Audio Bus Volume" -msgstr "Tömb értékének megváltoztatása" +msgstr "Hangbusz HangerÅ‘ MódosÃtás" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" @@ -1328,19 +1326,18 @@ msgid "Description" msgstr "LeÃrás" #: editor/editor_help.cpp -#, fuzzy msgid "Online Tutorials:" -msgstr "Online Dokumentáció" +msgstr "Online Oktatóanyagok:" #: editor/editor_help.cpp -#, fuzzy msgid "" "There are currently no tutorials for this class, you can [color=$color][url=" "$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/" "url][/color]." msgstr "" -"Ennek a metódusnak jelenleg nincs leÃrása. SegÃtsen minket azzal, hogy " -"[color=$color][url=$url]hozzájárul eggyel[/url][/color]!" +"Jelenleg nincsenek oktatóanyagok ehhez az osztályhoz. [color=$color][url=" +"$url]Hozzájárulhat eggyel[/url][/color], vagy [color=$color][url=" +"$url2]kérvényezhet egyet[/url][/color]." #: editor/editor_help.cpp msgid "Properties" @@ -1566,7 +1563,7 @@ msgstr "Összes tulajdonság összecsukása" #: editor/editor_node.cpp msgid "Copy Params" -msgstr "Paraméterek másolása" +msgstr "Paraméterek Másolása" #: editor/editor_node.cpp msgid "Paste Params" @@ -1578,7 +1575,7 @@ msgstr "ErÅ‘forrás Beillesztése" #: editor/editor_node.cpp msgid "Copy Resource" -msgstr "Forrás másolása" +msgstr "ErÅ‘forrás Másolása" #: editor/editor_node.cpp msgid "Make Built-In" @@ -1651,7 +1648,7 @@ msgstr "Jelenet Gyors Megnyitása.." #: editor/editor_node.cpp msgid "Quick Open Script.." -msgstr "Script Gyors Megnyitása.." +msgstr "Szkript Gyors Megnyitása.." #: editor/editor_node.cpp msgid "Save & Close" @@ -1765,25 +1762,25 @@ msgstr "" #: editor/editor_node.cpp msgid "Unable to find script field for addon plugin at: 'res://addons/%s'." msgstr "" -"Nem található script mezÅ‘ az addon pluginnak a következÅ‘ helyen: 'res://" +"Nem található szkript mezÅ‘ az addon pluginnak a következÅ‘ helyen: 'res://" "addons/%s'." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." -msgstr "Nem sikerült az addon script betöltése a következÅ‘ útvonalról: '%s'." +msgstr "Nem sikerült az addon szkript betöltése a következÅ‘ útvonalról: '%s'." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' Base type is not EditorPlugin." msgstr "" -"Nem sikerült az addon script betöltése a következÅ‘ útvonalról: '%s' Az " +"Nem sikerült az addon szkript betöltése a következÅ‘ útvonalról: '%s' Az " "alaptÃpus nem EditorPlugin." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s' Script is not in tool mode." msgstr "" -"Nem sikerült az addon script betöltése a következÅ‘ útvonalról: '%s' A script " -"nem eszközmódban van." +"Nem sikerült az addon szkript betöltése a következÅ‘ útvonalról: '%s' A " +"szkript nem eszközmódban van." #: editor/editor_node.cpp msgid "" @@ -1953,7 +1950,7 @@ msgstr "Projekt BeállÃtások" #: editor/editor_node.cpp msgid "Run Script" -msgstr "Script Futtatása" +msgstr "Szkript Futtatása" #: editor/editor_node.cpp editor/project_export.cpp msgid "Export" @@ -2045,7 +2042,7 @@ msgstr "" #: editor/editor_node.cpp msgid "Sync Script Changes" -msgstr "Script Változtatások Szinkronizálása" +msgstr "Szkript Változtatások Szinkronizálása" #: editor/editor_node.cpp msgid "" @@ -2054,7 +2051,7 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"Ha ez a beállÃtás be van kapcsolva, bármilyen script, amit elment, újra " +"Ha ez a beállÃtás be van kapcsolva, bármilyen szkript, amit elment, újra " "betöltÅ‘dik a futó játékba.\n" "Ha egy távoli eszközön használja, sokkal hatékonyabb a hálózati " "fájlrendszerrel együtt." @@ -2253,7 +2250,7 @@ msgstr "Jelszó:" #: editor/editor_node.cpp msgid "Open & Run a Script" -msgstr "Megnyit és Scriptet Futtat" +msgstr "Szkriptet Megnyit és Futtat" #: editor/editor_node.cpp msgid "New Inherited" @@ -2277,7 +2274,7 @@ msgstr "3D SzerkesztÅ‘ Megnyitása" #: editor/editor_node.cpp msgid "Open Script Editor" -msgstr "Script SzerkesztÅ‘ Megnyitása" +msgstr "Szkript SzerkesztÅ‘ Megnyitása" #: editor/editor_node.cpp editor/project_manager.cpp msgid "Open Asset Library" @@ -2293,625 +2290,621 @@ msgstr "ElÅ‘zÅ‘ SzerkesztÅ‘ Megnyitása" #: editor/editor_plugin.cpp msgid "Creating Mesh Previews" -msgstr "" +msgstr "Háló ElÅ‘nézetek Létrehozása" #: editor/editor_plugin.cpp msgid "Thumbnail.." -msgstr "" +msgstr "Indexkép.." #: editor/editor_plugin_settings.cpp msgid "Installed Plugins:" -msgstr "" +msgstr "TelepÃtett BÅ‘vÃtmények:" #: editor/editor_plugin_settings.cpp msgid "Update" -msgstr "" +msgstr "FrissÃtés" #: editor/editor_plugin_settings.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Version:" -msgstr "" +msgstr "Verzió:" #: editor/editor_plugin_settings.cpp msgid "Author:" -msgstr "" +msgstr "SzerzÅ‘:" #: editor/editor_plugin_settings.cpp msgid "Status:" -msgstr "" +msgstr "Ãllapot:" #: editor/editor_profiler.cpp msgid "Stop Profiling" -msgstr "" +msgstr "Profilozás LeállÃtása" #: editor/editor_profiler.cpp msgid "Start Profiling" -msgstr "" +msgstr "Profilozás IndÃtása" #: editor/editor_profiler.cpp msgid "Measure:" -msgstr "" +msgstr "Mérés:" #: editor/editor_profiler.cpp msgid "Frame Time (sec)" -msgstr "" +msgstr "KeretidÅ‘ (mp)" #: editor/editor_profiler.cpp msgid "Average Time (sec)" -msgstr "" +msgstr "Ãtlagos IdÅ‘ (mp)" #: editor/editor_profiler.cpp msgid "Frame %" -msgstr "" +msgstr "Keret %" #: editor/editor_profiler.cpp msgid "Physics Frame %" -msgstr "" +msgstr "Fizika Keret %" #: editor/editor_profiler.cpp editor/script_editor_debugger.cpp msgid "Time:" -msgstr "" +msgstr "IdÅ‘:" #: editor/editor_profiler.cpp msgid "Inclusive" -msgstr "" +msgstr "Befoglaló" #: editor/editor_profiler.cpp msgid "Self" -msgstr "" +msgstr "Saját" #: editor/editor_profiler.cpp msgid "Frame #:" -msgstr "" +msgstr "Keret #:" #: editor/editor_profiler.cpp msgid "Time" -msgstr "" +msgstr "IdÅ‘" #: editor/editor_profiler.cpp msgid "Calls" -msgstr "" +msgstr "HÃvások" #: editor/editor_run_native.cpp msgid "Select device from the list" -msgstr "" +msgstr "Válasszon készüléket a listából" #: editor/editor_run_native.cpp msgid "" "No runnable export preset found for this platform.\n" "Please add a runnable preset in the export menu." msgstr "" +"Nem található futtatható exportállomány ehhez a platformhoz.\n" +"Adjon hozzá egy futtatható exportállományt az export menüben." #: editor/editor_run_script.cpp msgid "Write your logic in the _run() method." -msgstr "" +msgstr "Ãrja a logikát a _run() metódusba." #: editor/editor_run_script.cpp msgid "There is an edited scene already." -msgstr "" +msgstr "Már létezik szerkesztett jelenet." #: editor/editor_run_script.cpp msgid "Couldn't instance script:" -msgstr "" +msgstr "Nem sikerült a szkript példányosÃtása:" #: editor/editor_run_script.cpp msgid "Did you forget the 'tool' keyword?" -msgstr "" +msgstr "Nem felejtette el a 'tool' kulcsszót?" #: editor/editor_run_script.cpp msgid "Couldn't run script:" -msgstr "" +msgstr "Nem sikerült a szkript futtatása:" #: editor/editor_run_script.cpp msgid "Did you forget the '_run' method?" -msgstr "" +msgstr "Nem felejtette el a '_run' metódust?" #: editor/editor_settings.cpp msgid "Default (Same as Editor)" -msgstr "" +msgstr "Alapértelmezett (Ugyanaz, Mint a SzerkesztÅ‘nek)" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" -msgstr "" +msgstr "Válassza Ki Az Importálandó Node-okat" #: editor/editor_sub_scene.cpp msgid "Scene Path:" -msgstr "" +msgstr "Jelenet Elérési Útja:" #: editor/editor_sub_scene.cpp msgid "Import From Node:" -msgstr "" +msgstr "Importálás Node-ból:" #: editor/export_template_manager.cpp msgid "Re-Download" -msgstr "" +msgstr "Letöltés Megint" #: editor/export_template_manager.cpp msgid "Uninstall" -msgstr "" +msgstr "EltávolÃtás" #: editor/export_template_manager.cpp msgid "(Installed)" -msgstr "" +msgstr "(TelepÃtve)" #: editor/export_template_manager.cpp msgid "Download" -msgstr "" +msgstr "Letöltés" #: editor/export_template_manager.cpp msgid "(Missing)" -msgstr "" +msgstr "(Hiányzik)" #: editor/export_template_manager.cpp msgid "(Current)" -msgstr "" +msgstr "(Jelenlegi)" #: editor/export_template_manager.cpp msgid "Retrieving mirrors, please wait.." -msgstr "" +msgstr "Tükrök letöltése, kérjük várjon.." #: editor/export_template_manager.cpp msgid "Remove template version '%s'?" -msgstr "" +msgstr "EltávolÃtja a(z) '%s' verziójú sablont?" #: editor/export_template_manager.cpp msgid "Can't open export templates zip." -msgstr "" +msgstr "Nem nyitható meg az export sablon zip." #: editor/export_template_manager.cpp msgid "Invalid version.txt format inside templates." -msgstr "" - -#: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" +msgstr "Érvénytelen version.txt formátum a sablonokban." #: editor/export_template_manager.cpp msgid "No version.txt found inside templates." -msgstr "" +msgstr "Nem található version.txt a sablonokban." #: editor/export_template_manager.cpp msgid "Error creating path for templates:" -msgstr "" +msgstr "Hiba történt a sablonok elérési útjának létrehozásakor:" #: editor/export_template_manager.cpp msgid "Extracting Export Templates" -msgstr "" +msgstr "Export Sablonok Kibontása" #: editor/export_template_manager.cpp msgid "Importing:" -msgstr "" +msgstr "Importálás:" #: editor/export_template_manager.cpp msgid "" "No download links found for this version. Direct download is only available " "for official releases." msgstr "" +"Nem található letöltési link ehhez a verzióhoz. Közvetlen letöltés csak a " +"hivatalos kiadásokhoz elérhetÅ‘." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't resolve." -msgstr "" +msgstr "Nem megoldható." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't connect." -msgstr "" +msgstr "Nem lehet csatlakozni." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "No response." -msgstr "" +msgstr "Nincs válasz." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request Failed." -msgstr "" +msgstr "Kérés Sikertelen." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Redirect Loop." -msgstr "" +msgstr "ÃtirányÃtási Hurok." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed:" -msgstr "" - -#: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" +msgstr "Sikertelen:" #: editor/export_template_manager.cpp msgid "Download Complete." -msgstr "" +msgstr "A Letöltés BefejezÅ‘dött." #: editor/export_template_manager.cpp msgid "Error requesting url: " -msgstr "" +msgstr "Hiba történt az url lekérdezésekor: " #: editor/export_template_manager.cpp msgid "Connecting to Mirror.." -msgstr "" +msgstr "Csatlakozás Tükörhöz.." #: editor/export_template_manager.cpp msgid "Disconnected" -msgstr "" +msgstr "Kapcsolat bontva" #: editor/export_template_manager.cpp msgid "Resolving" -msgstr "" +msgstr "Megoldás" #: editor/export_template_manager.cpp msgid "Can't Resolve" -msgstr "" +msgstr "Nem Megoldható" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Connecting.." -msgstr "" +msgstr "Csatlakozás.." #: editor/export_template_manager.cpp -#, fuzzy msgid "Can't Connect" -msgstr "Kapcsolódás..." +msgstr "Nem Lehet Csatlakozni" #: editor/export_template_manager.cpp msgid "Connected" -msgstr "" +msgstr "Csatlakozva" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Requesting.." -msgstr "" +msgstr "Lekérdezés.." #: editor/export_template_manager.cpp msgid "Downloading" -msgstr "" +msgstr "Letöltés" #: editor/export_template_manager.cpp msgid "Connection Error" -msgstr "" +msgstr "Kapcsolathiba" #: editor/export_template_manager.cpp msgid "SSL Handshake Error" -msgstr "" +msgstr "SSL-Kézfogás Hiba" #: editor/export_template_manager.cpp msgid "Current Version:" -msgstr "" +msgstr "Jelenlegi Verzió:" #: editor/export_template_manager.cpp msgid "Installed Versions:" -msgstr "" +msgstr "TelepÃtett Verziók:" #: editor/export_template_manager.cpp msgid "Install From File" -msgstr "" +msgstr "TelepÃtés Fájlból" #: editor/export_template_manager.cpp msgid "Remove Template" -msgstr "" +msgstr "Sablon EltávolÃtása" #: editor/export_template_manager.cpp msgid "Select template file" -msgstr "" +msgstr "Válasszon sablonfájlt" #: editor/export_template_manager.cpp msgid "Export Template Manager" -msgstr "" +msgstr "Export Sablon KezelÅ‘" #: editor/export_template_manager.cpp msgid "Download Templates" -msgstr "" +msgstr "Sablonok Letöltése" #: editor/export_template_manager.cpp msgid "Select mirror from list: " -msgstr "" +msgstr "Válasszon tükröt a listából: " #: editor/file_type_cache.cpp msgid "Can't open file_type_cache.cch for writing, not saving file type cache!" msgstr "" +"Nem lehet megnyitni a file_type_cache.cch fájlt Ãrásra, a fájltÃpus " +"gyorsÃtótár nem lesz mentve!" #: editor/filesystem_dock.cpp msgid "Cannot navigate to '%s' as it has not been found in the file system!" -msgstr "" +msgstr "Nem lehet '%s'-t elérni, mivel nem létezik a fájlrendszerben!" #: editor/filesystem_dock.cpp msgid "View items as a grid of thumbnails" -msgstr "" +msgstr "Elemek kirajzolása indexképek rácsába" #: editor/filesystem_dock.cpp msgid "View items as a list" -msgstr "" +msgstr "Elemek listázása" #: editor/filesystem_dock.cpp msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" +"Ãllapot: Fájl importálása sikertelen. JavÃtsa a fájlt majd importálja be " +"újra manuálisan." #: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." -msgstr "" +msgstr "Az erÅ‘források gyökere nem mozgatható vagy átnevezhetÅ‘." #: editor/filesystem_dock.cpp msgid "Cannot move a folder into itself." -msgstr "" +msgstr "Egy mappa nem helyezhetÅ‘ önmagába." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Error moving:" -msgstr "Hiba betöltéskor:" +msgstr "Hiba mozgatáskor:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Error duplicating:" -msgstr "Hiba betöltéskor:" +msgstr "Hiba másoláskor:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Unable to update dependencies:" -msgstr "A Scene-t nem sikerült betölteni a hiányzó függÅ‘ségek miatt:" +msgstr "Nem sikerült a függÅ‘ségek frissÃtése:" #: editor/filesystem_dock.cpp msgid "No name provided" -msgstr "" +msgstr "Nincs név megadva" #: editor/filesystem_dock.cpp msgid "Provided name contains invalid characters" -msgstr "" +msgstr "A megadott név érvénytelen karaktereket tartalmaz" #: editor/filesystem_dock.cpp msgid "No name provided." -msgstr "" +msgstr "Nincs név megadva." #: editor/filesystem_dock.cpp msgid "Name contains invalid characters." -msgstr "" +msgstr "A név érvénytelen karaktereket tartalmaz." #: editor/filesystem_dock.cpp msgid "A file or folder with this name already exists." -msgstr "" +msgstr "Egy fájl vagy mappa már létezik a megadott névvel." #: editor/filesystem_dock.cpp msgid "Renaming file:" -msgstr "" +msgstr "Fájl átnevezése:" #: editor/filesystem_dock.cpp msgid "Renaming folder:" -msgstr "" +msgstr "Mappa átnevezése:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicating file:" -msgstr "Kiválasztás megkettÅ‘zése" +msgstr "Fájl másolása:" #: editor/filesystem_dock.cpp msgid "Duplicating folder:" -msgstr "" +msgstr "Mappa másolása:" #: editor/filesystem_dock.cpp msgid "Expand all" -msgstr "" +msgstr "Összes kibontása" #: editor/filesystem_dock.cpp msgid "Collapse all" -msgstr "" +msgstr "Összes összecsukása" #: editor/filesystem_dock.cpp msgid "Rename.." -msgstr "" +msgstr "Ãtnevezés.." #: editor/filesystem_dock.cpp msgid "Move To.." -msgstr "" +msgstr "Ãthelyezés.." #: editor/filesystem_dock.cpp msgid "Open Scene(s)" -msgstr "" +msgstr "Jelenet(ek) Megnyitása" #: editor/filesystem_dock.cpp msgid "Instance" -msgstr "" +msgstr "Példány" #: editor/filesystem_dock.cpp msgid "Edit Dependencies.." -msgstr "" +msgstr "FüggÅ‘ségek Szerkesztése.." #: editor/filesystem_dock.cpp msgid "View Owners.." -msgstr "" +msgstr "Tulajdonosok Megtekintése.." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicate.." -msgstr "Animáció kulcs megkettÅ‘zése" +msgstr "MegkettÅ‘zés.." #: editor/filesystem_dock.cpp msgid "Previous Directory" -msgstr "" +msgstr "ElÅ‘zÅ‘ Könyvtár" #: editor/filesystem_dock.cpp msgid "Next Directory" -msgstr "" +msgstr "KövetkezÅ‘ Könyvtár" #: editor/filesystem_dock.cpp msgid "Re-Scan Filesystem" -msgstr "" +msgstr "Fájlrendszer Újra-vizsgálata" #: editor/filesystem_dock.cpp msgid "Toggle folder status as Favorite" -msgstr "" +msgstr "Mappa Kedvencnek jelölése / Kedvenc jelölés visszavonása" #: editor/filesystem_dock.cpp msgid "Instance the selected scene(s) as child of the selected node." msgstr "" +"Kiválasztott jelenet(ek) példányosÃtása a kiválasztott Node gyermekeként." #: editor/filesystem_dock.cpp msgid "" "Scanning Files,\n" "Please Wait.." msgstr "" +"Fájlok Vizsgálata,\n" +"Kérem Várjon.." #: editor/filesystem_dock.cpp msgid "Move" -msgstr "" +msgstr "Ãthelyezés" #: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp #: editor/project_manager.cpp msgid "Rename" -msgstr "" +msgstr "Ãtnevezés" #: editor/groups_editor.cpp msgid "Add to Group" -msgstr "" +msgstr "Hozzáadás Csoporthoz" #: editor/groups_editor.cpp msgid "Remove from Group" -msgstr "" +msgstr "EltávolÃtás Csoportból" #: editor/import/resource_importer_scene.cpp msgid "Import as Single Scene" -msgstr "" +msgstr "Importálás Egyetlen Jelenetként" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Animations" -msgstr "" +msgstr "Importálás Külön Animációkkal" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials" -msgstr "" +msgstr "Importálás Külön Anyagokkal" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects" -msgstr "" +msgstr "Importálás Külön Objektumokkal" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Materials" -msgstr "" +msgstr "Importálás Külön Objektumokkal És Anyagokkal" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Animations" -msgstr "" +msgstr "Importálás Külön Objektumokkal És Animációkkal" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials+Animations" -msgstr "" +msgstr "Importálás Külön Anyagokkal És Animációkkal" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Materials+Animations" -msgstr "" +msgstr "Importálás Külön Objektumokkal, Anyagokkal És Animációkkal" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes" -msgstr "" +msgstr "Importálás Több Jelenetként" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes+Materials" -msgstr "" +msgstr "Importálás Több Jelentként és Anyagokként" #: editor/import/resource_importer_scene.cpp #: editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Import Scene" -msgstr "" +msgstr "Jelenet Importálása" #: editor/import/resource_importer_scene.cpp msgid "Importing Scene.." -msgstr "" +msgstr "Jelenet Importálása.." #: editor/import/resource_importer_scene.cpp msgid "Generating Lightmaps" -msgstr "" +msgstr "Fénytérképek Létrehozása" #: editor/import/resource_importer_scene.cpp msgid "Generating for Mesh: " -msgstr "" +msgstr "Létrehozás a KövetkezÅ‘ Hálóhoz: " #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script.." -msgstr "" +msgstr "TetszÅ‘leges Szkript Futtatása.." #: editor/import/resource_importer_scene.cpp msgid "Couldn't load post-import script:" -msgstr "" +msgstr "Nem sikerült az import utáni szkript betöltése:" #: editor/import/resource_importer_scene.cpp msgid "Invalid/broken script for post-import (check console):" msgstr "" +"Érvénytelen vagy sérült az importálás utáni szkript (ellenÅ‘rizze a konzolt):" #: editor/import/resource_importer_scene.cpp msgid "Error running post-import script:" -msgstr "" +msgstr "Hiba történt az importálás utána szkript futtatásakor:" #: editor/import/resource_importer_scene.cpp msgid "Saving.." -msgstr "" +msgstr "Mentés.." #: editor/import_dock.cpp msgid "Set as Default for '%s'" -msgstr "" +msgstr "BeállÃtás Alapértelmezettként '%s'-hez" #: editor/import_dock.cpp msgid "Clear Default for '%s'" -msgstr "" +msgstr "Alapértelmezett Törlése '%s'-nél" #: editor/import_dock.cpp msgid " Files" -msgstr "" +msgstr " Fájlok" #: editor/import_dock.cpp msgid "Import As:" -msgstr "" +msgstr "Importálás Mint:" #: editor/import_dock.cpp editor/property_editor.cpp msgid "Preset.." -msgstr "" +msgstr "BeépÃtett BeállÃtások.." #: editor/import_dock.cpp msgid "Reimport" -msgstr "" +msgstr "Újraimportálás" #: editor/multi_node_edit.cpp msgid "MultiNode Set" -msgstr "" +msgstr "MultiNode BeállÃtás" #: editor/node_dock.cpp msgid "Groups" -msgstr "" +msgstr "Csoportok" #: editor/node_dock.cpp msgid "Select a Node to edit Signals and Groups." -msgstr "" +msgstr "Válasszon ki egy Node-ot a Jelzések és Csoportok módosÃtásához." #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Create Poly" -msgstr "" +msgstr "Sokszög Létrehozása" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/collision_polygon_editor_plugin.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Edit Poly" -msgstr "" +msgstr "Sokszög Szerkesztése" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Insert Point" -msgstr "" +msgstr "Pont Beszúrása" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/collision_polygon_editor_plugin.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Edit Poly (Remove Point)" -msgstr "" +msgstr "Sokszög Szerkesztése (Pont EltávolÃtása)" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Remove Poly And Point" -msgstr "" +msgstr "Sokszög és Pont EltávolÃtása" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Create a new polygon from scratch" -msgstr "" +msgstr "Új sokszög létrehozása a semmibÅ‘l" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "" @@ -2920,69 +2913,73 @@ msgid "" "Ctrl+LMB: Split Segment.\n" "RMB: Erase Point." msgstr "" +"MeglévÅ‘ sokszög módosÃtása:\n" +"Bal Egérgomb: Pont Mozgatása.\n" +"Ctrl + Bal Egérgomb: Szakasz Felosztása.\n" +"Jobb Egérgomb: Pont Eltörlése." #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Delete points" -msgstr "" +msgstr "Pontok Törlése" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Toggle Autoplay" -msgstr "" +msgstr "Automatikus Lejátszás Váltása" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Animation Name:" -msgstr "" +msgstr "Új Animáció Neve:" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Anim" -msgstr "" +msgstr "Új Animáció" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Change Animation Name:" -msgstr "" +msgstr "Animáció Nevének Megváltoztatása:" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Delete Animation?" -msgstr "" +msgstr "Animáció Törlése?" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Remove Animation" -msgstr "" +msgstr "Animáció EltávolÃtása" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: Invalid animation name!" -msgstr "" +msgstr "HIBA: Érvénytelen animáció név!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: Animation name already exists!" -msgstr "" +msgstr "HIBA: Animáció név már létezik!" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Rename Animation" -msgstr "" +msgstr "Animáció Ãtnevezése" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Animation" -msgstr "" +msgstr "Animáció Hozzáadása" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Blend Next Changed" -msgstr "" +msgstr "KövetkezÅ‘ Megváltozott Keverése" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Change Blend Time" -msgstr "" +msgstr "Keverési IdÅ‘ MódosÃtása" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Load Animation" -msgstr "" +msgstr "Animáció Betöltése" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Duplicate Animation" -msgstr "" +msgstr "Animáció MegkettÅ‘zése" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: No animation to copy!" @@ -2990,91 +2987,92 @@ msgstr "HIBA: Nincs másolható animáció!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: No animation resource on clipboard!" -msgstr "" +msgstr "HIBA: Nincs animációs erÅ‘forrás a vágólapon!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Pasted Animation" -msgstr "" +msgstr "Animáció Beillesztve" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Paste Animation" -msgstr "" +msgstr "Animáció Beillesztése" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: No animation to edit!" -msgstr "" +msgstr "HIBA: Nincs animáció szerkesztésre!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation backwards from current pos. (A)" msgstr "" +"A kiválasztott animáció lejátszása visszafelé a jelenlegi pozÃcióból. (A)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation backwards from end. (Shift+A)" -msgstr "" +msgstr "A kiválasztott animáció lejátszása visszafelé a végétÅ‘l. (Shift + A)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Stop animation playback. (S)" -msgstr "" +msgstr "Animáció lejátszásának leállÃtása. (S)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from start. (Shift+D)" -msgstr "" +msgstr "A kiválasztott animáció lejátszása az elejétÅ‘l. (Shift + D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from current pos. (D)" -msgstr "" +msgstr "A kiválasztott animáció lejátszása az jelenlegi pozÃcióból. (D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation position (in seconds)." -msgstr "" +msgstr "Animáció pozÃció (másodpercekben)." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Scale animation playback globally for the node." -msgstr "" +msgstr "Animáció lejátszás skálázása globálisan a Node-nak." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Create new animation in player." -msgstr "" +msgstr "Új animáció létrehozása a lejátszóban." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Load animation from disk." -msgstr "" +msgstr "Animáció betöltése a lemezrÅ‘l." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Load an animation from disk." -msgstr "" +msgstr "Animáció betöltése a lemezrÅ‘l." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Save the current animation" -msgstr "" +msgstr "Jelenlegi animáció elmentése" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Display list of animations in player." -msgstr "" +msgstr "A lejátszóban lévÅ‘ animációk listájának megjelenÃtése." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Autoplay on Load" -msgstr "" +msgstr "Lejátszás Betöltéskor" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Edit Target Blend Times" -msgstr "" +msgstr "Cél Keverési IdÅ‘k MódosÃtása" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Tools" -msgstr "" +msgstr "Animációs Eszközök" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Copy Animation" -msgstr "Animáció másolása" +msgstr "Animáció Másolása" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Onion Skinning" -msgstr "" +msgstr "MásolópapÃr Animáció (Onion Skinning)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Enable Onion Skinning" -msgstr "" +msgstr "MásolópapÃr Mód Bekapcsolása" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Directions" @@ -3082,361 +3080,362 @@ msgstr "Irányok" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Past" -msgstr "" +msgstr "Múlt" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Future" -msgstr "" +msgstr "JövÅ‘" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Depth" -msgstr "" +msgstr "Mélység" #: editor/plugins/animation_player_editor_plugin.cpp msgid "1 step" -msgstr "" +msgstr "1 lépés" #: editor/plugins/animation_player_editor_plugin.cpp msgid "2 steps" -msgstr "" +msgstr "2 lépés" #: editor/plugins/animation_player_editor_plugin.cpp msgid "3 steps" -msgstr "" +msgstr "3 lépés" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Differences Only" -msgstr "" +msgstr "Csak A Különbségek" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Force White Modulate" -msgstr "" +msgstr "Fehérmoduláció KierÅ‘ltetése" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Include Gizmos (3D)" -msgstr "" +msgstr "Kihatás Gizmókra Is (3D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Create New Animation" -msgstr "" +msgstr "Új Animáció Létrehozása" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Name:" -msgstr "" +msgstr "Animáció Neve:" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: editor/script_create_dialog.cpp msgid "Error!" -msgstr "" +msgstr "Hiba!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Blend Times:" -msgstr "" +msgstr "Keverési IdÅ‘k:" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Next (Auto Queue):" -msgstr "" +msgstr "KövetkezÅ‘ (Auto Sor):" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Cross-Animation Blend Times" -msgstr "" +msgstr "Animációk Közötti Keverési IdÅ‘k" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Animation" -msgstr "" +msgstr "Animáció" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "New name:" -msgstr "" +msgstr "Új név:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Edit Filters" -msgstr "" +msgstr "SzűrÅ‘k Szerkesztése" #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/multimesh_editor_plugin.cpp msgid "Scale:" -msgstr "" +msgstr "Skála:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Fade In (s):" -msgstr "" +msgstr "ElÅ‘tűnés (mp):" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Fade Out (s):" -msgstr "" +msgstr "Elhalványulás (mp):" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend" -msgstr "" +msgstr "Keverés" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Mix" -msgstr "" +msgstr "Mixelés" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Auto Restart:" -msgstr "" +msgstr "Automatikus ÚjraindÃtás:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Restart (s):" -msgstr "" +msgstr "ÚjraindÃtás (mp):" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Random Restart (s):" -msgstr "" +msgstr "Véletlenszerű ÚjraindÃtás (mp):" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Start!" -msgstr "" +msgstr "Start!" #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/multimesh_editor_plugin.cpp msgid "Amount:" -msgstr "" +msgstr "Mennyiség:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend:" -msgstr "" +msgstr "Keverés:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend 0:" -msgstr "" +msgstr "Keverés 0:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend 1:" -msgstr "" +msgstr "Keverés 1:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "X-Fade Time (s):" -msgstr "" +msgstr "Ãttűnési IdÅ‘ (mp):" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Current:" -msgstr "" +msgstr "Jelenlegi:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Add Input" -msgstr "" +msgstr "Bemenet Hozzáadása" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Clear Auto-Advance" -msgstr "" +msgstr "Automatikus Léptetés TisztÃtása" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Set Auto-Advance" -msgstr "" +msgstr "Automatikus Léptetés BeállÃtása" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Delete Input" -msgstr "" +msgstr "Bemenet Törlése" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Animation tree is valid." -msgstr "" +msgstr "Az animációs fa érvényes." #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Animation tree is invalid." -msgstr "" +msgstr "Az animációs fa érvénytelen." #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Animation Node" -msgstr "" +msgstr "Animációs Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "OneShot Node" -msgstr "" +msgstr "Egyszeri Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Mix Node" -msgstr "" +msgstr "MixelÅ‘ Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend2 Node" -msgstr "" +msgstr "Keverés2 Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend3 Node" -msgstr "" +msgstr "Keverés3 Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend4 Node" -msgstr "" +msgstr "Keverés4 Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "TimeScale Node" -msgstr "" +msgstr "IdÅ‘Skála Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "TimeSeek Node" -msgstr "" +msgstr "IdÅ‘KeresÅ‘ Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Transition Node" -msgstr "" +msgstr "Ãtmenet Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Import Animations.." -msgstr "" +msgstr "Animációk Importálása.." #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Edit Node Filters" -msgstr "" +msgstr "Node SzűrÅ‘k MódosÃtása" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Filters.." -msgstr "" +msgstr "SzűrÅ‘k.." #: editor/plugins/animation_tree_editor_plugin.cpp -#, fuzzy msgid "AnimationTree" -msgstr "Animáció másolása" +msgstr "AnimationTree" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Free" -msgstr "" +msgstr "Ingyenes" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Contents:" -msgstr "" +msgstr "Tartalom:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "View Files" -msgstr "" +msgstr "Fájlok Megtekintése" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't resolve hostname:" -msgstr "" +msgstr "A gazdagép neve nem oldható meg:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Connection error, please try again." -msgstr "" +msgstr "Kapcsolat hiba, kérjük próbálja meg újra." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't connect to host:" -msgstr "" +msgstr "Nem lehet csatlakozni a kiszolgálóhoz:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "No response from host:" -msgstr "" +msgstr "Nincs válasz a kiszolgálótól:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request failed, return code:" -msgstr "" +msgstr "Kérés sikertelen, visszatérési kód:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request failed, too many redirects" -msgstr "" +msgstr "Kérés sikertelen, túl sok átirányÃtás" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Bad download hash, assuming file has been tampered with." msgstr "" +"Rossz letöltési hash, a program feltételezi, hogy a fájlt rosszindulatilag " +"módosÃtották." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Expected:" -msgstr "" +msgstr "Várt:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Got:" -msgstr "" +msgstr "Kapott:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed sha256 hash check" -msgstr "" +msgstr "sha256 hash ellenÅ‘rzés megbukott" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" -msgstr "" +msgstr "Eszköz Letöltési Hiba:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Fetching:" -msgstr "" +msgstr "Lekérés:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Resolving.." -msgstr "" +msgstr "Megoldás.." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Error making request" -msgstr "" +msgstr "Hiba kéréskor" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Idle" -msgstr "" +msgstr "Tétlen" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Retry" -msgstr "" +msgstr "Újra" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download Error" -msgstr "" +msgstr "Letöltési Hiba" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download for this asset is already in progress!" -msgstr "" +msgstr "Ennek az eszköznek a letöltése már folyamatban van!" #: editor/plugins/asset_library_editor_plugin.cpp msgid "first" -msgstr "" +msgstr "elsÅ‘" #: editor/plugins/asset_library_editor_plugin.cpp msgid "prev" -msgstr "" +msgstr "elÅ‘zÅ‘" #: editor/plugins/asset_library_editor_plugin.cpp msgid "next" -msgstr "" +msgstr "következÅ‘" #: editor/plugins/asset_library_editor_plugin.cpp msgid "last" -msgstr "" +msgstr "utolsó" #: editor/plugins/asset_library_editor_plugin.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "All" -msgstr "" +msgstr "Mind" #: editor/plugins/asset_library_editor_plugin.cpp #: editor/project_settings_editor.cpp msgid "Plugins" -msgstr "" +msgstr "BÅ‘vÃtmények" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Sort:" -msgstr "" +msgstr "Rendezés:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Reverse" -msgstr "" +msgstr "Visszafele" #: editor/plugins/asset_library_editor_plugin.cpp #: editor/project_settings_editor.cpp msgid "Category:" -msgstr "" +msgstr "Kategória:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Site:" -msgstr "" +msgstr "Oldal:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Support.." -msgstr "" +msgstr "Támogatás.." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Official" -msgstr "" +msgstr "Hivatalos" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Testing" -msgstr "" +msgstr "Tesztelés Alatt" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" -msgstr "" +msgstr "Eszköz ZIP Fájl" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" @@ -3444,135 +3443,146 @@ msgid "" "Save your scene (for images to be saved in the same dir), or pick a save " "path from the BakedLightmap properties." msgstr "" +"Nem lehet megállapÃtani mentési útvonalat a fénytérképeknek.\n" +"Mentse el a jelenetét (hogy aztán a képek ugyanabba a mappába legyenek " +"mentve), vagy válasszon egy mentési útvonalat a BakedLightmap " +"tulajdonságaiból." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" "No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake " "Light' flag is on." msgstr "" +"Nincs mesh, amibe adatokat süthetne. Bizonyosodjon meg arról, hogy " +"tartalmaznak egy UV2 csatornát, és hogy a 'Fény Besütése' opció be van " +"kapcsolva." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Failed creating lightmap images, make sure path is writable." msgstr "" +"Fénytérképek létrehozása sikertelen, gyÅ‘zÅ‘djön meg arról, hogy az útvonal " +"Ãrható." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" -msgstr "" +msgstr "Fény Besütése" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Preview" -msgstr "" +msgstr "ElÅ‘nézet" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap" -msgstr "" +msgstr "Illesztés BeállÃtása" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Offset:" -msgstr "" +msgstr "Rács Eltolás:" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Step:" -msgstr "" +msgstr "Rács Léptetés:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Offset:" -msgstr "" +msgstr "Forgatási Eltolás:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Step:" -msgstr "" +msgstr "Forgatási Léptetés:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move Pivot" -msgstr "" +msgstr "Forgatási Pont Mozgatása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move Action" -msgstr "" +msgstr "Mozgási Művelet" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move vertical guide" -msgstr "" +msgstr "FüggÅ‘leges vezetÅ‘vonal mozgatása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create new vertical guide" -msgstr "" +msgstr "Új függÅ‘leges vezetÅ‘vonal létrehozása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Remove vertical guide" -msgstr "" +msgstr "FüggÅ‘leges vezetÅ‘vonal eltávolÃtása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move horizontal guide" -msgstr "" +msgstr "VÃzszintes vezetÅ‘vonal mozgatása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create new horizontal guide" -msgstr "" +msgstr "Új vÃzszintes vezetÅ‘vonal létrehozása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Remove horizontal guide" -msgstr "" +msgstr "VÃzszintes vezetÅ‘vonal eltávolÃtása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create new horizontal and vertical guides" -msgstr "" +msgstr "Új vÃzszintes és függÅ‘leges vezetÅ‘vonalak létrehozása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Edit IK Chain" -msgstr "" +msgstr "IK Lánc Szerkesztése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Edit CanvasItem" -msgstr "" +msgstr "CanvasItem Szerkesztése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" -msgstr "" +msgstr "Csak Horgonyok" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors and Margins" -msgstr "" +msgstr "Horgonyok és Margók MódosÃtása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors" -msgstr "" +msgstr "Horgonyok MódosÃtása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Paste Pose" -msgstr "" +msgstr "Póz Beillesztése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Select Mode" -msgstr "" +msgstr "Kiválasztó Mód" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Drag: Rotate" -msgstr "" +msgstr "Húzás: Forgatás" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+Drag: Move" -msgstr "" +msgstr "Alt + Húzás: Mozgatás" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)." msgstr "" +"Nyomja meg a 'v' gombot a Forgatási Pont Megváltoztatásához, Vagy 'Shift + " +"v'-t a Forgatási Pont Húzásához (mozgás közben)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+RMB: Depth list selection" -msgstr "" +msgstr "Alt + Jobb Egérgomb: Mélységi lista választás" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move Mode" -msgstr "" +msgstr "Mozgás Mód" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotate Mode" -msgstr "" +msgstr "Forgató mód" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -3580,895 +3590,903 @@ msgid "" "Show a list of all objects at the position clicked\n" "(same as Alt+RMB in select mode)." msgstr "" +"Lista mutatási minden objektumról a kattintás helye alatt\n" +"(ugyanaz, mint Alt + Jobb Egérgomb Kiválasztó Módban)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Click to change object's rotation pivot." -msgstr "" +msgstr "Kattintson ide az objektum forgatási pontjának megváltoztatásához." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Pan Mode" -msgstr "" +msgstr "Pásztázás Mód" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Toggles snapping" -msgstr "" +msgstr "Illesztés be- és kikapcsolása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Snap" -msgstr "" +msgstr "Illesztés Használata" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snapping options" -msgstr "" +msgstr "Illesztési beállÃtások" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to grid" -msgstr "" +msgstr "Rácshoz illesztés" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Rotation Snap" -msgstr "" +msgstr "Forgatási Illesztés Használata" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap..." -msgstr "" +msgstr "Illesztés BeállÃtása..." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap Relative" -msgstr "" +msgstr "RelatÃv Illesztés" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Pixel Snap" -msgstr "" +msgstr "Pixelhez Illesztés" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Smart snapping" -msgstr "" +msgstr "Intelligens illesztés" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to parent" -msgstr "" +msgstr "Illesztés szülÅ‘höz" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to node anchor" -msgstr "" +msgstr "Illesztés node horgonyhoz" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to node sides" -msgstr "" +msgstr "Illesztés node oldalakhoz" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to other nodes" -msgstr "" +msgstr "Illesztés más node-okhoz" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to guides" -msgstr "" +msgstr "Illesztés vezetÅ‘vonalakhoz" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Lock the selected object in place (can't be moved)." -msgstr "" +msgstr "A kiválasztott objektum zárolása (mozgathatatlanná tétele)." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Unlock the selected object (can be moved)." -msgstr "" +msgstr "A kiválasztott objektum feloldása (mozgathatóvá tétele)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Makes sure the object's children are not selectable." -msgstr "" +msgstr "Kiválaszthatatlanná teszi az objektum gyermekeit." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Restores the object's children's ability to be selected." -msgstr "" +msgstr "Újra kiválaszthatóvá teszi az objektum gyermekeit." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Make Bones" -msgstr "" +msgstr "Csontok Létrehozása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear Bones" -msgstr "" +msgstr "Csontok Törlése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Bones" -msgstr "" +msgstr "Csontok Mutatása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" -msgstr "" +msgstr "IK Lánc Létrehozása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear IK Chain" -msgstr "" +msgstr "IK Lánc Törlése" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "View" -msgstr "" +msgstr "Nézet" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Show Grid" -msgstr "" +msgstr "Rács MegjelenÃtése" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" -msgstr "" +msgid "Show Helpers" +msgstr "SegÃtÅ‘k MegjelenÃtése" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" -msgstr "" +msgid "Show Rulers" +msgstr "Vonalzók MegjelenÃtése" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" -msgstr "" +msgid "Show Guides" +msgstr "VezetÅ‘vonalak MegjelenÃtése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Selection" -msgstr "" +msgstr "Kijelölés Középre" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Frame Selection" -msgstr "" +msgstr "Kijelölés Keretezése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Layout" -msgstr "" +msgstr "Elrendezés" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Keys" -msgstr "" +msgstr "Kulcsok Beszúrása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Key" -msgstr "" +msgstr "Kulcs Beszúrása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Key (Existing Tracks)" -msgstr "" +msgstr "Kulcs Beszúrása (MeglévÅ‘ Nyomvonalakra)" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Copy Pose" -msgstr "Póz másolása" +msgstr "Póz Másolása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear Pose" -msgstr "" +msgstr "Póz Törlése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Drag pivot from mouse position" -msgstr "" +msgstr "Forgatási pont húzása az egér helyétÅ‘l" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Set pivot at mouse position" -msgstr "" +msgstr "Forgatási pont beállÃtása az egér helyére" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Multiply grid step by 2" -msgstr "" +msgstr "Rács Léptetés Mértékének Kétszerezése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Divide grid step by 2" -msgstr "" +msgstr "Rács Léptetés Mértékének Felezése" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Add %s" -msgstr "" +msgstr "%s Hozzáadása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Adding %s..." -msgstr "" +msgstr "%s Hozzáadása..." #: editor/plugins/canvas_item_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Ok" -msgstr "" +msgstr "Rendben" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Cannot instantiate multiple nodes without root." -msgstr "" +msgstr "Nem lehet több node-ot példányosÃtani gyökér nélkül." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Create Node" -msgstr "" +msgstr "Node Létrehozása" #: 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 "" +msgstr "Hiba történt a jelenet példányosÃtáskor %s-bÅ‘l" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change default type" -msgstr "" +msgstr "Alapértelmezett tÃpus megváltoztatása" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" "Drag & drop + Shift : Add node as sibling\n" "Drag & drop + Alt : Change node type" msgstr "" +"Fogd és vidd + Shift: Node hozzáadása testvérként\n" +"Fogd és vidd + Alt: Node tÃpusának megváltoztatása" #: editor/plugins/collision_polygon_editor_plugin.cpp msgid "Create Poly3D" -msgstr "" +msgstr "Poly3D Létrehozása" #: editor/plugins/collision_shape_2d_editor_plugin.cpp msgid "Set Handle" -msgstr "" +msgstr "Fogantyú BeállÃtása" #: editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Remove item %d?" -msgstr "" +msgstr "%d elem eltávolÃtása?" #: editor/plugins/cube_grid_theme_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp msgid "Add Item" -msgstr "" +msgstr "Elem Hozzáadása" #: editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Remove Selected Item" -msgstr "" +msgstr "Kijelölt Elem EltávolÃtása" #: editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Import from Scene" -msgstr "" +msgstr "Importálás JelenetbÅ‘l" #: editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Update from Scene" -msgstr "" +msgstr "FrissÃtés JelenetbÅ‘l" #: editor/plugins/curve_editor_plugin.cpp msgid "Flat0" -msgstr "" +msgstr "Lapos 0" #: editor/plugins/curve_editor_plugin.cpp msgid "Flat1" -msgstr "" +msgstr "Lapos 1" #: editor/plugins/curve_editor_plugin.cpp msgid "Ease in" -msgstr "" +msgstr "Lassan Be" #: editor/plugins/curve_editor_plugin.cpp msgid "Ease out" -msgstr "" +msgstr "Lassan Ki" #: editor/plugins/curve_editor_plugin.cpp msgid "Smoothstep" -msgstr "" +msgstr "SimÃtott Lépés" #: editor/plugins/curve_editor_plugin.cpp msgid "Modify Curve Point" -msgstr "" +msgstr "Görbe Pontjának MódosÃtása" #: editor/plugins/curve_editor_plugin.cpp msgid "Modify Curve Tangent" -msgstr "" +msgstr "Görbe ÉrintÅ‘jének MódosÃtása" #: editor/plugins/curve_editor_plugin.cpp msgid "Load Curve Preset" -msgstr "" +msgstr "ElÅ‘re BeállÃtott Görbe Betöltése" #: editor/plugins/curve_editor_plugin.cpp msgid "Add point" -msgstr "" +msgstr "Pont hozzáadása" #: editor/plugins/curve_editor_plugin.cpp msgid "Remove point" -msgstr "" +msgstr "Pont eltávolÃtása" #: editor/plugins/curve_editor_plugin.cpp msgid "Left linear" -msgstr "" +msgstr "Bal lineáris" #: editor/plugins/curve_editor_plugin.cpp msgid "Right linear" -msgstr "" +msgstr "Jobb lineáris" #: editor/plugins/curve_editor_plugin.cpp msgid "Load preset" -msgstr "" +msgstr "ElÅ‘re beállÃtott betöltése" #: editor/plugins/curve_editor_plugin.cpp msgid "Remove Curve Point" -msgstr "" +msgstr "Görbe Pontjának EltávolÃtása" #: editor/plugins/curve_editor_plugin.cpp msgid "Toggle Curve Linear Tangent" -msgstr "" +msgstr "Görbe Lineáris ÉrintÅ‘jének Kapcsolása" #: editor/plugins/curve_editor_plugin.cpp msgid "Hold Shift to edit tangents individually" -msgstr "" +msgstr "Tartsa lenyomva a Shift gombot az érintÅ‘k egyenkénti szerkesztéséhez" #: editor/plugins/gi_probe_editor_plugin.cpp msgid "Bake GI Probe" -msgstr "" +msgstr "GI Szonda Besütése" #: editor/plugins/gradient_editor_plugin.cpp msgid "Add/Remove Color Ramp Point" -msgstr "" +msgstr "SzÃn Gradiens Pont Hozzáadása / EltávolÃtása" #: editor/plugins/gradient_editor_plugin.cpp #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Modify Color Ramp" -msgstr "" +msgstr "SzÃn Gradiens MódosÃtása" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item %d" -msgstr "" +msgstr "%d elem" #: editor/plugins/item_list_editor_plugin.cpp msgid "Items" -msgstr "" +msgstr "Elemek" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item List Editor" -msgstr "" +msgstr "Elemlista SzerkesztÅ‘" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "" "No OccluderPolygon2D resource on this node.\n" "Create and assign one?" msgstr "" +"Nincs OccluderPolygon2D erÅ‘forrás ezen a node-on.\n" +"Létrehoz egyet és hozzárendeli a node-hoz?" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Create Occluder Polygon" -msgstr "" +msgstr "Ãrnyékoló Sokszög Létrehozása" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Create a new polygon from scratch." -msgstr "" +msgstr "Új sokszög létrehozása a semmibÅ‘l." #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Edit existing polygon:" -msgstr "" +msgstr "LétezÅ‘ sokszög szerkesztése:" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "LMB: Move Point." -msgstr "" +msgstr "Bal Egérgomb: Pont Mozgatása." #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Ctrl+LMB: Split Segment." -msgstr "" +msgstr "Ctrl + Bal Egérgomb: Szakasz Felosztása." #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "RMB: Erase Point." -msgstr "" +msgstr "Jobb Egérgomb: Pont Törlése." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh is empty!" -msgstr "" +msgstr "A háló üres!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Static Trimesh Body" -msgstr "" +msgstr "Statikus Trimesh Test Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Static Convex Body" -msgstr "" +msgstr "Statikus Konvex Test Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "This doesn't work on scene root!" -msgstr "" +msgstr "Ez nem hajtható végre a jelenet gyökerén!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Shape" -msgstr "" +msgstr "Trimesh Alakzat Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Convex Shape" -msgstr "" +msgstr "Konvex Alakzat Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Navigation Mesh" -msgstr "" +msgstr "Navigációs Háló Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Contained Mesh is not of type ArrayMesh." -msgstr "" +msgstr "A tartalmazott Mesh nem ArrayMesh tÃpusú." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "UV Unwrap failed, mesh may not be manifold?" -msgstr "" +msgstr "UV kibontás sikertelen, a mesh talán nem sokrétű?" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "No mesh to debug." -msgstr "" +msgstr "Nincs mesh a hibakereséshez." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Model has no UV in this layer" -msgstr "" +msgstr "A modellnek nincs UV-je ezen a rétegen" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "MeshInstance lacks a Mesh!" -msgstr "" +msgstr "MeshInstance-nak nincs Mesh-e!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh has not surface to create outlines from!" msgstr "" +"A Mesh-nek nincsenek felszÃnei, ami alapján körvonalakat lehetni készÃteni!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Could not create outline!" -msgstr "" +msgstr "KörvonalkészÃtés sikertelen!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline" -msgstr "" +msgstr "Körvonal KészÃtése" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh" -msgstr "" +msgstr "Mesh" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Body" -msgstr "" +msgstr "Trimesh Statikus Test Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Convex Static Body" -msgstr "" +msgstr "Konvex Statikus Test Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Collision Sibling" -msgstr "" +msgstr "Trimesh Ãœtközési Testvér Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Convex Collision Sibling" -msgstr "" +msgstr "Konvex Ãœtközési Testvér Létrehozása" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh.." -msgstr "" +msgstr "Körvonalháló Létrehozása.." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "View UV1" -msgstr "" +msgstr "UV1 Megtekintése" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "View UV2" -msgstr "" +msgstr "UV2 Megtekintése" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Unwrap UV2 for Lightmap/AO" -msgstr "" +msgstr "UV2 Kicsomagolása Fénytérképhez / AO-hoz" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh" -msgstr "" +msgstr "Körvonalháló KészÃtése" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Outline Size:" -msgstr "" +msgstr "Körvonal Mérete:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and no MultiMesh set in node)." msgstr "" +"Nincs háló forrás meghatározva (és nincs MultiMesh a Node-ban beállÃtva)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "No mesh source specified (and MultiMesh contains no Mesh)." -msgstr "" +msgstr "Nincs háló forrás meghatározva (és a MultiMesh nem tartalmaz Mesh-t)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (invalid path)." -msgstr "" +msgstr "Mesh forrás érvénytelen (érvénytelen útvonal)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (not a MeshInstance)." -msgstr "" +msgstr "Mesh forrás érvénytelen (nem MeshInstance)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh source is invalid (contains no Mesh resource)." -msgstr "" +msgstr "Mesh forrás érvénytelen (nem tartalmaz Mesh erÅ‘forrást)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "No surface source specified." -msgstr "" +msgstr "Nincs felületi forrás meghatározva." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Surface source is invalid (invalid path)." -msgstr "" +msgstr "Felületi forrás érvénytelen (érvénytelen útvonal)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Surface source is invalid (no geometry)." -msgstr "" +msgstr "Felületi forrás érvénytelen (nincs geometria)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Surface source is invalid (no faces)." -msgstr "" +msgstr "Felületi forrás érvénytelen (nincsenek oldalak)." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Parent has no solid faces to populate." -msgstr "" +msgstr "A szülÅ‘nek nincsenek kitölthetÅ‘ szilárd oldalai." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Couldn't map area." -msgstr "" +msgstr "A területet nem lehetett leképezni." #: editor/plugins/multimesh_editor_plugin.cpp msgid "Select a Source Mesh:" -msgstr "" +msgstr "Válasszon Ki Egy Forrás Mesh-t:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Select a Target Surface:" -msgstr "" +msgstr "Válasszon Ki Egy Cél Felületet:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Populate Surface" -msgstr "" +msgstr "Felület Kitöltése" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Populate MultiMesh" -msgstr "" +msgstr "MultiMesh Kitöltése" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Target Surface:" -msgstr "" +msgstr "Cél Felület:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Source Mesh:" -msgstr "" +msgstr "Forrás Mesh:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "X-Axis" -msgstr "" +msgstr "X-Tengely" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Y-Axis" -msgstr "" +msgstr "Y-Tengely" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Z-Axis" -msgstr "" +msgstr "Z-Tengely" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Mesh Up Axis:" -msgstr "" +msgstr "Mesh \"Fel\" Tengelye:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Random Rotation:" -msgstr "" +msgstr "Véletlenszerű Forgatás:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Random Tilt:" -msgstr "" +msgstr "Véletlenszerű Billentés:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Random Scale:" -msgstr "" +msgstr "Véletlenszerű Skálázás:" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Populate" -msgstr "" +msgstr "Kitöltés" #: editor/plugins/navigation_mesh_editor_plugin.cpp msgid "Bake!" -msgstr "" +msgstr "Besütés!" #: editor/plugins/navigation_mesh_editor_plugin.cpp msgid "Bake the navigation mesh." -msgstr "" +msgstr "A navigációs mesh besütése." #: editor/plugins/navigation_mesh_editor_plugin.cpp msgid "Clear the navigation mesh." -msgstr "" +msgstr "Navigációs háló törlése." #: editor/plugins/navigation_mesh_generator.cpp msgid "Setting up Configuration..." -msgstr "" +msgstr "Konfiguráció beállÃtása…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Calculating grid size..." -msgstr "" +msgstr "Rácsméret kiszámÃtása…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Creating heightfield..." -msgstr "" +msgstr "MagasságmezÅ‘ létrehozása…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Marking walkable triangles..." -msgstr "" +msgstr "Járható háromszögek megjelölése…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Constructing compact heightfield..." -msgstr "" +msgstr "Kompakt magasságmezÅ‘ kiépÃtése…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Eroding walkable area..." -msgstr "" +msgstr "Járható terület lepusztÃtása…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Partitioning..." -msgstr "" +msgstr "Particionálás…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Creating contours..." -msgstr "" +msgstr "Kontúrok létrehozása…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Creating polymesh..." -msgstr "" +msgstr "Polymesh létrehozása…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Converting to native navigation mesh..." -msgstr "" +msgstr "Ãtkonvertálás natÃv navigációs hálóra…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Navigation Mesh Generator Setup:" -msgstr "" +msgstr "Navigációs Háló Generátor BeállÃtás:" #: editor/plugins/navigation_mesh_generator.cpp msgid "Parsing Geometry..." -msgstr "" +msgstr "Geometria Elemzése…" #: editor/plugins/navigation_mesh_generator.cpp msgid "Done!" -msgstr "" +msgstr "Kész!" #: editor/plugins/navigation_polygon_editor_plugin.cpp msgid "Create Navigation Polygon" -msgstr "" +msgstr "Navigációs Sokszög Létrehozása" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Generating AABB" -msgstr "" +msgstr "AABB Generálása" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Can only set point into a ParticlesMaterial process material" -msgstr "" +msgstr "Csak egy ParticlesMaterial feldolgozó anyagba állÃthat pontot" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Error loading image:" -msgstr "" +msgstr "Hiba a kép betöltésekor:" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "No pixels with transparency > 128 in image.." -msgstr "" +msgstr "Nem létezik egyetlen pixel sem >128-as átlátszósággal a képben.." #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Generate Visibility Rect" -msgstr "" +msgstr "Láthatósági Téglalap Generálása" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Load Emission Mask" -msgstr "" +msgstr "Kibocsátási Maszk Betöltése" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Clear Emission Mask" -msgstr "" +msgstr "Kibocsátási Maszk Törlése" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Particles" -msgstr "" +msgstr "Részecskék" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Generated Point Count:" -msgstr "" +msgstr "Generált Pontok Száma:" #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Generation Time (sec):" -msgstr "" +msgstr "Generálási IdÅ‘ (mp):" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Emission Mask" -msgstr "" +msgstr "Kibocsátási Maszk" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Capture from Pixel" -msgstr "" +msgstr "Kinyerés PixelbÅ‘l" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Emission Colors" -msgstr "" +msgstr "Kibocsátási SzÃnek" #: editor/plugins/particles_editor_plugin.cpp msgid "Node does not contain geometry." -msgstr "" +msgstr "A Node nem tartalmaz geometriát." #: editor/plugins/particles_editor_plugin.cpp msgid "Node does not contain geometry (faces)." -msgstr "" +msgstr "A Node nem tartalmaz geometriát (oldalakat)." #: editor/plugins/particles_editor_plugin.cpp msgid "A processor material of type 'ParticlesMaterial' is required." -msgstr "" +msgstr "Egy 'ParticlesMaterial' tÃpusú feldolgozó anyag szükséges." #: editor/plugins/particles_editor_plugin.cpp msgid "Faces contain no area!" -msgstr "" +msgstr "Az oldalak nem tartalmaznak területet!" #: editor/plugins/particles_editor_plugin.cpp msgid "No faces!" -msgstr "" +msgstr "Nincsenek oldalak!" #: editor/plugins/particles_editor_plugin.cpp msgid "Generate AABB" -msgstr "" +msgstr "AABB Generálása" #: editor/plugins/particles_editor_plugin.cpp msgid "Create Emission Points From Mesh" -msgstr "" +msgstr "Kibocsátási Pontok Létrehozása A Mesh Alapján" #: editor/plugins/particles_editor_plugin.cpp msgid "Create Emission Points From Node" -msgstr "" +msgstr "Kibocsátási Pontok Létrehozása A Node Alapján" #: editor/plugins/particles_editor_plugin.cpp msgid "Create Emitter" -msgstr "" +msgstr "Kibocsátó Létrehozása" #: editor/plugins/particles_editor_plugin.cpp msgid "Emission Points:" -msgstr "" +msgstr "Kibocsátási Pontok:" #: editor/plugins/particles_editor_plugin.cpp msgid "Surface Points" -msgstr "" +msgstr "Felületi Pontok" #: editor/plugins/particles_editor_plugin.cpp msgid "Surface Points+Normal (Directed)" -msgstr "" +msgstr "Felületi Pontok + Normálok (IrányÃtott)" #: editor/plugins/particles_editor_plugin.cpp msgid "Volume" -msgstr "" +msgstr "Mennyiség" #: editor/plugins/particles_editor_plugin.cpp msgid "Emission Source: " -msgstr "" +msgstr "Kibocsátási Forrás: " #: editor/plugins/particles_editor_plugin.cpp msgid "Generate Visibility AABB" -msgstr "" +msgstr "Láthatósági AABB Generálása" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove Point from Curve" -msgstr "" +msgstr "Pont EltávolÃtása GörbérÅ‘l" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove Out-Control from Curve" -msgstr "" +msgstr "Ki-VezérlÅ‘ EltávolÃtása GörbébÅ‘l" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Remove In-Control from Curve" -msgstr "" +msgstr "Be-VezérlÅ‘ EltávolÃtása GörbébÅ‘l" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Add Point to Curve" -msgstr "" +msgstr "Pont Hozzáadása a Görbéhez" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Move Point in Curve" -msgstr "" +msgstr "Pont Mozgatása a Görbén" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Move In-Control in Curve" -msgstr "" +msgstr "Be-VezérlÅ‘ Mozgatása a Görbén" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Move Out-Control in Curve" -msgstr "" +msgstr "Ki-VezérlÅ‘ Mozgatása a Görbén" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Select Points" -msgstr "" +msgstr "Pontok Kiválasztása" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Shift+Drag: Select Control Points" -msgstr "" +msgstr "Shift + Húzás: VezérlÅ‘pontok Kiválasztása" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Click: Add Point" -msgstr "" +msgstr "Kattintás: Pont Hozzáadása" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Right Click: Delete Point" -msgstr "" +msgstr "Jobb Kattintás: Pont Törlése" #: editor/plugins/path_2d_editor_plugin.cpp msgid "Select Control Points (Shift+Drag)" -msgstr "" +msgstr "VezérlÅ‘pontok Kiválasztása (Shift + Húzás)" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Add Point (in empty space)" -msgstr "" +msgstr "Pont Hozzáadása (üres helyre)" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Split Segment (in curve)" -msgstr "" +msgstr "Szakasz Felosztása (görbén)" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Delete Point" -msgstr "" +msgstr "Pont Törlése" #: editor/plugins/path_2d_editor_plugin.cpp #: editor/plugins/path_editor_plugin.cpp msgid "Close Curve" -msgstr "" +msgstr "Görbe Lezárása" #: editor/plugins/path_editor_plugin.cpp msgid "Curve Point #" -msgstr "" +msgstr "Görbe Pont #" #: editor/plugins/path_editor_plugin.cpp msgid "Set Curve Point Position" -msgstr "" +msgstr "Görbe Pont PozÃció BeállÃtása" #: editor/plugins/path_editor_plugin.cpp msgid "Set Curve In Position" -msgstr "" +msgstr "Be-Görbe PozÃció BeállÃtása" #: editor/plugins/path_editor_plugin.cpp msgid "Set Curve Out Position" -msgstr "" +msgstr "Ki-Görbe PozÃció BeállÃtása" #: editor/plugins/path_editor_plugin.cpp msgid "Split Path" -msgstr "" +msgstr "Útvonal Felosztása" #: editor/plugins/path_editor_plugin.cpp msgid "Remove Path Point" -msgstr "" +msgstr "Útvonal Pont EltávolÃtása" #: editor/plugins/path_editor_plugin.cpp msgid "Remove Out-Control Point" -msgstr "" +msgstr "Ki-VezérlÅ‘ Pont EltávolÃtása" #: editor/plugins/path_editor_plugin.cpp msgid "Remove In-Control Point" -msgstr "" +msgstr "Be-VezérlÅ‘ Pont EltávolÃtása" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Create UV Map" -msgstr "" +msgstr "UV Térkép Létrehozása" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Transform UV Map" -msgstr "" +msgstr "UV Térkép Transzformálása" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Polygon 2D UV Editor" -msgstr "" +msgstr "2D UV Sokszög SzerkesztÅ‘" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Move Point" -msgstr "" +msgstr "Pont Mozgatása" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Ctrl: Rotate" -msgstr "" +msgstr "Ctrl: Forgatás" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift: Move All" -msgstr "" +msgstr "Shift: Mind Mozgatása" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Shift+Ctrl: Scale" -msgstr "" +msgstr "Shift + Ctrl: Skálázás" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Move Polygon" -msgstr "" +msgstr "Sokszög Mozgatása" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Rotate Polygon" -msgstr "" +msgstr "Sokszög Forgatása" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Scale Polygon" -msgstr "" +msgstr "Sokszög Skálázása" #: editor/plugins/polygon_2d_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp @@ -4476,309 +4494,328 @@ msgstr "" #: editor/project_settings_editor.cpp editor/property_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Edit" -msgstr "" +msgstr "Szerkesztés" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Polygon->UV" -msgstr "" +msgstr "Sokszög -> UV" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "UV->Polygon" -msgstr "" +msgstr "UV -> Sokszög" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Clear UV" -msgstr "" +msgstr "UV Törlése" #: editor/plugins/polygon_2d_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap" -msgstr "" +msgstr "Illesztés" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Enable Snap" -msgstr "" +msgstr "Illesztés Engedélyezése" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid" -msgstr "" +msgstr "Rács" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ERROR: Couldn't load resource!" -msgstr "" +msgstr "HIBA: Nem sikerült betölteni az erÅ‘forrást!" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Add Resource" -msgstr "" +msgstr "ErÅ‘forrás Hozzáadása" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Rename Resource" -msgstr "" +msgstr "ErÅ‘forrás Ãtnevezése" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Delete Resource" -msgstr "" +msgstr "ErÅ‘forrás Törlése" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "Resource clipboard is empty!" -msgstr "" +msgstr "Az erÅ‘forrás vágólap üres!" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Megnyitás SzerkesztÅ‘ben" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Példány:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "TÃpus:" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" -msgstr "" +msgstr "ErÅ‘forrás Betöltése" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Paste" -msgstr "" +msgstr "Beillesztés" #: editor/plugins/resource_preloader_editor_plugin.cpp msgid "ResourcePreloader" -msgstr "" +msgstr "ResourcePreloader" #: editor/plugins/script_editor_plugin.cpp msgid "Clear Recent Files" -msgstr "" +msgstr "Legutóbbi Fájlok Törlése" #: editor/plugins/script_editor_plugin.cpp msgid "Close and save changes?" -msgstr "" +msgstr "Bezárja és menti a változásokat?" #: editor/plugins/script_editor_plugin.cpp msgid "Error while saving theme" -msgstr "" +msgstr "HIba történt a téma mentésekor" #: editor/plugins/script_editor_plugin.cpp msgid "Error saving" -msgstr "" +msgstr "Hiba mentés közben" #: editor/plugins/script_editor_plugin.cpp msgid "Error importing theme" -msgstr "" +msgstr "Hiba történt a téma importálásakor" #: editor/plugins/script_editor_plugin.cpp msgid "Error importing" -msgstr "" +msgstr "Hiba importáláskor" #: editor/plugins/script_editor_plugin.cpp msgid "Import Theme" -msgstr "" +msgstr "Téma Importálása" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme As.." -msgstr "" +msgstr "Téma Mentése Másként.." #: editor/plugins/script_editor_plugin.cpp msgid " Class Reference" -msgstr "" +msgstr " Osztály Referencia" #: editor/plugins/script_editor_plugin.cpp msgid "Sort" -msgstr "" +msgstr "Rendezés" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Move Up" -msgstr "" +msgstr "Mozgatás Felfelé" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Move Down" -msgstr "" +msgstr "Mozgatás Lefelé" #: editor/plugins/script_editor_plugin.cpp msgid "Next script" -msgstr "" +msgstr "KövetkezÅ‘ Szkript" #: editor/plugins/script_editor_plugin.cpp msgid "Previous script" -msgstr "" +msgstr "ElÅ‘zÅ‘ Szkript" #: editor/plugins/script_editor_plugin.cpp msgid "File" -msgstr "" +msgstr "Fájl" #: editor/plugins/script_editor_plugin.cpp msgid "New" -msgstr "" +msgstr "Új" #: editor/plugins/script_editor_plugin.cpp msgid "Save All" -msgstr "" +msgstr "Összes Mentése" #: editor/plugins/script_editor_plugin.cpp msgid "Soft Reload Script" -msgstr "" +msgstr "Szkript Puha Újratöltése" #: editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Copy Script Path" -msgstr "Útvonal másolása" +msgstr "Szkript Útvonal Másolása" #: editor/plugins/script_editor_plugin.cpp msgid "Show In File System" -msgstr "" +msgstr "Mutassa a Fájlrendszerben" #: editor/plugins/script_editor_plugin.cpp msgid "History Prev" -msgstr "" +msgstr "ElÅ‘zÅ‘ ElÅ‘zmény" #: editor/plugins/script_editor_plugin.cpp msgid "History Next" -msgstr "" +msgstr "KövetkezÅ‘ ElÅ‘zmény" #: editor/plugins/script_editor_plugin.cpp msgid "Reload Theme" -msgstr "" +msgstr "Téma Újratöltése" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme" -msgstr "" +msgstr "Téma Mentése" #: editor/plugins/script_editor_plugin.cpp msgid "Save Theme As" -msgstr "" +msgstr "Téma Mentése Másként" #: editor/plugins/script_editor_plugin.cpp msgid "Close Docs" -msgstr "" +msgstr "Dokumentációs Lapok Bezárása" #: editor/plugins/script_editor_plugin.cpp msgid "Close All" -msgstr "" +msgstr "Mind Bezárása" #: editor/plugins/script_editor_plugin.cpp msgid "Close Other Tabs" -msgstr "" +msgstr "A Többi Lap Bezárása" #: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp msgid "Run" -msgstr "" +msgstr "Futtatás" #: editor/plugins/script_editor_plugin.cpp msgid "Toggle Scripts Panel" -msgstr "" +msgstr "Szkript Panel MegjelenÃtése" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find.." -msgstr "" +msgstr "Keresés.." #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp msgid "Find Next" -msgstr "" +msgstr "KövetkezÅ‘ Keresése" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Step Over" -msgstr "" +msgstr "Ãtlépés" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Step Into" -msgstr "" +msgstr "Belépés" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Break" -msgstr "" +msgstr "Szünet" #: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp #: editor/script_editor_debugger.cpp msgid "Continue" -msgstr "" +msgstr "Folytatás" #: editor/plugins/script_editor_plugin.cpp msgid "Keep Debugger Open" -msgstr "" +msgstr "HibakeresÅ‘ Nyitva Tartása" #: editor/plugins/script_editor_plugin.cpp msgid "Debug with external editor" -msgstr "" +msgstr "Hibakeresés külsÅ‘ szerkesztÅ‘vel" #: editor/plugins/script_editor_plugin.cpp msgid "Open Godot online documentation" -msgstr "" +msgstr "Godot online dokumentáció megnyitása" #: editor/plugins/script_editor_plugin.cpp msgid "Search the class hierarchy." -msgstr "" +msgstr "Keresés az osztályhierarchiában." #: editor/plugins/script_editor_plugin.cpp msgid "Search the reference documentation." -msgstr "" +msgstr "Keresés a referencia dokumentációban." #: editor/plugins/script_editor_plugin.cpp msgid "Go to previous edited document." -msgstr "" +msgstr "Ugrás az elÅ‘zÅ‘leg szerkesztett dokumentumra." #: editor/plugins/script_editor_plugin.cpp msgid "Go to next edited document." -msgstr "" +msgstr "Ugrás a következÅ‘leg szerkesztett dokumentumra." #: editor/plugins/script_editor_plugin.cpp msgid "Discard" -msgstr "" +msgstr "Elvetés" #: editor/plugins/script_editor_plugin.cpp msgid "Create Script" -msgstr "" +msgstr "Szkript Létrehozása" #: editor/plugins/script_editor_plugin.cpp msgid "" "The following files are newer on disk.\n" "What action should be taken?:" msgstr "" +"A alábbi fájlok újabbak a lemezen.\n" +"Mit szeretne lépni?:" #: editor/plugins/script_editor_plugin.cpp msgid "Reload" -msgstr "" +msgstr "Újratöltés" #: editor/plugins/script_editor_plugin.cpp msgid "Resave" -msgstr "" +msgstr "Újramentés" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Debugger" -msgstr "" +msgstr "HibakeresÅ‘" #: editor/plugins/script_editor_plugin.cpp msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" msgstr "" +"A beépÃtett szkriptek csak akkor szerkeszthetÅ‘ek, amikor az a jelenet, " +"amihez tartoznak, éppen be van töltve" #: editor/plugins/script_text_editor.cpp msgid "Only resources from filesystem can be dropped." -msgstr "" +msgstr "Csak a fájlrendszerbÅ‘l eredÅ‘ erÅ‘forrásokat lehet bedobni." #: editor/plugins/script_text_editor.cpp msgid "Pick Color" -msgstr "" +msgstr "SzÃn Választása" #: editor/plugins/script_text_editor.cpp msgid "Convert Case" -msgstr "" +msgstr "Kis- és Nagybetűk Konvertálása" #: editor/plugins/script_text_editor.cpp msgid "Uppercase" -msgstr "" +msgstr "Mind Nagybetű" #: editor/plugins/script_text_editor.cpp msgid "Lowercase" -msgstr "" +msgstr "Mind Kisbetű" #: editor/plugins/script_text_editor.cpp msgid "Capitalize" -msgstr "" +msgstr "Szó Eleji Nagybetű" #: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp msgid "Cut" -msgstr "" +msgstr "Kivágás" #: editor/plugins/script_text_editor.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp @@ -4789,108 +4826,108 @@ msgstr "Másolás" #: editor/plugins/script_text_editor.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp msgid "Select All" -msgstr "" +msgstr "Összes Kijelölése" #: editor/plugins/script_text_editor.cpp msgid "Delete Line" -msgstr "" +msgstr "Sor Törlése" #: editor/plugins/script_text_editor.cpp msgid "Indent Left" -msgstr "" +msgstr "Behúzás Balra" #: editor/plugins/script_text_editor.cpp msgid "Indent Right" -msgstr "" +msgstr "Behúzás Jobbra" #: editor/plugins/script_text_editor.cpp msgid "Toggle Comment" -msgstr "" - -#: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" +msgstr "Ãtváltás Megjegyzésre" #: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" -msgstr "" +msgstr "Sor Összezárása / Kibontása" #: editor/plugins/script_text_editor.cpp msgid "Fold All Lines" -msgstr "" +msgstr "Összes Sor Összezárása" #: editor/plugins/script_text_editor.cpp msgid "Unfold All Lines" -msgstr "" +msgstr "Összes Sor Kibontása" + +#: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Klónozás Lefelé" #: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" -msgstr "" +msgstr "Szimbólum Befejezése" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" -msgstr "" +msgstr "Sorvégi Szóközök LenyÃrása" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent To Spaces" -msgstr "" +msgstr "Behúzások Ãtkonvertálása Szóközökre" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent To Tabs" -msgstr "" +msgstr "Behúzások Ãtkonvertálása Tabokra" #: editor/plugins/script_text_editor.cpp msgid "Auto Indent" -msgstr "" +msgstr "Automatikus Behúzás" #: editor/plugins/script_text_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Toggle Breakpoint" -msgstr "" +msgstr "Töréspont Elhelyezése" #: editor/plugins/script_text_editor.cpp msgid "Remove All Breakpoints" -msgstr "" +msgstr "Összes Töréspont EltávolÃtása" #: editor/plugins/script_text_editor.cpp msgid "Goto Next Breakpoint" -msgstr "" +msgstr "Ugrás KövetkezÅ‘ Töréspontra" #: editor/plugins/script_text_editor.cpp msgid "Goto Previous Breakpoint" -msgstr "" +msgstr "Ugrás ElÅ‘zÅ‘ Töréspontra" #: editor/plugins/script_text_editor.cpp msgid "Convert To Uppercase" -msgstr "" +msgstr "Konvertálás Nagybetűsre" #: editor/plugins/script_text_editor.cpp msgid "Convert To Lowercase" -msgstr "" +msgstr "Konvertálás Kisbetűsre" #: editor/plugins/script_text_editor.cpp msgid "Find Previous" -msgstr "" +msgstr "ElÅ‘zÅ‘ Keresése" #: editor/plugins/script_text_editor.cpp msgid "Replace.." -msgstr "" +msgstr "Csere.." #: editor/plugins/script_text_editor.cpp msgid "Goto Function.." -msgstr "" +msgstr "Ugrás Funkcióra.." #: editor/plugins/script_text_editor.cpp msgid "Goto Line.." -msgstr "" +msgstr "Ugrás Sorra.." #: editor/plugins/script_text_editor.cpp msgid "Contextual Help" -msgstr "" +msgstr "Kontextusérzékeny Súgó" #: editor/plugins/shader_editor_plugin.cpp msgid "Shader" -msgstr "" +msgstr "Shader" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Change Scalar Constant" @@ -5664,11 +5701,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5928,10 +5960,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5952,7 +5980,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5972,10 +6002,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -5992,9 +6018,8 @@ msgid "Create New Project" msgstr "" #: editor/project_manager.cpp -#, fuzzy msgid "Create & Edit" -msgstr "Létrehozás" +msgstr "Létrehozás és Szerkesztés" #: editor/project_manager.cpp msgid "Install Project:" @@ -6657,18 +6682,13 @@ msgid "Error duplicating scene to save it." msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Sub-Resources" -msgstr "Forrás másolása" +msgstr "Al-ErÅ‘források" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6703,7 +6723,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Copy Node Path" -msgstr "Node útvonal másaolása" +msgstr "Node Útvonal Másolása" #: editor/scene_tree_dock.cpp msgid "Delete (No Confirm)" @@ -6778,10 +6798,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -6958,9 +6974,8 @@ msgid "Child Process Connected" msgstr "" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Copy Error" -msgstr "Póz másolása" +msgstr "Hiba Másolása" #: editor/script_editor_debugger.cpp msgid "Inspect Previous Instance" @@ -7115,9 +7130,8 @@ msgid "Select dependencies of the library for this entry" msgstr "" #: modules/gdnative/gdnative_library_editor_plugin.cpp -#, fuzzy msgid "Remove current entry" -msgstr "Jelenlegi nyomvonal felfelé mozgatása." +msgstr "Jelenlegi tétel eltávolÃtása" #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Double click to create a new entry" @@ -7163,11 +7177,12 @@ msgstr "" #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Invalid type argument to convert(), use TYPE_* constants." msgstr "" +"Érvénytelen tÃpus argumentum a convert()-hez használjon TYPE_* konstansokat." #: modules/gdscript/gdscript_functions.cpp modules/mono/glue/glue_header.h #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." -msgstr "" +msgstr "Nincs elég bájt a bájtok dekódolására, vagy hibás formátum." #: modules/gdscript/gdscript_functions.cpp msgid "step argument is zero!" @@ -7206,11 +7221,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" +msgstr "KövetkezÅ‘ SÃk" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Plane" +msgstr "ElÅ‘zÅ‘ SÃk" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7218,19 +7245,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7338,6 +7365,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7353,27 +7384,37 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " "properly!" msgstr "" +"Egy node munkamemória nélkül yield-elt, olvassa el a dokumentációt a yield " +"helyes használatáról!" #: modules/visual_script/visual_script.cpp msgid "" "Node yielded, but did not return a function state in the first working " "memory." msgstr "" +"A node yield-elt, de nem adta vissza funkció állapotot a legelsÅ‘ " +"munkamemóriában." #: modules/visual_script/visual_script.cpp msgid "" "Return value must be assigned to first element of node working memory! Fix " "your node please." msgstr "" +"A node munkamemóriájának elsÅ‘ elemének kell, hogy legyen visszatérési " +"értéke! JavÃtsa ki a node-ját." #: modules/visual_script/visual_script.cpp msgid "Node returned an invalid sequence output: " -msgstr "" +msgstr "Node egy érvénytelen szekvencia kimenettel tért vissza: " #: modules/visual_script/visual_script.cpp msgid "Found sequence bit but not the node in the stack, report bug!" @@ -7625,7 +7666,7 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Copy Nodes" -msgstr "Node-ok másolása" +msgstr "Node-ok Másolása" #: modules/visual_script/visual_script_editor.cpp msgid "Cut Nodes" @@ -7852,6 +7893,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -7959,7 +8008,7 @@ msgstr "Figyelem!" #: scene/gui/dialogs.cpp msgid "Please Confirm..." -msgstr "Kérem erÅ‘sÃtse meg..." +msgstr "Kérem ErÅ‘sÃtse Meg..." #: scene/gui/file_dialog.cpp msgid "Select this Folder" @@ -7996,11 +8045,10 @@ msgid "" "obtain a size. Otherwise, make it a RenderTarget and assign its internal " "texture to some node for display." msgstr "" -"Ez a nézet nincs beállÃtva renderelési célnak. Ha azt szeretné, hogy a " -"tartalma közvetlenül a képernyÅ‘n jelenjen meg, akkor készÃtsen rajta egy " -"gyermek Control-t, Ãgy megkaphatja a méretét. EllenkezÅ‘ esetben készÃtsen " -"egy RenderTarget-et, és rendelje hozzá a belsÅ‘ textúrát egy Node-hoz a " -"megjelenÃtéshez." +"Ez a nézetablak nincs beállÃtva leképezési célnak. Ha azt szeretné, hogy a " +"tartalma közvetlenül a képernyÅ‘n jelenjen meg, tegye azt egy Control " +"gyermekévé, hogy Ãgy kapjon méretet. EllenkezÅ‘ esetben tegye RenderTarget-" +"té, és állÃtsa hozzá a belsÅ‘ textúráját valamilyen node-hoz kirajzolásra." #: scene/resources/dynamic_font.cpp msgid "Error initializing FreeType." @@ -8018,6 +8066,16 @@ msgstr "Hiba a betűtÃpus betöltésekor." msgid "Invalid font size." msgstr "Érvénytelen betűtÃpus méret." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Érvénytelen version.txt formátum a sablonokban. A revÃzió nem érvényes " +#~ "azonosÃtó." + +#~ msgid "Can't write file." +#~ msgstr "Nem lehet fájlt Ãrni." + #~ msgid "Next" #~ msgstr "KövetkezÅ‘" diff --git a/editor/translations/id.po b/editor/translations/id.po index ae7fd98ae2..df10490482 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -10,22 +10,22 @@ # Damar S. M <the.last.walla@gmail.com>, 2017. # Khairul Hidayat <khairulcyber4rt@gmail.com>, 2016. # Romi Kusuma Bakti <romikusumab@gmail.com>, 2017. -# Sofyan Sugianto <sofyanartem@gmail.com>, 2017. +# Sofyan Sugianto <sofyanartem@gmail.com>, 2017-2018. # Tom My <tom.asadinawan@gmail.com>, 2017. # yursan9 <rizal.sagi@gmail.com>, 2016. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2017-12-11 10:47+0000\n" -"Last-Translator: Romi Kusuma Bakti <romikusumab@gmail.com>\n" +"PO-Revision-Date: 2018-03-02 01:38+0000\n" +"Last-Translator: Sofyan Sugianto <sofyanartem@gmail.com>\n" "Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/" "godot/id/>\n" "Language: id\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 2.18-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -36,9 +36,8 @@ msgid "All Selection" msgstr "Semua pilihan" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Change Keyframe Time" -msgstr "Ubah Nilai Animasi" +msgstr "Ubah Waktu Keyframe Animasi" #: editor/animation_editor.cpp msgid "Anim Change Transition" @@ -49,9 +48,8 @@ msgid "Anim Change Transform" msgstr "Ubah Transformasi Animasi" #: editor/animation_editor.cpp -#, fuzzy msgid "Anim Change Keyframe Value" -msgstr "Ubah Nilai Animasi" +msgstr "Ubah Nilai Keyframe Animasi" #: editor/animation_editor.cpp msgid "Anim Change Call" @@ -99,7 +97,7 @@ msgstr "Ubah Trek Anim ke Wrap Mode" #: editor/animation_editor.cpp msgid "Edit Node Curve" -msgstr "Edit Kurva Node" +msgstr "Sunting Kurva Node" #: editor/animation_editor.cpp msgid "Edit Selection Curve" @@ -380,9 +378,8 @@ msgid "No Matches" msgstr "Tidak ada yang cocok" #: editor/code_editor.cpp -#, fuzzy msgid "Replaced %d occurrence(s)." -msgstr "Diganti kejadian (kejadian-kejadian) %d." +msgstr "%d kejadian diganti." #: editor/code_editor.cpp msgid "Match Case" @@ -504,9 +501,8 @@ msgid "Connecting Signal:" msgstr "Menyambungkan Sinyal:" #: editor/connections_dialog.cpp -#, fuzzy msgid "Disconnect '%s' from '%s'" -msgstr "Sambungkan '%s' ke '%s'" +msgstr "Memutuskan '%s' dari '%s'" #: editor/connections_dialog.cpp msgid "Connect.." @@ -522,9 +518,8 @@ msgid "Signals" msgstr "Sinyal-sinyal" #: editor/create_dialog.cpp -#, fuzzy msgid "Change %s Type" -msgstr "Ubah Tipe Nilai Array" +msgstr "Ubah Tipe %s" #: editor/create_dialog.cpp editor/project_settings_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -532,9 +527,8 @@ msgid "Change" msgstr "Ubah" #: editor/create_dialog.cpp -#, fuzzy msgid "Create New %s" -msgstr "Buat Baru" +msgstr "Buat Baru %s" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp @@ -612,9 +606,8 @@ msgid "Fix Broken" msgstr "Perbaiki yang Rusak" #: editor/dependency_editor.cpp -#, fuzzy msgid "Dependency Editor" -msgstr "Editor Ketergantungan" +msgstr "Penyunting Dependensi" #: editor/dependency_editor.cpp msgid "Search Replacement Resource:" @@ -647,9 +640,8 @@ msgstr "" "Hapus saja? (tidak bisa dibatalkan/undo)" #: editor/dependency_editor.cpp -#, fuzzy msgid "Cannot remove:" -msgstr "Tidak bisa dibuang:\n" +msgstr "Tidak bisa menghapus:" #: editor/dependency_editor.cpp msgid "Error loading:" @@ -710,7 +702,7 @@ msgstr "Ubah Kunci Kamus" #: editor/dictionary_property_edit.cpp #, fuzzy msgid "Change Dictionary Value" -msgstr "Ubah Nilai Array" +msgstr "Ubah Nilai Dictionary" #: editor/editor_about.cpp msgid "Thanks from the Godot community!" @@ -733,9 +725,8 @@ msgid "Lead Developer" msgstr "Pengembang Utama" #: editor/editor_about.cpp -#, fuzzy msgid "Project Manager " -msgstr "Manajer Proyek" +msgstr "Manajer Proyek " #: editor/editor_about.cpp msgid "Developers" @@ -794,14 +785,12 @@ msgstr "" "lisensi masing-masing." #: editor/editor_about.cpp -#, fuzzy msgid "All Components" -msgstr "Konstanta:" +msgstr "Semua Komponen" #: editor/editor_about.cpp -#, fuzzy msgid "Components" -msgstr "Konstanta:" +msgstr "Komponen" #: editor/editor_about.cpp msgid "Licenses" @@ -812,9 +801,8 @@ msgid "Error opening package file, not in zip format." msgstr "Gagal saat membuka paket, tidak dalam bentuk zip." #: editor/editor_asset_installer.cpp -#, fuzzy msgid "Uncompressing Assets" -msgstr "Mengimpor ulang" +msgstr "Membuka Aset Terkompresi" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Package Installed Successfully!" @@ -843,14 +831,12 @@ msgid "Add Effect" msgstr "Tambahkan Efek" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Rename Audio Bus" -msgstr "Namai kembali Autoload" +msgstr "Ubah Nama Bus Audio" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Change Audio Bus Volume" -msgstr "Alih Audio Bus Solo" +msgstr "Ubah Volume Bus Audio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" @@ -877,9 +863,8 @@ msgid "Move Bus Effect" msgstr "Pindah Efek Bus" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Delete Bus Effect" -msgstr "Hapus yang Dipilih" +msgstr "Hapus Effect Bus" #: editor/editor_audio_buses.cpp msgid "Audio Bus, Drag and Drop to rearrange." @@ -907,18 +892,16 @@ msgid "Duplicate" msgstr "Gandakan" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Reset Volume" -msgstr "Kebalikan Semula Pandangan" +msgstr "Setel Ulang Volume" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Delete Effect" -msgstr "Hapus yang Dipilih" +msgstr "Hapus Efek" #: editor/editor_audio_buses.cpp msgid "Audio" -msgstr "" +msgstr "Suara" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus" @@ -931,22 +914,20 @@ msgstr "Master Bus tidak dapat dihapus!" #: editor/editor_audio_buses.cpp #, fuzzy msgid "Delete Audio Bus" -msgstr "Hapus Penampilan" +msgstr "Hapus Bus Audio" #: editor/editor_audio_buses.cpp #, fuzzy msgid "Duplicate Audio Bus" -msgstr "Duplikat Pilihan" +msgstr "Duplikat Audio Bus" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Reset Bus Volume" -msgstr "Kebalikan Semula Pandangan" +msgstr "Setel Ulang Bus Volume" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Move Audio Bus" -msgstr "Pindahkan Kunci Tambah" +msgstr "Pindahkan Audio Bus" #: editor/editor_audio_buses.cpp msgid "Save Audio Bus Layout As.." @@ -997,7 +978,7 @@ msgstr "Simpan Layout Bus ke berkas." #: editor/editor_audio_buses.cpp editor/import_dock.cpp #, fuzzy msgid "Load Default" -msgstr "Bawaan" +msgstr "Muat Konfigurasi Bawaan" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." @@ -1012,9 +993,9 @@ msgid "Valid characters:" msgstr "Karakter sah:" #: editor/editor_autoload_settings.cpp -#, fuzzy msgid "Invalid name. Must not collide with an existing engine class name." -msgstr "Nama tidak sah. Harus tidak serupa dengan class name engine yang ada." +msgstr "" +"Nama tidak valid. Tidak boleh sama dengan nama kelas bawaan engine yang ada." #: editor/editor_autoload_settings.cpp msgid "Invalid name. Must not collide with an existing buit-in type name." @@ -1062,7 +1043,6 @@ msgid "Remove Autoload" msgstr "Hapus Autoload" #: editor/editor_autoload_settings.cpp -#, fuzzy msgid "Enable" msgstr "Aktifkan" @@ -1102,16 +1082,16 @@ msgstr "Memperbaharui scene.." #: editor/editor_data.cpp msgid "[empty]" -msgstr "" +msgstr "[kosong]" #: editor/editor_data.cpp msgid "[unsaved]" -msgstr "" +msgstr "[belum disimpan]" #: editor/editor_dir_dialog.cpp #, fuzzy msgid "Please select a base directory first" -msgstr "Mohon simpan scene terlebih dahulu." +msgstr "Pilih direktori kerja terlebih dahulu" #: editor/editor_dir_dialog.cpp msgid "Choose a Directory" @@ -1147,31 +1127,28 @@ msgid "Packing" msgstr "Mengemas" #: editor/editor_export.cpp platform/javascript/export/export.cpp -#, fuzzy msgid "Template file not found:" -msgstr "Template berkas tidak ditemukan:\n" +msgstr "Templat berkas tidak ditemukan:" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "File Exists, Overwrite?" msgstr "File telah ada, Overwrite?" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Select Current Folder" -msgstr "Buat Folder" +msgstr "Pilih Folder Saat Ini" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Copy Path" -msgstr "" +msgstr "Salin Lokasi" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Show In File Manager" msgstr "Tampilkan di Manajer Berkas" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp -#, fuzzy msgid "New Folder.." -msgstr "Buat Folder" +msgstr "Buat Direktori..." #: editor/editor_file_dialog.cpp msgid "Refresh" @@ -1212,17 +1189,14 @@ msgid "Save a File" msgstr "Simpan sebuah File" #: editor/editor_file_dialog.cpp -#, fuzzy msgid "Go Back" -msgstr "Mundur" +msgstr "Kembali" #: editor/editor_file_dialog.cpp -#, fuzzy msgid "Go Forward" msgstr "Maju" #: editor/editor_file_dialog.cpp -#, fuzzy msgid "Go Up" msgstr "Naik" @@ -1251,9 +1225,8 @@ msgid "Move Favorite Down" msgstr "Pindahkan Favorit Kebawah" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Go to parent folder" -msgstr "Tidak dapat membuat folder." +msgstr "Pergi ke direktori induk" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Directories & Files:" @@ -1277,9 +1250,8 @@ msgid "ScanSources" msgstr "Sumber Pemindaian" #: editor/editor_file_system.cpp -#, fuzzy msgid "(Re)Importing Assets" -msgstr "Mengimpor ulang" +msgstr "Mengimpor ulang Aset" #: editor/editor_help.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp @@ -1315,9 +1287,8 @@ msgid "Brief Description:" msgstr "Deskripsi Singkat:" #: editor/editor_help.cpp -#, fuzzy msgid "Members" -msgstr "Member-member:" +msgstr "Anggota" #: editor/editor_help.cpp modules/visual_script/visual_script_editor.cpp msgid "Members:" @@ -1326,7 +1297,7 @@ msgstr "Member-member:" #: editor/editor_help.cpp #, fuzzy msgid "Public Methods" -msgstr "Metode Publik:" +msgstr "Fungsi Publik" #: editor/editor_help.cpp msgid "Public Methods:" @@ -1346,57 +1317,50 @@ msgid "Signals:" msgstr "Sinyal-sinyal:" #: editor/editor_help.cpp -#, fuzzy msgid "Enumerations" -msgstr "Fungsi-fungsi:" +msgstr "Enumerasi" #: editor/editor_help.cpp -#, fuzzy msgid "Enumerations:" -msgstr "Fungsi-fungsi:" +msgstr "Enumerasi:" #: editor/editor_help.cpp msgid "enum " -msgstr "" +msgstr "enum " #: editor/editor_help.cpp -#, fuzzy msgid "Constants" -msgstr "Konstanta:" +msgstr "Konstanta" #: editor/editor_help.cpp msgid "Constants:" msgstr "Konstanta:" #: editor/editor_help.cpp -#, fuzzy msgid "Description" -msgstr "Deskripsi:" +msgstr "Deskripsi" #: editor/editor_help.cpp -#, fuzzy msgid "Online Tutorials:" -msgstr "Online Dokumentasi" +msgstr "Tutorial Daring:" #: editor/editor_help.cpp -#, fuzzy msgid "" "There are currently no tutorials for this class, you can [color=$color][url=" "$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/" "url][/color]." msgstr "" -"Untuk saat ini tidak ada deskripsi metode ini. Tolong bantu kita dengan " -"[color=$color][url=$url]kontribusi[/url][/color]!" +"Untuk saat ini tidak ada tutorial dalam kelas ini, anda bisa [color=$color]" +"[url=$url]ikut berkontribusi[/url][/color] atau [color=$color][url=" +"$url2]memberikan usulan[/url][/color]." #: editor/editor_help.cpp -#, fuzzy msgid "Properties" -msgstr "Properti Objek." +msgstr "Properti Objek" #: editor/editor_help.cpp -#, fuzzy msgid "Property Description:" -msgstr "Deskripsi Singkat:" +msgstr "Deskripsi Properti Objek:" #: editor/editor_help.cpp msgid "" @@ -1407,9 +1371,8 @@ msgstr "" "dengan[color=$color][url=$url]kontribusi[/url][/color]!" #: editor/editor_help.cpp -#, fuzzy msgid "Methods" -msgstr "Daftar Fungsi:" +msgstr "Fungsi" #: editor/editor_help.cpp msgid "Method Description:" @@ -1432,9 +1395,8 @@ msgid "Find" msgstr "Cari" #: editor/editor_log.cpp -#, fuzzy msgid "Output:" -msgstr " Keluaran:" +msgstr "Keluaran:" #: editor/editor_log.cpp editor/plugins/animation_tree_editor_plugin.cpp #: editor/property_editor.cpp editor/script_editor_debugger.cpp @@ -1444,9 +1406,8 @@ msgid "Clear" msgstr "Bersihkan" #: editor/editor_log.cpp -#, fuzzy msgid "Clear Output" -msgstr "Luaran" +msgstr "Bersihkan Luaran" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Error saving resource!" @@ -1475,28 +1436,24 @@ msgid "Error while saving." msgstr "Error saat menyimpan." #: editor/editor_node.cpp -#, fuzzy msgid "Can't open '%s'." -msgstr "Menyambungkan.." +msgstr "Tidak dapat membuka '%s'." #: editor/editor_node.cpp -#, fuzzy msgid "Error while parsing '%s'." -msgstr "Error saat menyimpan." +msgstr "Kesalahan saat melakukan parsing '%s'." #: editor/editor_node.cpp msgid "Unexpected end of file '%s'." msgstr "akhir dari berkas tak terduga '%s'." #: editor/editor_node.cpp -#, fuzzy msgid "Missing '%s' or its dependencies." -msgstr "Scene '%s' memiliki dependensi yang rusak:" +msgstr "'%s' hilang atau memiliki dependensi yang rusak." #: editor/editor_node.cpp -#, fuzzy msgid "Error while loading '%s'." -msgstr "Error saat menyimpan." +msgstr "Terjadi kesalahan saat memuat '%s'." #: editor/editor_node.cpp msgid "Saving Scene" @@ -1513,15 +1470,15 @@ msgstr "Membuat Thumbnail" #: editor/editor_node.cpp #, fuzzy msgid "This operation can't be done without a tree root." -msgstr "Tindakan ini tidak dapat dibatalkan. Pulihkan saja?" +msgstr "Tindakan ini tidak bisa dilakukan tanpa \"tree root\"" #: editor/editor_node.cpp -#, fuzzy msgid "" "Couldn't save scene. Likely dependencies (instances or inheritance) couldn't " "be satisfied." msgstr "" -"Tidak dapat menyimpan scene. Dependensi (instance) mungkin tidak terpenuhi." +"Tidak dapat menyimpan scene. Dependensi (instance atau turunannya) mungkin " +"tidak terpenuhi." #: editor/editor_node.cpp msgid "Failed to load resource." @@ -1532,9 +1489,8 @@ msgid "Can't load MeshLibrary for merging!" msgstr "Tidak dapat memuat MeshLibrary untuk menggabungkan!" #: editor/editor_node.cpp -#, fuzzy msgid "Error saving MeshLibrary!" -msgstr "Error menyimpan MeshLibrary!" +msgstr "Terjadi kesalahan saat menyimpan MeshLibrary!" #: editor/editor_node.cpp msgid "Can't load TileSet for merging!" @@ -1650,15 +1606,14 @@ msgid "There is no defined scene to run." msgstr "Tidak ada definisi scene untuk dijalankan." #: editor/editor_node.cpp -#, fuzzy msgid "" "No main scene has ever been defined, select one?\n" "You can change it later in \"Project Settings\" under the 'application' " "category." msgstr "" "Tidak ada scene utama yang pernah didefinisikan, pilih satu?\n" -"Anda dapat mengubahnya nanti di akhir dalam \"Project Settings\" dibawah " -"kategori 'application'." +"Anda dapat mengubahnya nanti di \"Project Settings\" di bawah kategori " +"'application'." #: editor/editor_node.cpp msgid "" @@ -1707,9 +1662,8 @@ msgid "Quick Open Script.." msgstr "Buka Cepat Script.." #: editor/editor_node.cpp -#, fuzzy msgid "Save & Close" -msgstr "Simpan sebuah File" +msgstr "Simpan & Tutup" #: editor/editor_node.cpp msgid "Save changes to '%s' before closing?" @@ -1740,9 +1694,8 @@ msgid "Export Mesh Library" msgstr "Ekspor Mesh Library" #: editor/editor_node.cpp -#, fuzzy msgid "This operation can't be done without a root node." -msgstr "Tindakan ini tidak dapat dibatalkan. Pulihkan saja?" +msgstr "Tindakan ini tidak bisa dilakukan tanpa node dasar." #: editor/editor_node.cpp msgid "Export Tile Set" @@ -1785,19 +1738,16 @@ msgid "Open Project Manager?" msgstr "Buka Project Manager?" #: editor/editor_node.cpp -#, fuzzy msgid "Save & Quit" -msgstr "Simpan sebuah File" +msgstr "Simpan & Keluar" #: editor/editor_node.cpp -#, fuzzy msgid "Save changes to the following scene(s) before quitting?" -msgstr "Simpan perubahan saat ini sebelum keluar?" +msgstr "Simpan perubahan scene saat ini sebelum keluar?" #: editor/editor_node.cpp -#, fuzzy msgid "Save changes the following scene(s) before opening Project Manager?" -msgstr "Simpan perubahan saat ini sebelum membuka Manajer Projek?" +msgstr "Simpan perubahan scene saat ini sebelum membuka Manajer Projek?" #: editor/editor_node.cpp msgid "" @@ -1823,9 +1773,8 @@ msgstr "" "Tidak dapat mencari bidang script untuk addon plugin pada: 'res://addons/%s'." #: editor/editor_node.cpp -#, fuzzy msgid "Unable to load addon script from path: '%s'." -msgstr "Error memuat font." +msgstr "Tidak bisa memuat script addon dari lokasi: '%s'." #: editor/editor_node.cpp msgid "" @@ -1887,17 +1836,14 @@ msgid "Switch Scene Tab" msgstr "Pilih Tab Scene" #: editor/editor_node.cpp -#, fuzzy msgid "%d more files or folders" msgstr "%d file atau folder lagi" #: editor/editor_node.cpp -#, fuzzy msgid "%d more folders" -msgstr "%d file lagi" +msgstr "%d folder lagi" #: editor/editor_node.cpp -#, fuzzy msgid "%d more files" msgstr "%d file lagi" @@ -1915,9 +1861,8 @@ msgid "Toggle distraction-free mode." msgstr "Mode Tanpa Gangguan" #: editor/editor_node.cpp -#, fuzzy msgid "Add a new scene." -msgstr "Tambah tracks baru." +msgstr "Tambah scene baru." #: editor/editor_node.cpp msgid "Scene" @@ -2117,9 +2062,8 @@ msgstr "" "jaringan filesystem." #: editor/editor_node.cpp -#, fuzzy msgid "Editor" -msgstr "Edit" +msgstr "Editor" #: editor/editor_node.cpp editor/settings_config_dialog.cpp msgid "Editor Settings" @@ -2130,14 +2074,12 @@ msgid "Editor Layout" msgstr "Tata Letak Editor" #: editor/editor_node.cpp -#, fuzzy msgid "Toggle Fullscreen" msgstr "Mode Layar Penuh" #: editor/editor_node.cpp editor/project_export.cpp -#, fuzzy msgid "Manage Export Templates" -msgstr "Memuat Ekspor Template-template." +msgstr "Mengatur Templat Ekspor" #: editor/editor_node.cpp msgid "Help" @@ -2145,7 +2087,7 @@ msgstr "Bantuan" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Classes" -msgstr "" +msgstr "Kelas" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp #: editor/plugins/script_editor_plugin.cpp @@ -2160,7 +2102,7 @@ msgstr "Online Dokumentasi" #: editor/editor_node.cpp msgid "Q&A" -msgstr "" +msgstr "Tanya Jawab" #: editor/editor_node.cpp msgid "Issue Tracker" @@ -2184,11 +2126,11 @@ msgstr "Mainkan" #: editor/editor_node.cpp msgid "Pause the scene" -msgstr "" +msgstr "Hentikan sementara scene ini" #: editor/editor_node.cpp msgid "Pause Scene" -msgstr "" +msgstr "Hentikan Sementara Scene" #: editor/editor_node.cpp msgid "Stop the scene." @@ -2276,9 +2218,8 @@ msgid "Import" msgstr "Impor" #: editor/editor_node.cpp -#, fuzzy msgid "Node" -msgstr "Titik" +msgstr "" #: editor/editor_node.cpp msgid "FileSystem" @@ -2293,7 +2234,6 @@ msgid "Don't Save" msgstr "Jangan Simpan" #: editor/editor_node.cpp -#, fuzzy msgid "Import Templates From ZIP File" msgstr "Impor Templat dari Berkas ZIP" @@ -2306,7 +2246,6 @@ msgid "Export Library" msgstr "Ekspor Pustaka" #: editor/editor_node.cpp -#, fuzzy msgid "Merge With Existing" msgstr "Gabung dengan yang Ada" @@ -2319,12 +2258,10 @@ msgid "Open & Run a Script" msgstr "Buka & Jalankan Skrip" #: editor/editor_node.cpp -#, fuzzy msgid "New Inherited" -msgstr "Scene Turunan Baru.." +msgstr "Turunan Baru" #: editor/editor_node.cpp -#, fuzzy msgid "Load Errors" msgstr "Muat Galat" @@ -2333,12 +2270,10 @@ msgid "Select" msgstr "Pilih" #: editor/editor_node.cpp -#, fuzzy msgid "Open 2D Editor" msgstr "Buka Penyunting 2D" #: editor/editor_node.cpp -#, fuzzy msgid "Open 3D Editor" msgstr "Buka Penyunting 3D" @@ -2385,7 +2320,7 @@ msgstr "Pembuat:" #: editor/editor_plugin_settings.cpp msgid "Status:" -msgstr "" +msgstr "Status:" #: editor/editor_profiler.cpp msgid "Stop Profiling" @@ -2432,12 +2367,10 @@ msgid "Frame #:" msgstr "Bingkai #:" #: editor/editor_profiler.cpp -#, fuzzy msgid "Time" -msgstr "Waktu:" +msgstr "Waktu" #: editor/editor_profiler.cpp -#, fuzzy msgid "Calls" msgstr "Panggil" @@ -2450,79 +2383,80 @@ msgid "" "No runnable export preset found for this platform.\n" "Please add a runnable preset in the export menu." msgstr "" +"Tidak ada preset ekspor yang bisa digunakan untuk platform ini.\n" +"Mohon tambahkan preset yang bisa digunakan di menu ekspor." #: editor/editor_run_script.cpp msgid "Write your logic in the _run() method." -msgstr "" +msgstr "Tulis logika di dalam fungsi _run()." #: editor/editor_run_script.cpp msgid "There is an edited scene already." -msgstr "" +msgstr "Ada scene yang disunting." #: editor/editor_run_script.cpp msgid "Couldn't instance script:" -msgstr "" +msgstr "Tidak bisa meng-instance script:" #: editor/editor_run_script.cpp msgid "Did you forget the 'tool' keyword?" -msgstr "" +msgstr "Apakah anda lupa dengan kata kunci 'tool'?" #: editor/editor_run_script.cpp msgid "Couldn't run script:" -msgstr "" +msgstr "Tidak bisa menjalankan script:" #: editor/editor_run_script.cpp msgid "Did you forget the '_run' method?" -msgstr "" +msgstr "Apakah anda lupa dengan fungsi '_run' ?" #: editor/editor_settings.cpp msgid "Default (Same as Editor)" -msgstr "" +msgstr "Baku (Samakan seperti Penyunting saat ini)" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" -msgstr "" +msgstr "Pilih node untuk diimpor" #: editor/editor_sub_scene.cpp msgid "Scene Path:" -msgstr "" +msgstr "Lokasi Scene:" #: editor/editor_sub_scene.cpp msgid "Import From Node:" -msgstr "" +msgstr "Impor dari Node:" #: editor/export_template_manager.cpp msgid "Re-Download" -msgstr "" +msgstr "Unduh Ulang" #: editor/export_template_manager.cpp msgid "Uninstall" -msgstr "" +msgstr "Copot Pemasangan" #: editor/export_template_manager.cpp msgid "(Installed)" -msgstr "" +msgstr "(terpasang)" #: editor/export_template_manager.cpp msgid "Download" -msgstr "" +msgstr "Unduh" #: editor/export_template_manager.cpp msgid "(Missing)" -msgstr "" +msgstr "(hilang)" #: editor/export_template_manager.cpp msgid "(Current)" -msgstr "" +msgstr "(Kondisi Saat Ini)" #: editor/export_template_manager.cpp -#, fuzzy msgid "Retrieving mirrors, please wait.." -msgstr "Gangguan koneks, silakan coba lagi." +msgstr "Mendapatkan informasi cermin, silakan tunggu.." #: editor/export_template_manager.cpp msgid "Remove template version '%s'?" -msgstr "" +msgstr "Hapus templat versi '%s'?" #: editor/export_template_manager.cpp msgid "Can't open export templates zip." @@ -2530,27 +2464,19 @@ msgstr "Tidak dapat membuka ekspor template-template zip." #: editor/export_template_manager.cpp msgid "Invalid version.txt format inside templates." -msgstr "" - -#: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" +msgstr "Format version.txt tidak valid dalam berkas templat." #: editor/export_template_manager.cpp msgid "No version.txt found inside templates." -msgstr "" +msgstr "Berkas version.txt tidak ditemukan dalam templat." #: editor/export_template_manager.cpp -#, fuzzy msgid "Error creating path for templates:" -msgstr "Gagal menyimpan atlas:" +msgstr "Kesalahan saat membuat lokasi untuk templat:" #: editor/export_template_manager.cpp -#, fuzzy msgid "Extracting Export Templates" -msgstr "Memuat Ekspor Template-template." +msgstr "Mengekstrak Berkas Templat Ekspor" #: editor/export_template_manager.cpp msgid "Importing:" @@ -2561,17 +2487,18 @@ msgid "" "No download links found for this version. Direct download is only available " "for official releases." msgstr "" +"Tautan unduh tidak ditemukan untuk versi ini. Unduhan langsung hanya " +"tersedia untuk versi rilis resmi." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't resolve." -msgstr "" +msgstr "Tidak bisa menyelesaikan." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Can't connect." -msgstr "Menyambungkan.." +msgstr "Tidak dapat terhubung." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -2580,9 +2507,8 @@ msgstr "Tidak ada respon." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Request Failed." -msgstr "Menguji" +msgstr "Permintaan Gagal." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -2592,31 +2518,23 @@ msgstr "" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed:" -msgstr "" - -#: editor/export_template_manager.cpp -#, fuzzy -msgid "Can't write file." -msgstr "Tidak dapat membuat folder." +msgstr "Gagal:" #: editor/export_template_manager.cpp msgid "Download Complete." -msgstr "" +msgstr "Unduhan Selesai." #: editor/export_template_manager.cpp -#, fuzzy msgid "Error requesting url: " -msgstr "Gagal menyimpan atlas:" +msgstr "Kesalahan saat meminta url: " #: editor/export_template_manager.cpp -#, fuzzy msgid "Connecting to Mirror.." msgstr "Menyambungkan.." #: editor/export_template_manager.cpp -#, fuzzy msgid "Disconnected" -msgstr "Tidak tersambung" +msgstr "Terputus" #: editor/export_template_manager.cpp msgid "Resolving" @@ -2628,160 +2546,146 @@ msgstr "" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Connecting.." msgstr "Menyambungkan.." #: editor/export_template_manager.cpp -#, fuzzy msgid "Can't Connect" -msgstr "Menyambungkan.." +msgstr "Tidak dapat terhubung" #: editor/export_template_manager.cpp -#, fuzzy msgid "Connected" -msgstr "Menghubungkan" +msgstr "Terhubung" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Requesting.." -msgstr "Menguji" +msgstr "Melakukan permintaan.." #: editor/export_template_manager.cpp -#, fuzzy msgid "Downloading" -msgstr "Error memuat:" +msgstr "Mengunduh" #: editor/export_template_manager.cpp -#, fuzzy msgid "Connection Error" -msgstr "Menyambungkan.." +msgstr "Gangguan Koneksi" #: editor/export_template_manager.cpp -#, fuzzy msgid "SSL Handshake Error" -msgstr "Muat Galat" +msgstr "Kesalahan jabat tangan SSL" #: editor/export_template_manager.cpp msgid "Current Version:" -msgstr "" +msgstr "Versi sekarang:" #: editor/export_template_manager.cpp msgid "Installed Versions:" -msgstr "" +msgstr "Versi Terpasang:" #: editor/export_template_manager.cpp msgid "Install From File" -msgstr "" +msgstr "Memasang dari berkas" #: editor/export_template_manager.cpp -#, fuzzy msgid "Remove Template" -msgstr "Hapus Pilihan" +msgstr "Hapus Templat" #: editor/export_template_manager.cpp -#, fuzzy msgid "Select template file" -msgstr "Hapus file yang dipilih?" +msgstr "Pilih berkas templat" #: editor/export_template_manager.cpp -#, fuzzy msgid "Export Template Manager" -msgstr "Memuat Ekspor Template-template." +msgstr "Manajer Templat Ekspor" #: editor/export_template_manager.cpp -#, fuzzy msgid "Download Templates" -msgstr "Hapus Pilihan" +msgstr "Unduh Templat" #: editor/export_template_manager.cpp msgid "Select mirror from list: " -msgstr "" +msgstr "Pilih cermin dari daftar: " #: editor/file_type_cache.cpp msgid "Can't open file_type_cache.cch for writing, not saving file type cache!" msgstr "" +"Tidak dapat membuka file_type_cache.cch untuk menulis, berkas cache tidak " +"disimpan!" #: editor/filesystem_dock.cpp msgid "Cannot navigate to '%s' as it has not been found in the file system!" msgstr "" +"'%s' tidak bisa ditelusuri karena tidak bisa ditemukan dalam berkas sistem!" #: editor/filesystem_dock.cpp msgid "View items as a grid of thumbnails" -msgstr "" +msgstr "Tampilkan item sebagai grid thumbnail" #: editor/filesystem_dock.cpp msgid "View items as a list" -msgstr "" +msgstr "Tampilkan item sebagai daftar" #: editor/filesystem_dock.cpp msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" +"Status: Gagal mengimpor berkas. Mohon perbaiki berkas dan impor ulang secara " +"manual." #: editor/filesystem_dock.cpp msgid "Cannot move/rename resources root." -msgstr "" +msgstr "Tidak bisa memindah/mengubah nama aset root." #: editor/filesystem_dock.cpp msgid "Cannot move a folder into itself." -msgstr "" +msgstr "Tidak dapat memindahkan folder ke dalam dirinya sendiri." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Error moving:" -msgstr "Error memuat:" +msgstr "Galat saat memindahkan:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Error duplicating:" -msgstr "Error saat memuat:" +msgstr "Galat saat menggandakan berkas:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Unable to update dependencies:" -msgstr "Scene '%s' memiliki dependensi yang rusak:" +msgstr "Tidak bisa memperbarui dependensi:" #: editor/filesystem_dock.cpp msgid "No name provided" -msgstr "" +msgstr "Nama masih kosong" #: editor/filesystem_dock.cpp msgid "Provided name contains invalid characters" -msgstr "" +msgstr "Nama yang dimasukkan tidak valid" #: editor/filesystem_dock.cpp -#, fuzzy msgid "No name provided." -msgstr "Ubah Nama atau Pindahkan.." +msgstr "Nama masih kosong." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Name contains invalid characters." -msgstr "Karakter sah:" +msgstr "Nama mengandung karakter tidak valid." #: editor/filesystem_dock.cpp msgid "A file or folder with this name already exists." -msgstr "" +msgstr "Sudah ada nama berkas atau folder seperti itu." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Renaming file:" -msgstr "Namai kembali Variabel" +msgstr "Mengubah nama berkas dengan:" #: editor/filesystem_dock.cpp msgid "Renaming folder:" -msgstr "" +msgstr "Mengubah nama folder dengan:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicating file:" -msgstr "Gandakan" +msgstr "Menggandakan berkas:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicating folder:" -msgstr "Gandakan" +msgstr "Menggandakan folder:" #: editor/filesystem_dock.cpp msgid "Expand all" @@ -2792,16 +2696,14 @@ msgid "Collapse all" msgstr "" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Rename.." -msgstr "Ubah Nama atau Pindahkan.." +msgstr "Ubah Nama.." #: editor/filesystem_dock.cpp msgid "Move To.." -msgstr "Pindah Ke.." +msgstr "Pindahkan ke.." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Open Scene(s)" msgstr "Buka Scene" @@ -2811,16 +2713,15 @@ msgstr "" #: editor/filesystem_dock.cpp msgid "Edit Dependencies.." -msgstr "" +msgstr "Sunting Dependensi.." #: editor/filesystem_dock.cpp msgid "View Owners.." -msgstr "" +msgstr "Tampilkan Pemilik Berkas.." #: editor/filesystem_dock.cpp -#, fuzzy msgid "Duplicate.." -msgstr "Gandakan" +msgstr "Gandakan.." #: editor/filesystem_dock.cpp msgid "Previous Directory" @@ -2836,14 +2737,13 @@ msgstr "Pindai Ulang Berkas Sistem" #: editor/filesystem_dock.cpp msgid "Toggle folder status as Favorite" -msgstr "" +msgstr "Kondisikan status folder sebagai Favorit" #: editor/filesystem_dock.cpp msgid "Instance the selected scene(s) as child of the selected node." -msgstr "" +msgstr "Instance scene terpilih sebagai anak node saat ini." #: editor/filesystem_dock.cpp -#, fuzzy msgid "" "Scanning Files,\n" "Please Wait.." @@ -2858,7 +2758,7 @@ msgstr "Pindahkan" #: editor/filesystem_dock.cpp editor/plugins/animation_tree_editor_plugin.cpp #: editor/project_manager.cpp msgid "Rename" -msgstr "" +msgstr "Ubah Nama" #: editor/groups_editor.cpp msgid "Add to Group" @@ -2866,112 +2766,110 @@ msgstr "Tambahkan ke Grup" #: editor/groups_editor.cpp msgid "Remove from Group" -msgstr "" +msgstr "Hapus dari Grup" #: editor/import/resource_importer_scene.cpp -#, fuzzy msgid "Import as Single Scene" -msgstr "Memperbaharui Scene" +msgstr "Impor sebagai Scene Tunggal" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Animations" -msgstr "" +msgstr "Impor dengan Animasi Terpisah" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials" -msgstr "" +msgstr "Impor dengan Material Terpisah" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects" -msgstr "" +msgstr "Impor dengan Objek Terpisah" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Materials" -msgstr "" +msgstr "Impor dengan Objek+Material Terpisah" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Animations" -msgstr "" +msgstr "Impor dengan Objek+Animasi Terpisah" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials+Animations" -msgstr "" +msgstr "Impor dengan Material+Animasi Terpisah" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Materials+Animations" -msgstr "" +msgstr "Impor dengan Objek+Material+Animasi Terpisah" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes" -msgstr "" +msgstr "Impor sebagai Beberapa Scene" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes+Materials" -msgstr "" +msgstr "Impor Beberapa Scene+Material" #: editor/import/resource_importer_scene.cpp #: editor/plugins/cube_grid_theme_editor_plugin.cpp msgid "Import Scene" -msgstr "" +msgstr "Impor Scene" #: editor/import/resource_importer_scene.cpp msgid "Importing Scene.." -msgstr "" +msgstr "Mengimpor scene.." #: editor/import/resource_importer_scene.cpp +#, fuzzy msgid "Generating Lightmaps" -msgstr "" +msgstr "Sedang Membuat Pemetaan Cahaya" #: editor/import/resource_importer_scene.cpp msgid "Generating for Mesh: " msgstr "" #: editor/import/resource_importer_scene.cpp +#, fuzzy msgid "Running Custom Script.." -msgstr "" +msgstr "Menjalankan Skrip Buatan.." #: editor/import/resource_importer_scene.cpp msgid "Couldn't load post-import script:" -msgstr "" +msgstr "Tidak dapat memuat skrip post-import:" #: editor/import/resource_importer_scene.cpp msgid "Invalid/broken script for post-import (check console):" -msgstr "" +msgstr "Skrip post-import rusak/tidak valid (cek konsol):" #: editor/import/resource_importer_scene.cpp msgid "Error running post-import script:" -msgstr "" +msgstr "Kesalahan saat menjalankan skrip post-import:" #: editor/import/resource_importer_scene.cpp msgid "Saving.." -msgstr "" +msgstr "Menyimpan.." #: editor/import_dock.cpp msgid "Set as Default for '%s'" -msgstr "" +msgstr "Jadikan Baku untuk '%s'" #: editor/import_dock.cpp msgid "Clear Default for '%s'" -msgstr "" +msgstr "Bersihkan Baku untuk '%s'" #: editor/import_dock.cpp -#, fuzzy msgid " Files" -msgstr "File:" +msgstr " Berkas" #: editor/import_dock.cpp -#, fuzzy msgid "Import As:" -msgstr "Mengimpor:" +msgstr "Impor sebagai:" #: editor/import_dock.cpp editor/property_editor.cpp msgid "Preset.." msgstr "" #: editor/import_dock.cpp -#, fuzzy msgid "Reimport" -msgstr "Mengimpor ulang" +msgstr "Impor ulang" #: editor/multi_node_edit.cpp msgid "MultiNode Set" @@ -2979,97 +2877,105 @@ msgstr "" #: editor/node_dock.cpp msgid "Groups" -msgstr "" +msgstr "Grup" #: editor/node_dock.cpp msgid "Select a Node to edit Signals and Groups." -msgstr "" +msgstr "Pilih sebuah node untuk menyunting Sinyal dan Grup." #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp +#, fuzzy msgid "Create Poly" -msgstr "" +msgstr "Buat Bidang" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/collision_polygon_editor_plugin.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp +#, fuzzy msgid "Edit Poly" -msgstr "" +msgstr "Sunting Bidang" #: editor/plugins/abstract_polygon_2d_editor.cpp msgid "Insert Point" -msgstr "" +msgstr "Tambah Titik" #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/collision_polygon_editor_plugin.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Edit Poly (Remove Point)" -msgstr "" +msgstr "Sunting Bidang (Hapus Titik)" #: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy msgid "Remove Poly And Point" -msgstr "" +msgstr "Hapus Bidang dan Titik" #: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy msgid "Create a new polygon from scratch" -msgstr "" +msgstr "Buat bidang baru dari awal" #: editor/plugins/abstract_polygon_2d_editor.cpp +#, fuzzy msgid "" "Edit existing polygon:\n" "LMB: Move Point.\n" "Ctrl+LMB: Split Segment.\n" "RMB: Erase Point." msgstr "" +"Sunting bidang yang ada:\n" +"LMB: Pindahkan Titik.\n" +"Ctrl+LMB: Pecah Segmen.\n" +"RMB: Hapus Titik." #: editor/plugins/abstract_polygon_2d_editor.cpp -#, fuzzy msgid "Delete points" -msgstr "Hapus" +msgstr "Hapus Titik" #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Toggle Autoplay" -msgstr "" +msgstr "Kondisikan Putar Otomatis" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Animation Name:" -msgstr "" +msgstr "Nama Animasi Baru:" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Anim" -msgstr "" +msgstr "Animasi Baru" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Change Animation Name:" -msgstr "" +msgstr "Ubah Nama Animasi:" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Delete Animation?" -msgstr "Optimalkan Animasi" +msgstr "Hapus Animasi?" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Remove Animation" -msgstr "" +msgstr "Hapus Animasi" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: Invalid animation name!" -msgstr "" +msgstr "KESALAHAN: Nama animasi tidak valid!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: Animation name already exists!" -msgstr "" +msgstr "KESALAHAN: Nama animasi sudah ada!" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Rename Animation" -msgstr "" +msgstr "Ubah Nama Animasi" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Add Animation" -msgstr "" +msgstr "Tambah Animasi" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Blend Next Changed" @@ -3081,95 +2987,106 @@ msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Load Animation" -msgstr "" +msgstr "Muat Animasi" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Duplicate Animation" -msgstr "" +msgstr "Gandakan Animasi" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: No animation to copy!" -msgstr "" +msgstr "KESALAHAN: Tidak ada animasi untuk disalin!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "ERROR: No animation resource on clipboard!" -msgstr "" +msgstr "KESALAHAN: Tidak ada aset animasi di clipboard!" #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Pasted Animation" -msgstr "" +msgstr "Animasi Ditempel" #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Paste Animation" -msgstr "" +msgstr "Tempelkan Animasi" #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "ERROR: No animation to edit!" -msgstr "" +msgstr "KESALAHAN: Tidak ada animasi untuk disunting!" #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Play selected animation backwards from current pos. (A)" -msgstr "" +msgstr "Mainkan mundur animasi terpilih dari lokasi sekarang. (A)" #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Play selected animation backwards from end. (Shift+A)" -msgstr "" +msgstr "Mainkan mundur animasi terpilih dari akhir. (Shift+A)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Stop animation playback. (S)" -msgstr "" +msgstr "Hentikan playback animasi. (S)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from start. (Shift+D)" -msgstr "" +msgstr "Mainkan animasi terpilih dari awal. (Shift+D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from current pos. (D)" -msgstr "" +msgstr "Mainkan animasi terpilih dari posisi sekarang. (D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation position (in seconds)." -msgstr "" +msgstr "Posisi Animasi (dalam detik)." #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Scale animation playback globally for the node." -msgstr "" +msgstr "Skalakan playback animasi secara global untuk node ini." #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Create new animation in player." -msgstr "" +msgstr "Buat animasi baru dalam pemutar animasi." #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Load animation from disk." -msgstr "" +msgstr "Memuat animasi dari diska." #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Load an animation from disk." -msgstr "" +msgstr "Memuat animasi dari diska." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Save the current animation" -msgstr "" +msgstr "Simpan animasi saat ini" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Display list of animations in player." -msgstr "" +msgstr "Tampilkan daftar animasi dalam pemutar animasi." #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Autoplay on Load" -msgstr "" +msgstr "Putar Otomatis saat Dimuat" #: editor/plugins/animation_player_editor_plugin.cpp +#, fuzzy msgid "Edit Target Blend Times" -msgstr "" +msgstr "Sunting Target Waktu Blend" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Tools" -msgstr "" +msgstr "Perkakas Animasi" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Copy Animation" -msgstr "" +msgstr "Salin Animasi" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Onion Skinning" @@ -3199,19 +3116,19 @@ msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp msgid "1 step" -msgstr "" +msgstr "1 langkah" #: editor/plugins/animation_player_editor_plugin.cpp msgid "2 steps" -msgstr "" +msgstr "2 langkah" #: editor/plugins/animation_player_editor_plugin.cpp msgid "3 steps" -msgstr "" +msgstr "3 langkah" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Differences Only" -msgstr "" +msgstr "Hanya yang berbeda" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Force White Modulate" @@ -3223,18 +3140,18 @@ msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Create New Animation" -msgstr "" +msgstr "Buat Animasi Baru" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Name:" -msgstr "" +msgstr "Nama Animasi:" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: editor/script_create_dialog.cpp msgid "Error!" -msgstr "" +msgstr "Kesalahan!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Blend Times:" @@ -3255,12 +3172,12 @@ msgstr "Animasi" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "New name:" -msgstr "" +msgstr "Nama baru:" #: editor/plugins/animation_tree_editor_plugin.cpp #, fuzzy msgid "Edit Filters" -msgstr "File:" +msgstr "Sunting Filter" #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/multimesh_editor_plugin.cpp @@ -3389,8 +3306,9 @@ msgid "Import Animations.." msgstr "" #: editor/plugins/animation_tree_editor_plugin.cpp +#, fuzzy msgid "Edit Node Filters" -msgstr "" +msgstr "Sunting Filter Node" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Filters.." @@ -3420,27 +3338,26 @@ msgid "Can't resolve hostname:" msgstr "" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Connection error, please try again." -msgstr "Gangguan koneks, silakan coba lagi." +msgstr "Gangguan koneksi, silakan coba lagi." #: editor/plugins/asset_library_editor_plugin.cpp #, fuzzy msgid "Can't connect to host:" -msgstr "Sambungkan Ke Node:" +msgstr "Tidak bisa terhubung ke host:" #: editor/plugins/asset_library_editor_plugin.cpp +#, fuzzy msgid "No response from host:" -msgstr "" +msgstr "Tidak ada respon dari host:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Request failed, return code:" -msgstr "Format file yang diminta tidak diketahui:" +msgstr "Permintaan gagal, return code:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request failed, too many redirects" -msgstr "" +msgstr "Permintaan gagal, terlalu banyak pengalihan" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Bad download hash, assuming file has been tampered with." @@ -3455,12 +3372,13 @@ msgid "Got:" msgstr "" #: editor/plugins/asset_library_editor_plugin.cpp +#, fuzzy msgid "Failed sha256 hash check" -msgstr "" +msgstr "Gagal mengecek hash sha256" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" -msgstr "" +msgstr "Gagal Mengunduh Aset:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Fetching:" @@ -3471,9 +3389,8 @@ msgid "Resolving.." msgstr "" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Error making request" -msgstr "Error menyimpan resource!" +msgstr "Kesalahan saat melakukan permintaan" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Idle" @@ -3485,27 +3402,27 @@ msgstr "" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download Error" -msgstr "" +msgstr "Unduhan Gagal" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download for this asset is already in progress!" -msgstr "" +msgstr "Unduhan untuk aset ini sedang diproses!" #: editor/plugins/asset_library_editor_plugin.cpp msgid "first" -msgstr "" +msgstr "pertama" #: editor/plugins/asset_library_editor_plugin.cpp msgid "prev" -msgstr "" +msgstr "sebelumnya" #: editor/plugins/asset_library_editor_plugin.cpp msgid "next" -msgstr "" +msgstr "selanjutnya" #: editor/plugins/asset_library_editor_plugin.cpp msgid "last" -msgstr "" +msgstr "terakhir" #: editor/plugins/asset_library_editor_plugin.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp @@ -3515,7 +3432,7 @@ msgstr "Semua" #: editor/plugins/asset_library_editor_plugin.cpp #: editor/project_settings_editor.cpp msgid "Plugins" -msgstr "" +msgstr "Pengaya" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Sort:" @@ -3548,14 +3465,18 @@ msgstr "Menguji" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" -msgstr "Aset-aset File ZIP" +msgstr "Berkas Aset ZIP" #: editor/plugins/baked_lightmap_editor_plugin.cpp +#, fuzzy msgid "" "Can't determine a save path for lightmap images.\n" "Save your scene (for images to be saved in the same dir), or pick a save " "path from the BakedLightmap properties." msgstr "" +"Tidak dapat menentukan lokasi penyimpanan untuk gambar lightmap\n" +"Simpan scene-mu (untuk gambar silakan simpan di direktori yang sama dengan " +"scene), atau tentukan lokasi penyimpanan dari properti BakedLightmap" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" @@ -3575,11 +3496,11 @@ msgstr "Ganti Radius Lampu" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Preview" -msgstr "" +msgstr "Pratinjau" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap" -msgstr "" +msgstr "Atur Snap" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -3640,12 +3561,14 @@ msgid "Create new horizontal and vertical guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy msgid "Edit IK Chain" -msgstr "" +msgstr "Sunting Rantai IK" #: editor/plugins/canvas_item_editor_plugin.cpp +#, fuzzy msgid "Edit CanvasItem" -msgstr "" +msgstr "Sunting CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" @@ -3812,15 +3735,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4006,8 +3929,9 @@ msgid "Toggle Curve Linear Tangent" msgstr "" #: editor/plugins/curve_editor_plugin.cpp +#, fuzzy msgid "Hold Shift to edit tangents individually" -msgstr "" +msgstr "Tahan Shift untuk menyunting tangen kurva satu-persatu" #: editor/plugins/gi_probe_editor_plugin.cpp msgid "Bake GI Probe" @@ -4031,8 +3955,9 @@ msgid "Items" msgstr "" #: editor/plugins/item_list_editor_plugin.cpp +#, fuzzy msgid "Item List Editor" -msgstr "" +msgstr "Penyunting Daftar Item" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "" @@ -4049,8 +3974,9 @@ msgid "Create a new polygon from scratch." msgstr "" #: editor/plugins/light_occluder_2d_editor_plugin.cpp +#, fuzzy msgid "Edit existing polygon:" -msgstr "" +msgstr "Sunting poligon yang ada:" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "LMB: Move Point." @@ -4572,8 +4498,9 @@ msgid "Transform UV Map" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp +#, fuzzy msgid "Polygon 2D UV Editor" -msgstr "" +msgstr "Penyunting UV Poligon 2D" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Move Point" @@ -4609,7 +4536,7 @@ msgstr "" #: editor/project_settings_editor.cpp editor/property_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Edit" -msgstr "Edit" +msgstr "Sunting" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Polygon->UV" @@ -4658,6 +4585,23 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +#, fuzzy +msgid "Open in Editor" +msgstr "Buka dalam Penyunting" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4837,7 +4781,7 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp #, fuzzy msgid "Debug with external editor" -msgstr "Editor Ketergantungan" +msgstr "Debug menggunakan penyunting eksternal" #: editor/plugins/script_editor_plugin.cpp msgid "Open Godot online documentation" @@ -4853,11 +4797,12 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "Go to previous edited document." -msgstr "" +msgstr "Ke dokumen yang disunting sebelumnya." #: editor/plugins/script_editor_plugin.cpp +#, fuzzy msgid "Go to next edited document." -msgstr "" +msgstr "Ke dokumen yang disunting selanjutnya." #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -4889,7 +4834,7 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp msgid "" "Built-in scripts can only be edited when the scene they belong to is loaded" -msgstr "" +msgstr "Skrip built-in hanya bisa disunting ketika scene induknya dimuat" #: editor/plugins/script_text_editor.cpp msgid "Only resources from filesystem can be dropped." @@ -4949,10 +4894,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Pergi ke Baris" @@ -4966,6 +4907,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5717,8 +5662,9 @@ msgid "Texture Region" msgstr "" #: editor/plugins/texture_region_editor_plugin.cpp +#, fuzzy msgid "Texture Region Editor" -msgstr "" +msgstr "Penyunting Daerah Tekstur" #: editor/plugins/theme_editor_plugin.cpp msgid "Can't save theme to file:" @@ -5749,11 +5695,11 @@ msgstr "Hapus" #: editor/plugins/theme_editor_plugin.cpp msgid "Edit theme.." -msgstr "" +msgstr "Sunting tema.." #: editor/plugins/theme_editor_plugin.cpp msgid "Theme editing menu." -msgstr "" +msgstr "Menu untuk menyunting tema." #: editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" @@ -5768,12 +5714,14 @@ msgid "Create Empty Template" msgstr "" #: editor/plugins/theme_editor_plugin.cpp +#, fuzzy msgid "Create Empty Editor Template" -msgstr "" +msgstr "Buat Templat Penyunting Kosongan" #: editor/plugins/theme_editor_plugin.cpp +#, fuzzy msgid "Create From Current Editor Theme" -msgstr "" +msgstr "Buat dari Tema Editor Saat Ini" #: editor/plugins/theme_editor_plugin.cpp msgid "CheckBox Radio1" @@ -5823,11 +5771,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -6099,10 +6042,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -6124,12 +6063,14 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." -msgstr "" +msgstr "Tidak dapat menyunting project.godot dalam lokasi proyek." #: editor/project_manager.cpp msgid "Couldn't create project.godot in project path." @@ -6145,10 +6086,6 @@ msgid "Rename Project" msgstr "Projek Baru Permainan" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp #, fuzzy msgid "New Game Project" msgstr "Projek Baru Permainan" @@ -6158,27 +6095,24 @@ msgid "Import Existing Project" msgstr "Impor Projek yang Sudah Ada" #: editor/project_manager.cpp -#, fuzzy msgid "Import & Edit" -msgstr "Impor" +msgstr "Impor & Ubah" #: editor/project_manager.cpp msgid "Create New Project" msgstr "Buat Projek Baru" #: editor/project_manager.cpp -#, fuzzy msgid "Create & Edit" -msgstr "Buat" +msgstr "Buat & Ubah" #: editor/project_manager.cpp msgid "Install Project:" msgstr "" #: editor/project_manager.cpp -#, fuzzy msgid "Install & Edit" -msgstr "Pasang" +msgstr "Pasang & Ubah" #: editor/project_manager.cpp msgid "Project Name:" @@ -6869,10 +6803,6 @@ msgstr "Resource" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6987,10 +6917,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "Buka Cepat Script.." @@ -7436,33 +7362,47 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "Hapus yang Dipilih" +msgid "Next Plane" +msgstr "Tab selanjutnya" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "Duplikat Pilihan" +msgid "Previous Plane" +msgstr "Tab sebelumnya" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +#, fuzzy +msgid "Previous Floor" +msgstr "Tab sebelumnya" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Previous Floor" -msgstr "Tab sebelumnya" +msgid "GridMap Delete Selection" +msgstr "Hapus yang Dipilih" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Duplicate Selection" +msgstr "Duplikat Pilihan" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7576,6 +7516,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Buat Subskribsi" @@ -7593,6 +7537,10 @@ msgstr "Proyek" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8162,6 +8110,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8358,6 +8314,17 @@ msgstr "Error memuat font." msgid "Invalid font size." msgstr "Ukuran font tidak sah." +#, fuzzy +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Format version.txt tidak valid dalam berkas templat. Revisi tidak valid." + +#, fuzzy +#~ msgid "Can't write file." +#~ msgstr "Tidak dapat membuat folder." + #~ msgid "Next" #~ msgstr "Berikutnya" diff --git a/editor/translations/is.po b/editor/translations/is.po index 3cccf15a6c..b0b8698f37 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -2365,12 +2365,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2423,10 +2417,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3590,15 +3580,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4421,6 +4411,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4703,10 +4709,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4719,6 +4721,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5559,11 +5565,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5823,10 +5824,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5847,7 +5844,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5867,10 +5866,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6558,10 +6553,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6671,10 +6662,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7097,11 +7084,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7109,19 +7108,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7229,6 +7228,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7244,6 +7247,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7743,6 +7750,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/it.po b/editor/translations/it.po index 86700a094b..ba1a09e3ad 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -2485,14 +2485,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Formato di version.txt invalido nelle templates." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Formato di version.txt invalido nelle templates. Revision non é un " -"identificatore valido." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Non é stato trovato version.txt all'interno di templates." @@ -2549,10 +2541,6 @@ msgid "Failed:" msgstr "Fallito:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Impossibile scrivere il file." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Download Completato." @@ -3756,16 +3744,16 @@ msgstr "Mostra Griglia" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show helpers" +msgid "Show Helpers" msgstr "Mostra Ossa" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show rulers" +msgid "Show Rulers" msgstr "Mostra Ossa" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Mostra guide" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4624,6 +4612,22 @@ msgid "Resource clipboard is empty!" msgstr "Clipboard risorse vuota!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Apri nell Editor" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Istanza:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Tipo:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Carica Risorsa" @@ -4923,10 +4927,6 @@ msgid "Toggle Comment" msgstr "Cambia a Commento" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Clona Sotto" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Svolgere Linea" @@ -4941,6 +4941,10 @@ msgid "Unfold All Lines" msgstr "Svolgere Tutte le Linee" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Clona Sotto" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Completa Simbolo" @@ -5799,11 +5803,6 @@ msgstr "Tab 2" msgid "Tab 3" msgstr "Tab 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Tipo:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Tipo Dato:" @@ -6082,11 +6081,6 @@ msgid "Please choose an empty folder." msgstr "Si prega di esportare al di fuori della cartella del progetto!" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" -"Per favore seleziona una cartella che non contiene un file 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Progetto Importato" @@ -6109,7 +6103,9 @@ msgstr "Percorso di progetto invalido (cambiato qualcosa?)." #: editor/project_manager.cpp #, fuzzy -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "Impossibile creare project.godot nel percorso di progetto." #: editor/project_manager.cpp @@ -6131,11 +6127,6 @@ msgid "Rename Project" msgstr "Progetto Senza Nome" #: editor/project_manager.cpp -#, fuzzy -msgid "Couldn't get project.godot in the project path." -msgstr "Impossibile creare project.godot nel percorso di progetto." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Nuovo Progetto di Gioco" @@ -6866,10 +6857,6 @@ msgstr "Sub-Risorse:" msgid "Clear Inheritance" msgstr "Liberare ereditarietà " -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Apri nell Editor" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Elimina Nodo(i)" @@ -6991,10 +6978,6 @@ msgstr "" "Fai click per mostrare il dock gruppi." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Istanza:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Apri script" @@ -7436,13 +7419,26 @@ msgstr "L'oggetto non può fornire una lunghezza." #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "Elimina selezionati" +msgid "Next Plane" +msgstr "Scheda successiva" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "Duplica Selezione" +msgid "Previous Plane" +msgstr "Scheda precedente" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Prossimo Piano" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Floor" +msgstr "Scheda precedente" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" @@ -7450,22 +7446,23 @@ msgstr "Piano:" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Grid Map" -msgstr "Snap Griglia" +msgid "GridMap Delete Selection" +msgstr "Elimina selezionati" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Snap View" -msgstr "Vista dall'Alto" +msgid "GridMap Duplicate Selection" +msgstr "Duplica Selezione" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Previous Floor" -msgstr "Scheda precedente" +msgid "Grid Map" +msgstr "Snap Griglia" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Prossimo Piano" +#, fuzzy +msgid "Snap View" +msgstr "Vista dall'Alto" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy @@ -7593,6 +7590,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Crea Outline" @@ -7612,6 +7613,10 @@ msgstr "Progetto" msgid "Warnings" msgstr "Avvertimento" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8194,6 +8199,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin necessita di un nodo figlio ARVRCamera" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp #, fuzzy msgid "Plotting Meshes: " msgstr "Bliting Immagini" @@ -8399,6 +8412,29 @@ msgstr "Errore caricamento font." msgid "Invalid font size." msgstr "Dimensione font Invalida." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Formato di version.txt invalido nelle templates. Revision non é un " +#~ "identificatore valido." + +#~ msgid "Can't write file." +#~ msgstr "Impossibile scrivere il file." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "Per favore seleziona una cartella che non contiene un file 'project." +#~ "godot'." + +#, fuzzy +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "Impossibile creare project.godot nel percorso di progetto." + +#, fuzzy +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "Impossibile creare project.godot nel percorso di progetto." + #~ msgid "Next" #~ msgstr "Successivo" diff --git a/editor/translations/ja.po b/editor/translations/ja.po index 061a3909e9..905c498a3c 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -2746,14 +2746,6 @@ msgid "Invalid version.txt format inside templates." msgstr "テンプレート内ã®version.txt フォーマットãŒä¸æ£ã§ã™." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"テンプレート内ã®version.txt フォーマットãŒä¸æ£ã§ã™. Revisionã¯æœ‰åŠ¹ãªè˜åˆ¥åã§" -"ã¯ã‚ã‚Šã¾ã›ã‚“." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "テンプレート内ã«version.txtãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“." @@ -2814,10 +2806,6 @@ msgid "Failed:" msgstr "失敗:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "ファイルã«æ›¸ãè¾¼ã¿ã§ãã¾ã›ã‚“ã§ã—ãŸ." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "ダウンãƒãƒ¼ãƒ‰å®Œäº†." @@ -4145,17 +4133,17 @@ msgstr "グリッドを表示" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show helpers" +msgid "Show Helpers" msgstr "ボーンを表示ã™ã‚‹" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show rulers" +msgid "Show Rulers" msgstr "ボーンを表示ã™ã‚‹" #: editor/plugins/canvas_item_editor_plugin.cpp #, fuzzy -msgid "Show guides" +msgid "Show Guides" msgstr "ボーンを表示ã™ã‚‹" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -5106,6 +5094,23 @@ msgid "Resource clipboard is empty!" msgstr "リソースã®ã‚¯ãƒªãƒƒãƒ—ボードã¯ç©ºã§ã™!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "エディタã§é–‹ã" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "インスタンス:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +#, fuzzy +msgid "Type:" +msgstr "åž‹(Type):" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "リソースをèªã¿è¾¼ã‚€" @@ -5418,11 +5423,6 @@ msgstr "コメントを切り替ãˆã‚‹" #: editor/plugins/script_text_editor.cpp #, fuzzy -msgid "Clone Down" -msgstr "複製ã—ã¦ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰" - -#: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Fold/Unfold Line" msgstr "è¡Œã«ç§»å‹•" @@ -5436,6 +5436,11 @@ msgstr "" #: editor/plugins/script_text_editor.cpp #, fuzzy +msgid "Clone Down" +msgstr "複製ã—ã¦ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰" + +#: editor/plugins/script_text_editor.cpp +#, fuzzy msgid "Complete Symbol" msgstr "記å·ã™ã¹ã¦" @@ -6344,12 +6349,6 @@ msgstr "タブ2" msgid "Tab 3" msgstr "タブ3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -#, fuzzy -msgid "Type:" -msgstr "åž‹(Type):" - #: editor/plugins/theme_editor_plugin.cpp #, fuzzy msgid "Data Type:" @@ -6643,10 +6642,6 @@ msgid "Please choose an empty folder." msgstr "'project.godot' ファイルをé¸æŠžã—ã¦ãã ã•ã„." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "'project.godot'ãŒãªã„フォルダをé¸æŠžã—ã¦ãã ã•ã„." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "インãƒãƒ¼ãƒˆã•ã‚ŒãŸãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆ" @@ -6670,7 +6665,9 @@ msgstr "ä¸æ£ãªãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆã®ãƒ‘ス(何ã‹å¤‰ãˆã¾ã—ãŸã‹ï¼Ÿï¼‰" #: editor/project_manager.cpp #, fuzzy -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "project.godotをプãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘スã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ" #: editor/project_manager.cpp @@ -6694,11 +6691,6 @@ msgid "Rename Project" msgstr "åç„¡ã—ã®ãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆ" #: editor/project_manager.cpp -#, fuzzy -msgid "Couldn't get project.godot in the project path." -msgstr "project.godotをプãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘スã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "æ–°ã—ã„ゲームプãƒã‚¸ã‚§ã‚¯ãƒˆ" @@ -7471,10 +7463,6 @@ msgstr "サブリソース:" msgid "Clear Inheritance" msgstr "継承をクリアã™ã‚‹" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "エディタã§é–‹ã" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "ノードを消去" @@ -7610,10 +7598,6 @@ msgstr "" "クリックã—ã¦ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ‰ãƒƒã‚¯ã‚’表示ã—ã¦ãã ã•ã„." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "インスタンス:" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "フォルダを作æˆ" @@ -8080,13 +8064,25 @@ msgstr "オブジェクトã«é•·ã•ãŒã‚ã‚Šã¾ã›ã‚“." #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "é¸æŠžç¯„囲を消去" +msgid "Next Plane" +msgstr "次ã®ã‚¿ãƒ–" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "é¸æŠžç¯„囲を複製" +msgid "Previous Plane" +msgstr "以å‰ã®ã‚¿ãƒ–" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "次ã®åºŠé¢" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "å‰ã®åºŠé¢" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" @@ -8094,21 +8090,23 @@ msgstr "床é¢:" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Grid Map" -msgstr "グリッドSnap" +msgid "GridMap Delete Selection" +msgstr "é¸æŠžç¯„囲を消去" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Snap View" -msgstr "上é¢å›³" +msgid "GridMap Duplicate Selection" +msgstr "é¸æŠžç¯„囲を複製" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "å‰ã®åºŠé¢" +#, fuzzy +msgid "Grid Map" +msgstr "グリッドSnap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "次ã®åºŠé¢" +#, fuzzy +msgid "Snap View" +msgstr "上é¢å›³" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy @@ -8230,6 +8228,10 @@ msgid "Mono" msgstr "モノラル音声" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "アウトラインを生æˆ" @@ -8248,6 +8250,10 @@ msgstr "プãƒã‚¸ã‚§ã‚¯ãƒˆ" msgid "Warnings" msgstr "è¦å‘Š" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp #, fuzzy msgid "" @@ -8865,6 +8871,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROriginã¯ARVRCameraåノードãŒå¿…è¦ã§ã™" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp #, fuzzy msgid "Plotting Meshes: " msgstr "イメージをé…ç½®(Blit)" @@ -9070,6 +9084,27 @@ msgstr "フォントèªã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼ã€‚" msgid "Invalid font size." msgstr "無効ãªãƒ•ã‚©ãƒ³ãƒˆ サイズã§ã™ã€‚" +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "テンプレート内ã®version.txt フォーマットãŒä¸æ£ã§ã™. Revisionã¯æœ‰åŠ¹ãªè˜åˆ¥å" +#~ "ã§ã¯ã‚ã‚Šã¾ã›ã‚“." + +#~ msgid "Can't write file." +#~ msgstr "ファイルã«æ›¸ãè¾¼ã¿ã§ãã¾ã›ã‚“ã§ã—ãŸ." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "'project.godot'ãŒãªã„フォルダをé¸æŠžã—ã¦ãã ã•ã„." + +#, fuzzy +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "project.godotをプãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘スã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ" + +#, fuzzy +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "project.godotをプãƒã‚¸ã‚§ã‚¯ãƒˆãƒ‘スã«ç”Ÿæˆã§ãã¾ã›ã‚“ã§ã—ãŸ" + #~ msgid "Next" #~ msgstr "次" diff --git a/editor/translations/ko.po b/editor/translations/ko.po index 29518c9797..28294c7307 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -7,13 +7,14 @@ # Ch <ccwpc@hanmail.net>, 2017. # paijai 송 (fivejobi) <xotjq237@gmail.com>, 2018. # TheRedPlanet <junmo.moon8@gmail.com>, 2018. +# Xavier Cho <mysticfallband@gmail.com>, 2018. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-01-20 17:48+0000\n" -"Last-Translator: 박한얼 <volzhs@gmail.com>\n" +"PO-Revision-Date: 2018-02-24 08:39+0000\n" +"Last-Translator: TheRedPlanet <junmo.moon8@gmail.com>\n" "Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/" "godot/ko/>\n" "Language: ko\n" @@ -21,7 +22,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 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -36,8 +37,9 @@ msgid "Anim Change Keyframe Time" msgstr "ì• ë‹ˆë©”ì´ì…˜ í‚¤í”„ë ˆìž„ 시간 변경" #: editor/animation_editor.cpp +#, fuzzy msgid "Anim Change Transition" -msgstr "ì• ë‹ˆë©”ì´ì…˜ 변화 변경" +msgstr "ì• ë‹ˆë©”ì´ì…˜ êµì²´ 트랜지션" #: editor/animation_editor.cpp msgid "Anim Change Transform" @@ -162,8 +164,9 @@ msgid "Constant" msgstr "ë¹„ì„ í˜•" #: editor/animation_editor.cpp +#, fuzzy msgid "In" -msgstr "안" +msgstr "In" #: editor/animation_editor.cpp msgid "Out" @@ -2098,7 +2101,7 @@ msgstr "프로ì 트 실행." #: editor/editor_node.cpp msgid "Play" -msgstr "재성" +msgstr "실행" #: editor/editor_node.cpp msgid "Pause the scene" @@ -2443,14 +2446,6 @@ msgid "Invalid version.txt format inside templates." msgstr "템플릿 ì•ˆì— version.txtê°€ ìœ íš¨í•˜ì§€ ì•Šì€ í˜•ì‹ìž…니다." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"í…œí”Œë¦¿ì— version.txt 형ì‹ì´ ìœ íš¨í•˜ì§€ 않습니다. ë¦¬ë¹„ì „ì€ ìœ íš¨í•œ ì‹ë³„ìžê°€ ì•„ë‹™" -"니다." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "í…œí”Œë¦¿ì— version.txt를 ì°¾ì„ ìˆ˜ 없습니다." @@ -2505,10 +2500,6 @@ msgid "Failed:" msgstr "실패:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "파ì¼ì— 쓸 수 없습니다." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "다운로드 완료." @@ -3686,15 +3677,15 @@ msgid "Show Grid" msgstr "그리드 보기" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "í—¬í¼ ë³´ê¸°" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "ìž ë³´ê¸°" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "ê°€ì´ë“œ 보기" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4521,6 +4512,22 @@ msgid "Resource clipboard is empty!" msgstr "리소스 í´ë¦½ë³´ë“œê°€ 비었습니다!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "ì—디터ì—ì„œ 열기" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "ì¸ìŠ¤í„´ìŠ¤:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "타입:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "리소스 로드" @@ -4805,10 +4812,6 @@ msgid "Toggle Comment" msgstr "ì£¼ì„ í† ê¸€" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "아래로 ë³µì œ" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "ë¼ì¸ 펼치기/ì ‘ê¸°" @@ -4821,6 +4824,10 @@ msgid "Unfold All Lines" msgstr "ëª¨ë“ ë¼ì¸ 펼치기" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "아래로 ë³µì œ" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "ìžë™ 완성" @@ -5664,11 +5671,6 @@ msgstr "íƒ 2" msgid "Tab 3" msgstr "íƒ 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "타입:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "ë°ì´íƒ€ 타입:" @@ -5932,10 +5934,6 @@ msgid "Please choose an empty folder." msgstr "비어있는 í´ë”를 ì„ íƒí•˜ì„¸ìš”." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "'project.godot' 파ì¼ì´ 없는 í´ë”를 ì„ íƒ í•˜ì‹ì‹œì˜¤." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "ê°€ì ¸ì˜¨ 프로ì 트" @@ -5956,8 +5954,12 @@ msgid "Invalid project path (changed anything?)." msgstr "ìœ íš¨í•˜ì§€ ì•Šì€ í”„ë¡œì 트 경로 (ë”ê°€ ë³€ê²½í•˜ì‹ ê±°ë¼ë„?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "프로ì 트 ê²½ë¡œì— project.godot 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"프로ì 트 경로로 부터 project.godot 파ì¼ì„ 로드 í• ìˆ˜ 없습니다 (ì—러 %d). 존재" +"하지 않거나 ì†ìƒë˜ì—ˆì„ 수 있습니다." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -5976,10 +5978,6 @@ msgid "Rename Project" msgstr "프로ì 트 ì´ë¦„ 변경" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "프로ì 트 ê²½ë¡œì— project.godot 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "새 게임 프로ì 트" @@ -6678,10 +6676,6 @@ msgstr "서브-리소스" msgid "Clear Inheritance" msgstr "ìƒì† 지우기" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "ì—디터ì—ì„œ 열기" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "노드 ì‚ì œ" @@ -6798,10 +6792,6 @@ msgstr "" "í´ë¦í•´ì„œ 그룹 ë…ì„ ë³´ì‹ì‹œì˜¤." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "ì¸ìŠ¤í„´ìŠ¤:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "스í¬ë¦½íŠ¸ 열기" @@ -7231,32 +7221,44 @@ msgid "Object can't provide a length." msgstr "오브ì 트는 길ì´ë¥¼ ì œê³µí• ìˆ˜ 없습니다." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "그리드맵 ì„ íƒ ì‚ì œ" +msgid "Next Plane" +msgstr "ë‹¤ìŒ í‰ë©´" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "그리드맵 ì„ íƒ ë³µì œ" +msgid "Previous Plane" +msgstr "ì´ì „ í‰ë©´" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "í‰ë©´:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "ë‹¤ìŒ ì¸µ" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "ì´ì „ 층" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "층:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "그리드맵" +msgid "GridMap Delete Selection" +msgstr "그리드맵 ì„ íƒ ì‚ì œ" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "스냅 ë·°" +msgid "GridMap Duplicate Selection" +msgstr "그리드맵 ì„ íƒ ë³µì œ" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "ì´ì „ 층" +msgid "Grid Map" +msgstr "그리드맵" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "ë‹¤ìŒ ì¸µ" +msgid "Snap View" +msgstr "스냅 ë·°" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7363,6 +7365,10 @@ msgid "Mono" msgstr "모노" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "C# 지ì›ì— 대하여" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "C# 솔루션 만들기" @@ -7378,6 +7384,10 @@ msgstr "프로ì 트 빌드" msgid "Warnings" msgstr "ê²½ê³ " +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7919,6 +7929,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROriginì€ ARVRCamera ìžì‹ 노드를 요구 함" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(ë‚¨ì€ ì‹œê°„: %d:%02d s)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "메시 구분 중: " @@ -8114,6 +8132,25 @@ msgstr "í°íŠ¸ 로딩 ì—러." msgid "Invalid font size." msgstr "ìœ íš¨í•˜ì§€ ì•Šì€ í°íŠ¸ í¬ê¸°." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "í…œí”Œë¦¿ì— version.txt 형ì‹ì´ ìœ íš¨í•˜ì§€ 않습니다. ë¦¬ë¹„ì „ì€ ìœ íš¨í•œ ì‹ë³„ìžê°€ ì•„" +#~ "닙니다." + +#~ msgid "Can't write file." +#~ msgstr "파ì¼ì— 쓸 수 없습니다." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "'project.godot' 파ì¼ì´ 없는 í´ë”를 ì„ íƒ í•˜ì‹ì‹œì˜¤." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "프로ì 트 ê²½ë¡œì— project.godot 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "프로ì 트 ê²½ë¡œì— project.godot 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다." + #~ msgid "Next" #~ msgstr "다ìŒ" diff --git a/editor/translations/lt.po b/editor/translations/lt.po index 5e5400d1e7..0ad2945bdc 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -2374,12 +2374,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Å ablonuose nerasta version.txt failo." @@ -2433,10 +2427,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3608,15 +3598,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4439,6 +4429,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4721,10 +4727,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4737,6 +4739,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5578,11 +5584,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5842,10 +5843,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5866,7 +5863,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5886,10 +5885,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6580,10 +6575,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6693,10 +6684,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7119,11 +7106,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7131,19 +7130,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7251,6 +7250,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7266,6 +7269,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7765,6 +7772,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/nb.po b/editor/translations/nb.po index 623898fcb5..8d9ffe7a21 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -2477,13 +2477,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Ugyldig version.txt format i mal." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Ugyldig version.txt format i mal. Revisjon er ikke en gyldig identifikator." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Ingen version.txt funnet i mal." @@ -2542,10 +2535,6 @@ msgid "Failed:" msgstr "Feilet:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Kan ikke skrive fil." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Nedlastning fullført." @@ -3758,15 +3747,15 @@ msgid "Show Grid" msgstr "Vis Rutenett" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Vis hjelpere" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Vis linjaler" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Vis veiledere" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4602,6 +4591,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4891,10 +4896,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Slett Valgte" @@ -4908,6 +4909,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5754,11 +5759,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -6021,10 +6021,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -6046,7 +6042,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -6066,10 +6064,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6766,10 +6760,6 @@ msgstr "Ressurs" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6882,10 +6872,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7313,32 +7299,46 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "Slett Valgte" +msgid "Next Plane" +msgstr "Neste fane" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "Dupliser Utvalg" +msgid "Previous Plane" +msgstr "Forrige fane" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Delete Selection" +msgstr "Slett Valgte" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "GridMap Duplicate Selection" +msgstr "Dupliser Utvalg" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7453,6 +7453,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Lag Omriss" @@ -7470,6 +7474,10 @@ msgstr "Prosjekt" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7991,6 +7999,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8153,6 +8169,16 @@ msgstr "" msgid "Invalid font size." msgstr "Ugyldig fontstørrelse." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Ugyldig version.txt format i mal. Revisjon er ikke en gyldig " +#~ "identifikator." + +#~ msgid "Can't write file." +#~ msgstr "Kan ikke skrive fil." + #~ msgid "Next" #~ msgstr "Neste" diff --git a/editor/translations/nl.po b/editor/translations/nl.po index c44ef3ebc8..e54a0c7960 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -5,24 +5,26 @@ # # aelspire <aelspire@gmail.com>, 2017. # Aram Nap <xyphex.aram@gmail.com>, 2017. -# Arjan219 <arjannugteren1@gmail.com>, 2017. +# Arjan219 <arjannugteren1@gmail.com>, 2017-2018. # Christophe Swolfs <swolfschristophe@gmail.com>, 2017. # Cornee Traas <corneetraas@hotmail.com>, 2017. # Daeran Wereld <daeran@gmail.com>, 2017. # Dzejkop <jakubtrad@gmail.com>, 2017. # Ferdinand de Coninck <ferdinand.deconinck@gmail.com>, 2018. +# Jorn Theunissen <jorn-theunissen@hotmail.com>, 2018. # Maikel <maikel_martens_1@hotmail.com>, 2017. # Pieter-Jan Briers <pieterjan.briers@gmail.com>, 2017-2018. # Robin Arys <robinarys@hotmail.com>, 2017. # Senno Kaasjager <senno.kaasjager@gmail.com>, 2017. # Uxilo <jmolendijk93@gmail.com>, 2017-2018. +# Willem <studiebolmail@gmail.com>, 2018. # Wout Standaert <wout@blobkat.com>, 2017. # Zatherz <zatherz@linux.pl>, 2017. # msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-22 08:07+0000\n" +"PO-Revision-Date: 2018-02-17 19:35+0000\n" "Last-Translator: Pieter-Jan Briers <pieterjan.briers@gmail.com>\n" "Language-Team: Dutch <https://hosted.weblate.org/projects/godot-engine/godot/" "nl/>\n" @@ -30,7 +32,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.19\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -1693,7 +1695,6 @@ msgid "Export Mesh Library" msgstr "Exporteer Mesh Library" #: editor/editor_node.cpp -#, fuzzy msgid "This operation can't be done without a root node." msgstr "Deze bewerking is niet mogelijk zonder een hoofdknoop." @@ -2065,7 +2066,6 @@ msgstr "" "efficiënter met het netwerk bestandssysteem." #: editor/editor_node.cpp -#, fuzzy msgid "Editor" msgstr "Editor" @@ -2302,9 +2302,8 @@ msgid "Creating Mesh Previews" msgstr "Creëren van Mesh Previews" #: editor/editor_plugin.cpp -#, fuzzy msgid "Thumbnail.." -msgstr "Thumbnail.." +msgstr "Voorbeeld.." #: editor/editor_plugin_settings.cpp msgid "Installed Plugins:" @@ -2472,14 +2471,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Ongeldig version.txt formaat in sjablonen." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Ongeldig version.txt formaat in sjablonen. Revisie is geen geldig " -"identificatienummer." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Geen version.txt gevonden in sjablonen." @@ -2534,16 +2525,12 @@ msgid "Failed:" msgstr "Mislukt:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Kan niet naar bestand schrijven." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Download Voltooid." #: editor/export_template_manager.cpp msgid "Error requesting url: " -msgstr "Fout met het opvragen van url: " +msgstr "Fout bij het opvragen van een URL: " #: editor/export_template_manager.cpp msgid "Connecting to Mirror.." @@ -3225,7 +3212,7 @@ msgstr "Hoeveelheid:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend:" -msgstr "Mengen" +msgstr "Mengen:" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend 0:" @@ -3249,7 +3236,7 @@ msgstr "Voeg invoer toe" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Clear Auto-Advance" -msgstr "Verwijder Automatische Voortgang." +msgstr "Verwijder Automatische Voortgang" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Set Auto-Advance" @@ -3455,7 +3442,6 @@ msgid "Official" msgstr "Officieel" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Testing" msgstr "Testen" @@ -3738,15 +3724,15 @@ msgid "Show Grid" msgstr "Raster Weergeven" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Toon helpers" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Toon linialen" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Toon hulplijnen" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4035,11 +4021,11 @@ msgid "UV Unwrap failed, mesh may not be manifold?" msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp +#, fuzzy msgid "No mesh to debug." -msgstr "" +msgstr "Geen mesh om te debuggen." #: editor/plugins/mesh_instance_editor_plugin.cpp -#, fuzzy msgid "Model has no UV in this layer" msgstr "Model heeft geen UV in deze laag" @@ -4048,7 +4034,6 @@ msgid "MeshInstance lacks a Mesh!" msgstr "MeshInstance ontbreekt een Mesh!" #: editor/plugins/mesh_instance_editor_plugin.cpp -#, fuzzy msgid "Mesh has not surface to create outlines from!" msgstr "Mesh heeft geen oppervlakte om omlijning van te maken!" @@ -4169,7 +4154,7 @@ msgstr "" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Populate MultiMesh" -msgstr "" +msgstr "Vul MultiMesh" #: editor/plugins/multimesh_editor_plugin.cpp msgid "Target Surface:" @@ -4246,8 +4231,9 @@ msgid "Constructing compact heightfield..." msgstr "Compact hoogteveld aan het bouwen..." #: editor/plugins/navigation_mesh_generator.cpp +#, fuzzy msgid "Eroding walkable area..." -msgstr "" +msgstr "Wandelbaar gebied eroderen..." #: editor/plugins/navigation_mesh_generator.cpp msgid "Partitioning..." @@ -4292,11 +4278,11 @@ msgstr "" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Error loading image:" -msgstr "" +msgstr "Error bij het laden van afbeelding:" #: editor/plugins/particles_2d_editor_plugin.cpp msgid "No pixels with transparency > 128 in image.." -msgstr "" +msgstr "Geen pixels met transparantie > 128 in afbeelding.." #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Generate Visibility Rect" @@ -4600,6 +4586,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4737,7 +4739,7 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp msgid "Run" -msgstr "" +msgstr "Starten" #: editor/plugins/script_editor_plugin.cpp #, fuzzy @@ -4890,10 +4892,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Ga naar Regel" @@ -4907,6 +4905,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5764,11 +5766,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -6038,10 +6035,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -6063,7 +6056,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -6084,10 +6079,6 @@ msgid "Rename Project" msgstr "Hernoem Functie" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6102,7 +6093,7 @@ msgstr "Importeren" #: editor/project_manager.cpp msgid "Create New Project" -msgstr "" +msgstr "Creëer Nieuw Project" #: editor/project_manager.cpp #, fuzzy @@ -6199,7 +6190,7 @@ msgstr "" #: editor/project_manager.cpp msgid "New Project" -msgstr "" +msgstr "Nieuw Project" #: editor/project_manager.cpp #, fuzzy @@ -6791,10 +6782,6 @@ msgstr "Resource" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6907,10 +6894,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "Omschrijving:" @@ -7348,33 +7331,47 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "Geselecteerde Verwijderen" +msgid "Next Plane" +msgstr "Volgend tabblad" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "Dupliceer Selectie" +msgid "Previous Plane" +msgstr "Vorig tabblad" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +#, fuzzy +msgid "Previous Floor" +msgstr "Vorig tabblad" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Previous Floor" -msgstr "Vorig tabblad" +msgid "GridMap Delete Selection" +msgstr "Geselecteerde Verwijderen" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Duplicate Selection" +msgstr "Dupliceer Selectie" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7488,6 +7485,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Subscriptie Maken" @@ -7505,6 +7506,10 @@ msgstr "Project" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8073,6 +8078,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8262,6 +8275,16 @@ msgstr "Fout bij het laden van lettertype." msgid "Invalid font size." msgstr "Ongeldige lettertype grootte." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Ongeldig version.txt formaat in sjablonen. Revisie is geen geldig " +#~ "identificatienummer." + +#~ msgid "Can't write file." +#~ msgstr "Kan niet naar bestand schrijven." + #~ msgid "Next" #~ msgstr "Volgende" diff --git a/editor/translations/pl.po b/editor/translations/pl.po index f5b08d11c1..21618953a0 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -2463,14 +2463,6 @@ msgid "Invalid version.txt format inside templates." msgstr "NieprawidÅ‚owy format pliku version.txt w szablonach." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"nieprawidÅ‚owy format pliku version.txt wewnÄ…trz szablonów. Zmiana nie jest " -"prawidÅ‚owym identyfikatorem." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Nie znaleziono pliku version.txt w szablonach." @@ -2525,10 +2517,6 @@ msgid "Failed:" msgstr "Nie powiodÅ‚o siÄ™:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Nie można zapisać pliku." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Pobieranie zakoÅ„czone." @@ -3726,15 +3714,15 @@ msgid "Show Grid" msgstr "Pokaż siatkÄ™" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Pokaż linie pomocnicze" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Pokaż linijki" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Pokaż prowadnice" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4585,6 +4573,22 @@ msgid "Resource clipboard is empty!" msgstr "Schowka zasobów jest pusty!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Otwórz w edytorze" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Instancja:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Typ:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Wczytaj Zasób" @@ -4874,10 +4878,6 @@ msgid "Toggle Comment" msgstr "Ustaw komentarz" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Duplikuj liniÄ™" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "ZwiÅ„/rozwiÅ„ wiersz" @@ -4890,6 +4890,10 @@ msgid "Unfold All Lines" msgstr "RozwiÅ„ wszystkie linie" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Duplikuj liniÄ™" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "UzupeÅ‚nij symbol" @@ -5756,11 +5760,6 @@ msgstr "ZakÅ‚adka 2" msgid "Tab 3" msgstr "ZakÅ‚adka 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Typ:" - #: editor/plugins/theme_editor_plugin.cpp #, fuzzy msgid "Data Type:" @@ -6028,10 +6027,6 @@ msgid "Please choose an empty folder." msgstr "ProszÄ™ wybrać plik 'project.godot'." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "ProszÄ™ wybrać folder nie zawierajÄ…cy pliku 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Zaimportowano projekt" @@ -6052,8 +6047,11 @@ msgid "Invalid project path (changed anything?)." msgstr "Niepoprawna Å›cieżka projektu (zmienić cokolwiek?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "Nie można byÅ‚o utworzyć engine.cfg w Å›cieżce projektu." +#, fuzzy +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "Nie można byÅ‚o edytować engine.cfg w Å›cieżce projektu." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6072,10 +6070,6 @@ msgid "Rename Project" msgstr "ZmieÅ„ nazwÄ™ projektu" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "Nie znaleziono project.godot w Å›cieżce projektu." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Nowy projekt gry" @@ -6781,10 +6775,6 @@ msgstr "Zasoby" msgid "Clear Inheritance" msgstr "Wyczyść dziedziczenie" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Otwórz w edytorze" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "UsuÅ„ wÄ™zeÅ‚ (wÄ™zÅ‚y)" @@ -6902,10 +6892,6 @@ msgstr "" "Kliknij, aby wyÅ›wietlić panel grup." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Instancja:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Otwórz skrypt" @@ -7336,32 +7322,46 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "GridMap UsuÅ„ zaznaczenie" +#, fuzzy +msgid "Next Plane" +msgstr "NastÄ™pna zakÅ‚adka" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "GridMap duplikuj zaznaczenie" +#, fuzzy +msgid "Previous Plane" +msgstr "Poprzednia zakÅ‚adka" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "NastÄ™pny poziom" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Poprzedni poziom" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Poziom:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Grid Map" +msgid "GridMap Delete Selection" +msgstr "GridMap UsuÅ„ zaznaczenie" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "PrzyciÄ…ganie widoku" +msgid "GridMap Duplicate Selection" +msgstr "GridMap duplikuj zaznaczenie" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Poprzedni poziom" +msgid "Grid Map" +msgstr "Grid Map" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "NastÄ™pny poziom" +msgid "Snap View" +msgstr "PrzyciÄ…ganie widoku" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy @@ -7475,6 +7475,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "Utwórz solucjÄ™ C#" @@ -7490,6 +7494,10 @@ msgstr "Zbuduj projekt" msgid "Warnings" msgstr "Ostrzeżenia" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8029,6 +8037,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin wymaga by ARVRCamera dziedziczyÅ‚a po node" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8227,6 +8243,25 @@ msgstr "BÅ‚Ä…d Å‚adowania fonta." msgid "Invalid font size." msgstr "Niepoprawny rozmiar fonta." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "nieprawidÅ‚owy format pliku version.txt wewnÄ…trz szablonów. Zmiana nie " +#~ "jest prawidÅ‚owym identyfikatorem." + +#~ msgid "Can't write file." +#~ msgstr "Nie można zapisać pliku." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "ProszÄ™ wybrać folder nie zawierajÄ…cy pliku 'project.godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "Nie można byÅ‚o utworzyć engine.cfg w Å›cieżce projektu." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "Nie znaleziono project.godot w Å›cieżce projektu." + #~ msgid "Next" #~ msgstr "NastÄ™pny" diff --git a/editor/translations/pr.po b/editor/translations/pr.po index 3fd24dd39f..6029e861fd 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -2382,12 +2382,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2441,10 +2435,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3622,15 +3612,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4461,6 +4451,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4745,10 +4751,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Yar, Blow th' Selected Down!" @@ -4762,6 +4764,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5609,11 +5615,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5874,10 +5875,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5898,7 +5895,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5919,10 +5918,6 @@ msgid "Rename Project" msgstr "Rename Function" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6616,10 +6611,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6732,10 +6723,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7170,32 +7157,44 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "GridMap Delete Selection" -msgstr "Yar, Blow th' Selected Down!" +msgid "Next Plane" +msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Delete Selection" +msgstr "Yar, Blow th' Selected Down!" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "GridMap Duplicate Selection" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7304,6 +7303,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7319,6 +7322,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7847,6 +7854,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index 6963d39352..ae67217cfd 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -9,13 +9,14 @@ # Francesco Perrotti-Garcia <fpg1503@gmail.com>, 2017. # George Marques <george@gmarqu.es>, 2016. # Guilherme Felipe C G Silva <guilhermefelipecgs@gmail.com>, 2017. +# João Vitor de Oliveira Carlos <lopogax@gmail.com>, 2018. # Joaquim Ferreira <joaquimferreira1996@bol.com.br>, 2016. # jonathan railarem <railarem@gmail.com>, 2017. # Lucas Silva <lucasb.hpp@gmail.com>, 2018. # Luiz G. Correia <luizgabriell2.0@gmail.com>, 2017. # Mailson Silva Marins <mailsons335@gmail.com>, 2016. # MalcomRF <malcomkbk@gmail.com>, 2017. -# Marcus Correia <marknokalt@live.com>, 2017. +# Marcus Correia <marknokalt@live.com>, 2017-2018. # Michael Alexsander Silva Dias <michaelalexsander@protonmail.com>, 2017-2018. # Renato Rotenberg <renato.rotenberg@gmail.com>, 2017. # Rodolfo R Gomes <rodolforg@gmail.com>, 2017. @@ -25,7 +26,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2018-01-22 08:08+0000\n" +"PO-Revision-Date: 2018-02-22 20:49+0000\n" "Last-Translator: Michael Alexsander Silva Dias <michaelalexsander@protonmail." "com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" @@ -35,7 +36,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 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -47,7 +48,7 @@ msgstr "Toda a Seleção" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Time" -msgstr "Alterar tempo de quadro-chave da animação" +msgstr "Alterar Tempo de Quadro-Chave da Anim" #: editor/animation_editor.cpp msgid "Anim Change Transition" @@ -59,7 +60,7 @@ msgstr "Alterar Transformação da Anim" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Value" -msgstr "Alterar valor de quadro-chave da animação" +msgstr "Alterar Valor de Quadro-Chave da Anim" #: editor/animation_editor.cpp msgid "Anim Change Call" @@ -433,7 +434,7 @@ msgstr "Coluna:" #: editor/connections_dialog.cpp msgid "Method in target Node must be specified!" -msgstr "O método no Nó destino precisa ser especificado!" +msgstr "O método no nó destino precisa ser especificado!" #: editor/connections_dialog.cpp msgid "" @@ -441,7 +442,7 @@ msgid "" "Node." msgstr "" "Método destino não encontrado! EspecÃfique um método válido ou anexe um " -"script ao Nó destino." +"script ao nó destino." #: editor/connections_dialog.cpp msgid "Connect To Node:" @@ -470,7 +471,7 @@ msgstr "Argumentos de Chamada Extras:" #: editor/connections_dialog.cpp msgid "Path to Node:" -msgstr "Caminho para o Nó:" +msgstr "Caminho para o nó:" #: editor/connections_dialog.cpp msgid "Make Function" @@ -482,7 +483,7 @@ msgstr "Postergado" #: editor/connections_dialog.cpp msgid "Oneshot" -msgstr "Uma vez" +msgstr "Oneshot" #: editor/connections_dialog.cpp editor/dependency_editor.cpp #: editor/export_template_manager.cpp @@ -1063,7 +1064,7 @@ msgstr "Caminho:" #: editor/editor_autoload_settings.cpp msgid "Node Name:" -msgstr "Nome do Nó:" +msgstr "Nome do nó:" #: editor/editor_autoload_settings.cpp editor/editor_profiler.cpp #: editor/project_manager.cpp editor/settings_config_dialog.cpp @@ -1653,11 +1654,11 @@ msgstr "Abrir Cena Base" #: editor/editor_node.cpp msgid "Quick Open Scene.." -msgstr "Abri Cena Ãgil..." +msgstr "Abri Cena Rápidamente..." #: editor/editor_node.cpp msgid "Quick Open Script.." -msgstr "Abrir Rápidamente Script.." +msgstr "Abrir Script Rápidamente..." #: editor/editor_node.cpp msgid "Save & Close" @@ -2417,7 +2418,7 @@ msgstr "Padrão (Mesma do Editor)" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" -msgstr "Selecionar Nó(s) para Importar" +msgstr "Selecione Nó(s) para Importar" #: editor/editor_sub_scene.cpp msgid "Scene Path:" @@ -2468,14 +2469,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Formato do version.txt dentro dos modelos é inválido." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Formato do version.txt dentro dos modelos é inválido. A revisão não é um " -"identificador válido." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Não foi encontrado um version.txt dentro dos modelos." @@ -2530,10 +2523,6 @@ msgid "Failed:" msgstr "Falhou:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Não foi possÃvel escrever o arquivo." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Download completo." @@ -2883,7 +2872,7 @@ msgstr "Reimportar" #: editor/multi_node_edit.cpp msgid "MultiNode Set" -msgstr "Múltiplos Nós definidos" +msgstr "Múltiplos Nodes definidos" #: editor/node_dock.cpp msgid "Groups" @@ -2891,7 +2880,7 @@ msgstr "Grupos" #: editor/node_dock.cpp msgid "Select a Node to edit Signals and Groups." -msgstr "Selecione um Nó para editar Sinais e Grupos." +msgstr "Selecione um nó para editar Sinais e Grupos." #: editor/plugins/abstract_polygon_2d_editor.cpp #: editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -3260,39 +3249,39 @@ msgstr "Ãrvore de Animação é inválida." #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Animation Node" -msgstr "Nó de Animação" +msgstr "Nó Animation" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "OneShot Node" -msgstr "Nó de tipo Uma-Vez" +msgstr "Nó OneShot" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Mix Node" -msgstr "Misturar Nó" +msgstr "Nó Mix" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend2 Node" -msgstr "Nó Misturar2" +msgstr "Nó Blend2" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend3 Node" -msgstr "Nó Misturar3" +msgstr "Nó Blend3" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Blend4 Node" -msgstr "Nó Misturar4" +msgstr "Nó Blend4" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "TimeScale Node" -msgstr "Nó Tempo de Escala" +msgstr "Nó TimeScale" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "TimeSeek Node" -msgstr "Nó Tempo de Procura" +msgstr "Nó TimeSeek" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Transition Node" -msgstr "Nó de Transição" +msgstr "Nó Transition" #: editor/plugins/animation_tree_editor_plugin.cpp msgid "Import Animations.." @@ -3720,15 +3709,15 @@ msgid "Show Grid" msgstr "Mostrar Grade" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Mostrar auxiliadores" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Mostrar réguas" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Mostrar guias" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4558,6 +4547,22 @@ msgid "Resource clipboard is empty!" msgstr "Recurso da área de transferência está vazio!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Abrir no Editor" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Instância:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Tipo:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Carregar Recurso" @@ -4844,10 +4849,6 @@ msgid "Toggle Comment" msgstr "Alternar Comentário" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Clonar Abaixo" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Dobrar/Desdobrar Linha" @@ -4860,6 +4861,10 @@ msgid "Unfold All Lines" msgstr "Mostrar Todas as Linhas" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Clonar Abaixo" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Completar SÃmbolo" @@ -5018,11 +5023,11 @@ msgstr "Alterar Nome da Entrada" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Connect Graph Nodes" -msgstr "Conectar Nós de Grafos" +msgstr "Conectar Nodes de Grafos" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Disconnect Graph Nodes" -msgstr "Desconectar Nós de Grafos" +msgstr "Desconectar Nodes de Grafos" #: editor/plugins/shader_graph_editor_plugin.cpp msgid "Remove Shader Graph Node" @@ -5703,11 +5708,6 @@ msgstr "Guia 2" msgid "Tab 3" msgstr "Guia 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Tipo:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Tipo de Dados:" @@ -5979,11 +5979,6 @@ msgid "Please choose an empty folder." msgstr "Por favor, escolha uma pasta vazia." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" -"Por favor, escolha uma pasta que não contenha um arquivo 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Projeto Importado" @@ -6004,8 +5999,12 @@ msgid "Invalid project path (changed anything?)." msgstr "Caminho de projeto inválido (mudou alguma coisa?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "Não foi possÃvel encontrar project.godot no caminho do projeto." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"Não foi possÃvel carregar project.godot no caminho do projeto (erro %d). Ele " +"pode estar ausente ou corrompido." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6024,10 +6023,6 @@ msgid "Rename Project" msgstr "Renomear Projeto" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "Não foi possÃvel encontrar project.godot no caminho do projeto." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Novo Projeto de Jogo" @@ -6540,7 +6535,7 @@ msgstr "Erro ao carregar arquivo: Não é um recurso!" #: editor/property_editor.cpp msgid "Selected node is not a Viewport!" -msgstr "Nó selecionado não é uma Viewport!" +msgstr "O nó selecionado não é uma Viewport!" #: editor/property_editor.cpp msgid "Pick a Node" @@ -6657,7 +6652,7 @@ msgstr "Mover Nó no Pai" #: editor/scene_tree_dock.cpp msgid "Move Nodes In Parent" -msgstr "Mover Nós no Pai" +msgstr "Mover Nodes no Pai" #: editor/scene_tree_dock.cpp msgid "Duplicate Node(s)" @@ -6731,10 +6726,6 @@ msgstr "Sub-Recursos" msgid "Clear Inheritance" msgstr "Limpar Herança" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Abrir no Editor" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Excluir Nó(s)" @@ -6784,8 +6775,8 @@ msgid "" "Instance a scene file as a Node. Creates an inherited scene if no root node " "exists." msgstr "" -"Instanciar um arquivo de cena como um Nó. Criar uma cena herdada se não " -"existe um nó raiz." +"Instanciar um arquivo de cena como um nó. Cria uma cena herdada se não " +"existir um nó raiz." #: editor/scene_tree_dock.cpp msgid "Filter nodes" @@ -6852,10 +6843,6 @@ msgstr "" "Clique para mostrar o painel de grupos." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Instância:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Abrir script" @@ -6889,7 +6876,7 @@ msgstr "Renomear Nó" #: editor/scene_tree_editor.cpp msgid "Scene Tree (Nodes):" -msgstr "Ãrvore de Cena (Nós):" +msgstr "Ãrvore de Cena (Nodes):" #: editor/scene_tree_editor.cpp msgid "Node Configuration Warning!" @@ -7284,32 +7271,44 @@ msgid "Object can't provide a length." msgstr "Objeto não pôde fornecer um comprimento." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "Excluir Seleção do Gridap" +msgid "Next Plane" +msgstr "Próximo Plano" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "Duplicar Seleção do GridMap" +msgid "Previous Plane" +msgstr "Plano Anterior" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "Plano:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Próximo Chão" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Chão Anterior" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Chão:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Mapa de Grade" +msgid "GridMap Delete Selection" +msgstr "Excluir Seleção do Gridap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "Ancorar Vista" +msgid "GridMap Duplicate Selection" +msgstr "Duplicar Seleção do GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Chão Anterior" +msgid "Grid Map" +msgstr "Mapa de Grade" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Próximo Chão" +msgid "Snap View" +msgstr "Ancorar Vista" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7416,6 +7415,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "Sobre o suporte ao C#" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "Criar solução C#" @@ -7431,6 +7434,10 @@ msgstr "Compilar Projeto" msgid "Warnings" msgstr "Avisos" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7453,7 +7460,7 @@ msgid "" "your node please." msgstr "" "Um valor de retorno deve ser atribuÃdo ao primeiro elemento da memória " -"corrente do nó! Conserte seu node, por favor." +"corrente do nó! Conserte seu nó, por favor." #: modules/visual_script/visual_script.cpp msgid "Node returned an invalid sequence output: " @@ -7537,11 +7544,11 @@ msgstr "Adicionar Nó" #: modules/visual_script/visual_script_editor.cpp msgid "Remove VisualScript Nodes" -msgstr "Remover Nós VisualScript" +msgstr "Remover Nodes VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Duplicate VisualScript Nodes" -msgstr "Duplicar Nós VisualScript" +msgstr "Duplicar Nodes VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a Getter. Hold Shift to drop a generic signature." @@ -7577,7 +7584,7 @@ msgstr "Adicionar Nó de Pré-carregamento" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" -msgstr "Adicionar Nó(s) a partir de árvore" +msgstr "Adicionar Nó(s) a Partir da Ãrvore" #: modules/visual_script/visual_script_editor.cpp msgid "Add Getter Property" @@ -7601,7 +7608,7 @@ msgstr "Remover Nó VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Connect Nodes" -msgstr "Conectar Nós" +msgstr "Conectar Nodes" #: modules/visual_script/visual_script_editor.cpp msgid "Condition" @@ -7653,7 +7660,7 @@ msgstr "Ãrea de transferência vazia!" #: modules/visual_script/visual_script_editor.cpp msgid "Paste VisualScript Nodes" -msgstr "Colar Nós VisualScript" +msgstr "Colar Nodes VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Function" @@ -7689,7 +7696,7 @@ msgstr "Tipo de Base:" #: modules/visual_script/visual_script_editor.cpp msgid "Available Nodes:" -msgstr "Nós DisponÃveis:" +msgstr "Nodes DisponÃveis:" #: modules/visual_script/visual_script_editor.cpp msgid "Select or create a function to edit graph" @@ -7713,15 +7720,15 @@ msgstr "Localizar Tipo de Nó" #: modules/visual_script/visual_script_editor.cpp msgid "Copy Nodes" -msgstr "Copiar Nós" +msgstr "Copiar Nodes" #: modules/visual_script/visual_script_editor.cpp msgid "Cut Nodes" -msgstr "Recortar Nós" +msgstr "Recortar Nodes" #: modules/visual_script/visual_script_editor.cpp msgid "Paste Nodes" -msgstr "Colar Nós" +msgstr "Colar Nodes" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -7741,11 +7748,11 @@ msgstr "Nome da propriedade de Ãndice inválido." #: modules/visual_script/visual_script_func_nodes.cpp msgid "Base object is not a Node!" -msgstr "Objeto base não é um Node!" +msgstr "Objeto base não é um nó!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Path does not lead Node!" -msgstr "O caminho não leva a um Node!" +msgstr "O caminho não leva a um nó!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name '%s' in node %s." @@ -7985,6 +7992,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin necessita um nó ARVRCamera como filho" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(Tempo Restante: %d:%02d s)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "Planejando Malhas: " @@ -8184,6 +8199,26 @@ msgstr "Erro ao carregar fonte." msgid "Invalid font size." msgstr "Tamanho de fonte inválido." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Formato do version.txt dentro dos modelos é inválido. A revisão não é um " +#~ "identificador válido." + +#~ msgid "Can't write file." +#~ msgstr "Não foi possÃvel escrever o arquivo." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "Por favor, escolha uma pasta que não contenha um arquivo 'project.godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "Não foi possÃvel encontrar project.godot no caminho do projeto." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "Não foi possÃvel encontrar project.godot no caminho do projeto." + #~ msgid "Next" #~ msgstr "Próximo" diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po index 7bddb64cd0..9f520ddf46 100644 --- a/editor/translations/pt_PT.po +++ b/editor/translations/pt_PT.po @@ -8,6 +8,7 @@ # João Graça <jgraca95@gmail.com>, 2017. # João Lopes <linux-man@hotmail.com>, 2017-2018. # Miguel Gomes <miggas09@gmail.com>, 2017. +# Paulo Caldeira <paucal@gmail.com>, 2018. # Pedro Gomes <pedrogomes1698@gmail.com>, 2017. # Rueben Stevens <supercell03@gmail.com>, 2017. # SARDON <fabio3_Santos@hotmail.com>, 2017. @@ -16,15 +17,15 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-22 08:08+0000\n" -"Last-Translator: João Lopes <linux-man@hotmail.com>\n" +"PO-Revision-Date: 2018-02-24 23:41+0000\n" +"Last-Translator: Paulo Caldeira <paucal@gmail.com>\n" "Language-Team: Portuguese (Portugal) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_PT/>\n" "Language: pt_PT\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -837,7 +838,7 @@ msgstr "Alterar Volume do canal áudio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" -msgstr "Alternar solo do canal áudio" +msgstr "Alternar solo do canal de áudio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Mute" @@ -845,7 +846,7 @@ msgstr "Alternar silêncio do canal áudio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Bypass Effects" -msgstr "Alternar efeitos do canal áudio" +msgstr "Alternar efeitos bypass do canal de áudio" #: editor/editor_audio_buses.cpp msgid "Select Audio Bus Send" @@ -1097,7 +1098,7 @@ msgstr "Escolha uma Diretoria" #: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp msgid "Create Folder" -msgstr "Criar Pasta/Diretoria" +msgstr "Criar Pasta" #: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp #: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp @@ -2458,14 +2459,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Formato de version.txt inválido, dentro dos Modelos." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Formato de version.txt inválido, dentro dos Modelos. Revisão não é um " -"identificador válido." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Não foi encontrado version.txt dentro dos Modelos." @@ -2520,10 +2513,6 @@ msgid "Failed:" msgstr "Falhou:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "ImpossÃvel escrever o Ficheiro." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Download Completo." @@ -3435,7 +3424,7 @@ msgstr "Oficial" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Testing" -msgstr "A testar" +msgstr "Em teste" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" @@ -3705,15 +3694,15 @@ msgid "Show Grid" msgstr "Mostrar grelha" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Mostrar ajudantes" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Mostrar réguas" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Mostrar guias" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4540,6 +4529,22 @@ msgid "Resource clipboard is empty!" msgstr "Ãrea de transferência de recursos vazia!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Abrir no Editor" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Instância:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Tipo:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Carregar recurso" @@ -4826,10 +4831,6 @@ msgid "Toggle Comment" msgstr "Alternar comentário" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Clonar abaixo" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Fechar/Abrir Linha" @@ -4842,6 +4843,10 @@ msgid "Unfold All Lines" msgstr "Mostrar todas as linhas" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Clonar abaixo" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Completar sÃmbolo" @@ -5685,11 +5690,6 @@ msgstr "Aba 2" msgid "Tab 3" msgstr "Aba 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Tipo:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Tipo de dados:" @@ -5959,10 +5959,6 @@ msgid "Please choose an empty folder." msgstr "Por favor escolha uma pasta vazia." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "Escolha uma pasta que não contenha um Ficheiro 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Projeto importado" @@ -5983,8 +5979,12 @@ msgid "Invalid project path (changed anything?)." msgstr "Caminho de Projeto inválido (alguma alteração?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "ImpossÃvel encontrar project.godot no Caminho do Projeto." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"Não foi possÃvel carregar o project.godot no caminho do projeto. Poderá " +"estar em falta ou corrompido." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6003,10 +6003,6 @@ msgid "Rename Project" msgstr "Renomear Projeto" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "ImpossÃvel encontrar project.godot no Caminho do Projeto." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Novo Projeto de jogo" @@ -6709,10 +6705,6 @@ msgstr "Sub-recursos" msgid "Clear Inheritance" msgstr "Limpar herança" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Abrir no Editor" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Apagar Nó(s)" @@ -6830,10 +6822,6 @@ msgstr "" "Clique para mostrar doca dos grupos." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Instância:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Abrir Script" @@ -7263,32 +7251,44 @@ msgid "Object can't provide a length." msgstr "Objeto não fornece um comprimento." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "Apagar seleção GridMap" +msgid "Next Plane" +msgstr "Plano seguinte" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "Seleção duplicada de GridMap" +msgid "Previous Plane" +msgstr "Plano anterior" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "Plano:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Próximo Piso" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Piso anterior" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Piso:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Mapa de grelha" +msgid "GridMap Delete Selection" +msgstr "Apagar seleção GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "Vista de Ajuste" +msgid "GridMap Duplicate Selection" +msgstr "Seleção duplicada de GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Piso anterior" +msgid "Grid Map" +msgstr "Mapa de grelha" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Próximo Piso" +msgid "Snap View" +msgstr "Vista de Ajuste" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7395,6 +7395,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "Sobre o suporte C#" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "Criar solução C#" @@ -7410,6 +7414,10 @@ msgstr "Construir Projeto" msgid "Warnings" msgstr "Avisos" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7963,6 +7971,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin exige um Nó filho ARVRCamera" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(Tempo restante: %d:%02d s)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "A traçar Meshes: " @@ -8164,6 +8180,25 @@ msgstr "Erro ao carregar letra." msgid "Invalid font size." msgstr "Tamanho de letra inválido." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Formato de version.txt inválido, dentro dos Modelos. Revisão não é um " +#~ "identificador válido." + +#~ msgid "Can't write file." +#~ msgstr "ImpossÃvel escrever o Ficheiro." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "Escolha uma pasta que não contenha um Ficheiro 'project.godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "ImpossÃvel encontrar project.godot no Caminho do Projeto." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "ImpossÃvel encontrar project.godot no Caminho do Projeto." + #~ msgid "Next" #~ msgstr "Proximo" diff --git a/editor/translations/ro.po b/editor/translations/ro.po index 9aa5fbeeff..1d89dd74ea 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -2364,12 +2364,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2422,10 +2416,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3588,15 +3578,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4419,6 +4409,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4701,10 +4707,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4717,6 +4719,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5557,11 +5563,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5821,10 +5822,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5845,7 +5842,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5865,10 +5864,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6556,10 +6551,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6669,10 +6660,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7095,11 +7082,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7107,19 +7106,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7227,6 +7226,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7242,6 +7245,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7741,6 +7748,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/ru.po b/editor/translations/ru.po index cf82142c80..67e02b9ce8 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -18,7 +18,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-01-24 12:27+0000\n" +"PO-Revision-Date: 2018-02-23 20:40+0000\n" "Last-Translator: ijet <my-ijet@mail.ru>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" @@ -28,7 +28,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -2459,14 +2459,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Ðеверный формат version.txt файла внутри шаблонов." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Ðеверный формат version.txt файла внутри шаблонов. Идентификатор ревизии не " -"верен." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Ðе найден version.txt файл в шаблонах." @@ -2521,10 +2513,6 @@ msgid "Failed:" msgstr "Ðе удалоÑÑŒ:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Ðе удалоÑÑŒ запиÑать файл." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Загрузка завершена." @@ -3711,15 +3699,15 @@ msgid "Show Grid" msgstr "Показать Ñетку" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Показывать помощники" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Показывать линейки" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Показывать направлÑющие" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4546,6 +4534,22 @@ msgid "Resource clipboard is empty!" msgstr "Ðет реÑурÑа в буфере обмена!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Открыть в редакторе" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "ÐкземплÑÑ€:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Тип:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Загрузить реÑурÑ" @@ -4832,10 +4836,6 @@ msgid "Toggle Comment" msgstr "Переключить комментарий" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Копировать вниз" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Свернуть/Развернуть Ñтроку" @@ -4848,6 +4848,10 @@ msgid "Unfold All Lines" msgstr "Развернуть вÑе Ñтроки" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Копировать вниз" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "СпиÑок автозавершениÑ" @@ -5693,11 +5697,6 @@ msgstr "Вкладка 2" msgid "Tab 3" msgstr "Вкладка 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Тип:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Тип информации:" @@ -5963,10 +5962,6 @@ msgid "Please choose an empty folder." msgstr "ПожалуйÑта, выберите пуÑтую папку." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "ПожалуйÑта, выберите папку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ Ñодержит файл 'project.godot'." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Импортированный проект" @@ -5987,8 +5982,12 @@ msgid "Invalid project path (changed anything?)." msgstr "Ðеверный путь к проекту (Что-то изменили?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "ОтÑутÑтвует project.godot в папке проекта." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"Ðе удалоÑÑŒ загрузить project.godot в пути проекта (ошибка %d). Возможно, он " +"отÑутÑтвует или поврежден." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6007,10 +6006,6 @@ msgid "Rename Project" msgstr "Переименовать проект" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "ОтÑутÑтвует project.godot в папке проекта." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Ðовый игровой проект" @@ -6715,10 +6710,6 @@ msgstr "Вложенные реÑурÑÑ‹" msgid "Clear Inheritance" msgstr "ОчиÑтить наÑледование" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Открыть в редакторе" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Удалить узел(узлы)" @@ -6836,10 +6827,6 @@ msgstr "" "Ðажмите, чтобы показать панель групп." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "ÐкземплÑÑ€:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Открыть Ñкрипт" @@ -7268,32 +7255,44 @@ msgid "Object can't provide a length." msgstr "Объект не может предоÑтавить длину." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "Удалить выделенную Ñетку" +msgid "Next Plane" +msgstr "Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð¿Ð¾ÑкоÑÑ‚ÑŒ" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "Дублировать выделенную Ñетку" +msgid "Previous Plane" +msgstr "ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ð¿Ð»Ð¾ÑкоÑÑ‚ÑŒ" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "ПлоÑкоÑÑ‚ÑŒ:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Следующий Ñтаж" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Предыдущий Ñтаж" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Ðтаж:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Ð¡ÐµÑ‚Ð¾Ñ‡Ð½Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°" +msgid "GridMap Delete Selection" +msgstr "Удалить выделенную Ñетку" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "ПривÑзать вид" +msgid "GridMap Duplicate Selection" +msgstr "Дублировать выделенную Ñетку" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Предыдущий Ñтаж" +msgid "Grid Map" +msgstr "Ð¡ÐµÑ‚Ð¾Ñ‡Ð½Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Следующий Ñтаж" +msgid "Snap View" +msgstr "ПривÑзать вид" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7400,6 +7399,10 @@ msgid "Mono" msgstr "Моно" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "О C# поддержке" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "Создать C# решение" @@ -7415,6 +7418,10 @@ msgstr "Собрать проект" msgid "Warnings" msgstr "ПредупреждениÑ" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7818,6 +7825,10 @@ msgid "" "Consider adding CollisionShape2D or CollisionPolygon2D children nodes to " "define its shape." msgstr "" +"Ðтот узел не имеет дочерних форм, поÑтому он не может взаимодейÑтвовать Ñ " +"проÑтранÑтвом.\n" +"РаÑÑмотрите возможноÑÑ‚ÑŒ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ CollisionShape2D или CollisionPolygon2D " +"дочерних узлов, Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐµÐ³Ð¾ формы." #: scene/2d/collision_polygon_2d.cpp msgid "" @@ -7965,6 +7976,15 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin требует дочерний узел ARVRCamera" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +#, fuzzy +msgid "(Time Left: %d:%02d s)" +msgstr "(ОÑталоÑÑŒ: %d:%02d Ñек)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "ПоÑтроение полиÑетки: " @@ -7986,6 +8006,10 @@ msgid "" "Consider adding CollisionShape or CollisionPolygon children nodes to define " "its shape." msgstr "" +"Ðтот узел не имеет дочерних форм, поÑтому он не может взаимодейÑтвовать Ñ " +"проÑтранÑтвом.\n" +"РаÑÑмотрите возможноÑÑ‚ÑŒ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ CollisionShape или CollisionPolygon " +"дочерних узлов, чтобы определить его форму." #: scene/3d/collision_polygon.cpp msgid "" @@ -8161,6 +8185,26 @@ msgstr "Ошибка загрузки шрифта." msgid "Invalid font size." msgstr "ÐедопуÑтимый размер шрифта." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Ðеверный формат version.txt файла внутри шаблонов. Идентификатор ревизии " +#~ "не верен." + +#~ msgid "Can't write file." +#~ msgstr "Ðе удалоÑÑŒ запиÑать файл." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "ПожалуйÑта, выберите папку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ Ñодержит файл 'project.godot'." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "ОтÑутÑтвует project.godot в папке проекта." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "ОтÑутÑтвует project.godot в папке проекта." + #~ msgid "Next" #~ msgstr "Следующий" diff --git a/editor/translations/sk.po b/editor/translations/sk.po index 33c848f91b..c5fa76fb01 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -2385,12 +2385,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2443,11 +2437,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -#, fuzzy -msgid "Can't write file." -msgstr "Popis:" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3623,15 +3612,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4465,6 +4454,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4748,10 +4753,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4764,6 +4765,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5612,11 +5617,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5879,10 +5879,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5904,7 +5900,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5925,10 +5923,6 @@ msgid "Rename Project" msgstr "VÅ¡etky vybrané" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6623,10 +6617,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6740,10 +6730,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "Popis:" @@ -7174,32 +7160,44 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "GridMap Delete Selection" -msgstr "VÅ¡etky vybrané" +msgid "Next Plane" +msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Delete Selection" +msgstr "VÅ¡etky vybrané" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "GridMap Duplicate Selection" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7309,6 +7307,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7324,6 +7326,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7840,6 +7846,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8001,6 +8015,10 @@ msgstr "" msgid "Invalid font size." msgstr "" +#, fuzzy +#~ msgid "Can't write file." +#~ msgstr "Popis:" + #~ msgid "Meta+" #~ msgstr "Meta+" diff --git a/editor/translations/sl.po b/editor/translations/sl.po index 9e9db80294..04fb6d9816 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -2380,12 +2380,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2438,10 +2432,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3618,15 +3608,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4457,6 +4447,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4741,10 +4747,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "IzbriÅ¡i Izbrano" @@ -4758,6 +4760,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5604,11 +5610,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5869,10 +5870,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5893,7 +5890,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5914,10 +5913,6 @@ msgid "Rename Project" msgstr "Preimenuj Funkcijo" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6611,10 +6606,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6725,10 +6716,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7157,32 +7144,44 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "GridMap Delete Selection" -msgstr "IzbriÅ¡i Izbrano" +msgid "Next Plane" +msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Delete Selection" +msgstr "IzbriÅ¡i Izbrano" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "GridMap Duplicate Selection" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7291,6 +7290,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7306,6 +7309,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7835,6 +7842,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index 1c53884f32..e411ff2305 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -2453,14 +2453,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Ðеважећи формат датотеке version.txt унутар шаблона." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Ðеважећи формат датотеке „version.txt“ унутар шаблона. „Revision“ није " -"важећи идентификатор." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "„version.txt“ није пронаћен у шаблону." @@ -2517,10 +2509,6 @@ msgid "Failed:" msgstr "ÐеуÑпех:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "ÐеуÑпех при запиÑивању датотеке." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Преузимање уÑпешно." @@ -3710,15 +3698,15 @@ msgid "Show Grid" msgstr "Покажи мрежу" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Покажи помагаче" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Покажи лељире" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Покажи водиче" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4548,6 +4536,22 @@ msgid "Resource clipboard is empty!" msgstr "Ðема реÑурÑа за копирање!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Тип:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Учитај реÑурÑ" @@ -4840,10 +4844,6 @@ msgid "Toggle Comment" msgstr "Коментариши" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Клонирај доле" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "Откриј линију" @@ -4857,6 +4857,10 @@ msgid "Unfold All Lines" msgstr "Откриј Ñве линије" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Клонирај доле" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Потпун Ñимбол" @@ -5710,11 +5714,6 @@ msgstr "Tab 2" msgid "Tab 3" msgstr "Tab 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Тип:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Тип податка:" @@ -5988,10 +5987,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -6013,7 +6008,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -6033,10 +6030,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6730,10 +6723,6 @@ msgstr "РеÑурÑи" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6843,10 +6832,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7271,31 +7256,45 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +#, fuzzy +msgid "Next Plane" +msgstr "Следећи таб" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Plane" +msgstr "Претходни таб" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Претодни Ñпрат" + +#: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Мапа мреже" +msgid "GridMap Delete Selection" +msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Претодни Ñпрат" +msgid "Grid Map" +msgstr "Мапа мреже" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7408,6 +7407,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Ðаправи ивице" @@ -7425,6 +7428,10 @@ msgstr "Пројекат" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7930,6 +7937,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8091,6 +8106,16 @@ msgstr "" msgid "Invalid font size." msgstr "Ðеважећа величина фонта." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Ðеважећи формат датотеке „version.txt“ унутар шаблона. „Revision“ није " +#~ "важећи идентификатор." + +#~ msgid "Can't write file." +#~ msgstr "ÐеуÑпех при запиÑивању датотеке." + #~ msgid "Next" #~ msgstr "Следеће" diff --git a/editor/translations/sv.po b/editor/translations/sv.po index 5779cb56b1..64a268a7bc 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -2699,12 +2699,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2760,10 +2754,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp #, fuzzy msgid "Download Complete." msgstr "Nedladdning Klar." @@ -3987,15 +3977,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4839,6 +4829,24 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +#, fuzzy +msgid "Instance:" +msgstr "Instans:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +#, fuzzy +msgid "Type:" +msgstr "Typ:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Ladda Resurs" @@ -5151,10 +5159,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -5167,6 +5171,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -6052,12 +6060,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -#, fuzzy -msgid "Type:" -msgstr "Typ:" - #: editor/plugins/theme_editor_plugin.cpp #, fuzzy msgid "Data Type:" @@ -6331,10 +6333,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -6357,7 +6355,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -6378,10 +6378,6 @@ msgid "Rename Project" msgstr "Byt namn pÃ¥ Projekt" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp #, fuzzy msgid "New Game Project" msgstr "Nytt Spelprojekt" @@ -7122,10 +7118,6 @@ msgstr "Resurser" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp #, fuzzy msgid "Delete Node(s)" @@ -7244,11 +7236,6 @@ msgstr "" #: editor/scene_tree_editor.cpp #, fuzzy -msgid "Instance:" -msgstr "Instans:" - -#: editor/scene_tree_editor.cpp -#, fuzzy msgid "Open script" msgstr "Öppna Skript" @@ -7708,11 +7695,25 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +#, fuzzy +msgid "Next Plane" +msgstr "Nästa flik" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "Previous Plane" +msgstr "FöregÃ¥ende flik" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7720,19 +7721,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7849,6 +7850,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "Skapa Prenumeration" @@ -7867,6 +7872,10 @@ msgstr "Projekt" msgid "Warnings" msgstr "Varning" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8414,6 +8423,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin kräver en ARVRCamera Barn-Node" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/ta.po b/editor/translations/ta.po index 16e646b2a0..4be5e8b832 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -2365,12 +2365,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2423,10 +2417,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3590,15 +3580,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4421,6 +4411,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4703,10 +4709,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4719,6 +4721,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5559,11 +5565,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5823,10 +5824,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5847,7 +5844,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5867,10 +5866,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6558,10 +6553,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6671,10 +6662,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7097,11 +7084,23 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7109,19 +7108,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7229,6 +7228,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7244,6 +7247,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7743,6 +7750,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/th.po b/editor/translations/th.po index 4f8b834985..b31fba186a 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2018-01-20 09:49+0000\n" +"PO-Revision-Date: 2018-02-25 04:41+0000\n" "Last-Translator: Poommetee Ketson <poommetee@protonmail.com>\n" "Language-Team: Thai <https://hosted.weblate.org/projects/godot-engine/godot/" "th/>\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -102,11 +102,11 @@ msgstr "ลบคีย์à¹à¸à¸™à¸´à¹€à¸¡à¸Šà¸±à¸™" #: editor/animation_editor.cpp editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Duplicate Selection" -msgstr "ทำซ้ำในà¹à¸—ร็à¸à¹€à¸”ิม" +msgstr "ทำซ้ำที่เลืà¸à¸" #: editor/animation_editor.cpp msgid "Duplicate Transposed" -msgstr "ทำซ้ำในà¹à¸—ร็à¸à¸—ี่เลืà¸à¸" +msgstr "ทำซ้ำเปลี่ยนà¹à¸—ร็à¸" #: editor/animation_editor.cpp msgid "Remove Selection" @@ -2404,12 +2404,6 @@ msgid "Invalid version.txt format inside templates." msgstr "รูปà¹à¸šà¸šà¸‚à¸à¸‡ version.txt ในà¹à¸¡à¹ˆà¹à¸šà¸šà¹„ม่ถูà¸à¸•à¹‰à¸à¸‡" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "รูปà¹à¸šà¸šà¸‚à¸à¸‡ version.txt ในà¹à¸¡à¹ˆà¹à¸šà¸šà¹„ม่ถูà¸à¸•à¹‰à¸à¸‡ หมายเลขรุ่น revision ต้à¸à¸‡à¹ƒà¸Šà¹‰à¸£à¸°à¸šà¸¸à¹„ด้" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "ไม่พบ version.txt ในà¹à¸¡à¹ˆà¹à¸šà¸š" @@ -2462,10 +2456,6 @@ msgid "Failed:" msgstr "ผิดพลาด:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "เขียนไฟล์ไม่ได้" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "ดาวน์โหลดเสร็จสิ้น" @@ -3639,15 +3629,15 @@ msgid "Show Grid" msgstr "à¹à¸ªà¸”งเส้นตาราง" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "à¹à¸ªà¸”งตัวช่วย" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "à¹à¸ªà¸”งไม้บรรทัด" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "à¹à¸ªà¸”งเส้นนำ" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4474,6 +4464,22 @@ msgid "Resource clipboard is empty!" msgstr "คลิปบà¸à¸£à¹Œà¸”ไม่มีรีซà¸à¸£à¹Œà¸ª!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "เปิดในโปรà¹à¸à¸£à¸¡à¹à¸à¹‰à¹„ข" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "à¸à¸´à¸™à¸ªà¹à¸•à¸™à¸‹à¹Œ:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "ประเภท:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "โหลดรีซà¸à¸£à¹Œà¸ª" @@ -4758,10 +4764,6 @@ msgid "Toggle Comment" msgstr "เปิด/ปิด ความคิดเห็น" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "คัดลà¸à¸à¸šà¸£à¸£à¸—ัดลงมา" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "ซ่à¸à¸™/à¹à¸ªà¸”งบรรทัด" @@ -4774,6 +4776,10 @@ msgid "Unfold All Lines" msgstr "à¹à¸ªà¸”งทั้งหมด" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "คัดลà¸à¸à¸šà¸£à¸£à¸—ัดลงมา" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "เสนà¸à¹à¸™à¸°à¸„ำเต็ม" @@ -5617,11 +5623,6 @@ msgstr "à¹à¸—็บ 2" msgid "Tab 3" msgstr "à¹à¸—็บ 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "ประเภท:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "ชนิดข้à¸à¸¡à¸¹à¸¥:" @@ -5680,15 +5681,15 @@ msgstr "ค้นหา tile" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Transpose" -msgstr "สลับเปลี่ยน" +msgstr "สลับà¹à¸à¸™" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Mirror X" -msgstr "สะท้à¸à¸™à¸šà¸™à¸¥à¹ˆà¸²à¸‡" +msgstr "สะท้à¸à¸™à¸‹à¹‰à¸²à¸¢à¸‚วา" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Mirror Y" -msgstr "สะท้à¸à¸™à¸‹à¹‰à¸²à¸¢à¸‚วา" +msgstr "สะท้à¸à¸™à¸šà¸™à¸¥à¹ˆà¸²à¸‡" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Paint Tile" @@ -5883,10 +5884,6 @@ msgid "Please choose an empty folder." msgstr "à¸à¸£à¸¸à¸“าเลืà¸à¸à¹‚ฟลเดà¸à¸£à¹Œà¸§à¹ˆà¸²à¸‡à¹€à¸›à¸¥à¹ˆà¸²" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "à¸à¸£à¸¸à¸“าเลืà¸à¸à¹‚ฟลเดà¸à¸£à¹Œà¸—ี่ไม่มีไฟล์ 'project.godot'" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "นำเข้าโปรเจà¸à¸•à¹Œà¹à¸¥à¹‰à¸§" @@ -5907,8 +5904,11 @@ msgid "Invalid project path (changed anything?)." msgstr "ตำà¹à¸«à¸™à¹ˆà¸‡à¹‚ปรเจà¸à¸•à¹Œà¸œà¸´à¸”พลาด (ได้à¹à¸à¹‰à¹„ขà¸à¸°à¹„รไปหรืà¸à¹„ม่?)" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "ไม่พบไฟล์ project.godot" +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"โหลดไฟล์ project.godot ในโฟลเดà¸à¸£à¹Œà¹‚ปรเจà¸à¸•à¹Œà¹„ม่ได้ (ข้à¸à¸œà¸´à¸”พลาด %d) ไฟล์à¸à¸²à¸ˆà¸ªà¸¹à¸à¸«à¸²à¸¢à¸«à¸£à¸·à¸à¹€à¸ªà¸µà¸¢à¸«à¸²à¸¢" #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -5927,10 +5927,6 @@ msgid "Rename Project" msgstr "เปลี่ยนชื่à¸à¹‚ปรเจà¸à¸•à¹Œ" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "ไม่พบไฟล์ project.godot" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "โปรเจà¸à¸•à¹Œà¹ƒà¸«à¸¡à¹ˆ" @@ -6343,11 +6339,11 @@ msgstr "รีซà¸à¸£à¹Œà¸ª:" #: editor/project_settings_editor.cpp msgid "Remaps by Locale:" -msgstr "à¹à¸—นที่ตามท้à¸à¸‡à¸–ิ่น:" +msgstr "à¹à¸—นที่ตามภูมิภาค:" #: editor/project_settings_editor.cpp msgid "Locale" -msgstr "ท้à¸à¸‡à¸–ิ่น" +msgstr "ภูมิภาค" #: editor/project_settings_editor.cpp msgid "Locales Filter" @@ -6626,10 +6622,6 @@ msgstr "รีซà¸à¸£à¹Œà¸ªà¸¢à¹ˆà¸à¸¢" msgid "Clear Inheritance" msgstr "ลบà¸à¸²à¸£à¸ªà¸·à¸šà¸—à¸à¸”" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "เปิดในโปรà¹à¸à¸£à¸¡à¹à¸à¹‰à¹„ข" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "ลบโหนด" @@ -6745,10 +6737,6 @@ msgstr "" "คลิà¸à¹€à¸žà¸·à¹ˆà¸à¹à¸ªà¸”งà¹à¸œà¸‡à¸à¸¥à¸¸à¹ˆà¸¡" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "à¸à¸´à¸™à¸ªà¹à¸•à¸™à¸‹à¹Œ:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "เปิดสคริปต์" @@ -7175,32 +7163,44 @@ msgid "Object can't provide a length." msgstr "ไม่สามารถบà¸à¸à¸„วามยาวขà¸à¸‡à¸§à¸±à¸•à¸–ุได้" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "ลบที่เลืà¸à¸à¹ƒà¸™ GridMap" +msgid "Next Plane" +msgstr "ระนาบถัดไป" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "ทำซ้ำใน GridMap" +msgid "Previous Plane" +msgstr "ระนาบà¸à¹ˆà¸à¸™à¸«à¸™à¹‰à¸²" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "ระนาบ:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "ไปชั้นบน" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "ไปชั้นล่าง" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "ชั้น:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "จำà¸à¸±à¸”ด้วยเส้นตาราง" +msgid "GridMap Delete Selection" +msgstr "ลบที่เลืà¸à¸à¹ƒà¸™ GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "บังคับà¹à¸™à¸§à¸•à¸²à¸£à¸²à¸‡" +msgid "GridMap Duplicate Selection" +msgstr "ทำซ้ำใน GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "ไปชั้นล่าง" +msgid "Grid Map" +msgstr "จำà¸à¸±à¸”ด้วยเส้นตาราง" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "ไปชั้นบน" +msgid "Snap View" +msgstr "บังคับà¹à¸™à¸§à¸•à¸²à¸£à¸²à¸‡" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7307,6 +7307,10 @@ msgid "Mono" msgstr "โมโน" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¸à¸²à¸£à¸ªà¸™à¸±à¸šà¸ªà¸™à¸¸à¸™ C#" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "สร้าง C# solution" @@ -7322,6 +7326,10 @@ msgstr "Build โปรเจà¸à¸•à¹Œ" msgid "Warnings" msgstr "คำเตืà¸à¸™" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7837,6 +7845,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin ต้à¸à¸‡à¸¡à¸µ ARVRCamera เป็นโหนดลูà¸" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(เหลืà¸à¸à¸µà¸: %d:%02d วิ)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "วางà¹à¸™à¸§ meshes: " @@ -8018,6 +8034,23 @@ msgstr "ผิดพลาดขณะโหลดฟà¸à¸™à¸•à¹Œ" msgid "Invalid font size." msgstr "ขนาดฟà¸à¸™à¸•à¹Œà¸œà¸´à¸”พลาด" +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "รูปà¹à¸šà¸šà¸‚à¸à¸‡ version.txt ในà¹à¸¡à¹ˆà¹à¸šà¸šà¹„ม่ถูà¸à¸•à¹‰à¸à¸‡ หมายเลขรุ่น revision ต้à¸à¸‡à¹ƒà¸Šà¹‰à¸£à¸°à¸šà¸¸à¹„ด้" + +#~ msgid "Can't write file." +#~ msgstr "เขียนไฟล์ไม่ได้" + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "à¸à¸£à¸¸à¸“าเลืà¸à¸à¹‚ฟลเดà¸à¸£à¹Œà¸—ี่ไม่มีไฟล์ 'project.godot'" + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "ไม่พบไฟล์ project.godot" + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "ไม่พบไฟล์ project.godot" + #~ msgid "Next" #~ msgstr "ต่à¸à¹„ป" diff --git a/editor/translations/tr.po b/editor/translations/tr.po index 934077d896..bb485dc603 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -2453,14 +2453,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Åžablonların içinde geçersiz version.txt formatı." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Åžablonların içinde geçersiz version.txt formatı. Revizyon geçerli bir " -"tanımlayıcı deÄŸil." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Åžablonların içinde version.txt bulunamadı." @@ -2515,10 +2507,6 @@ msgid "Failed:" msgstr "BaÅŸarısız:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Dosyaya yazılamıyor." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Ä°ndirme Tamamlandı." @@ -3704,15 +3692,15 @@ msgid "Show Grid" msgstr "Izgarayı Göster" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Yardımcıları Göster" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Cetvelleri göster" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Kılavuzları göster" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4539,6 +4527,22 @@ msgid "Resource clipboard is empty!" msgstr "Kaynak panosu boÅŸ!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Düzenleyicide Aç" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "Örnek:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Tür:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Kaynak Yükle" @@ -4825,10 +4829,6 @@ msgid "Toggle Comment" msgstr "Yorumu Aç / Kapat" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "AÅŸağıya EÅŸle" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Satırı Katla/Aç" @@ -4841,6 +4841,10 @@ msgid "Unfold All Lines" msgstr "Tüm Satırları GeniÅŸlet" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "AÅŸağıya EÅŸle" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Simgeyi Tamamla" @@ -5684,11 +5688,6 @@ msgstr "Sekme 2" msgid "Tab 3" msgstr "Sekme 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Tür:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Veri Türü:" @@ -5956,10 +5955,6 @@ msgid "Please choose an empty folder." msgstr "Lütfen boÅŸ bir klasör seçin." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "Lütfen 'proje.godot' dosyası içermeyen bir klasör seçin." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "İçe Aktarılan Proje" @@ -5980,8 +5975,11 @@ msgid "Invalid project path (changed anything?)." msgstr "Geçersiz proje yolu (bir ÅŸey deÄŸiÅŸti mi?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "Proje yolunda proje.godot alınamadı." +#, fuzzy +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "proje yolundaki proje.godot düzenlenemedi." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6000,10 +5998,6 @@ msgid "Rename Project" msgstr "Projeyi Yeniden Adlandır" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "Proje yolunda proje.godot alınamadı." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Yeni Oyun Projesi" @@ -6706,10 +6700,6 @@ msgstr "Alt Kaynaklar" msgid "Clear Inheritance" msgstr "Kalıtı Temizle" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Düzenleyicide Aç" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Düğümleri Sil" @@ -6827,10 +6817,6 @@ msgstr "" "Gruplar dokunu göstermek için tıkla." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "Örnek:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Betik Aç" @@ -7258,32 +7244,46 @@ msgid "Object can't provide a length." msgstr "Nesne bir uzunluk saÄŸlayamaz." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "IzgaraHaritası Seçimi Sil" +#, fuzzy +msgid "Next Plane" +msgstr "Sonraki sekme" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "IzgaraHaritası Seçimi ÇoÄŸalt" +#, fuzzy +msgid "Previous Plane" +msgstr "Önceki sekme" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "Sonraki Zemin" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Önceki Zemin" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Zemin:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Izgara Haritası" +msgid "GridMap Delete Selection" +msgstr "IzgaraHaritası Seçimi Sil" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "Yapışma Görünümü" +msgid "GridMap Duplicate Selection" +msgstr "IzgaraHaritası Seçimi ÇoÄŸalt" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Önceki Zemin" +msgid "Grid Map" +msgstr "Izgara Haritası" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "Sonraki Zemin" +msgid "Snap View" +msgstr "Yapışma Görünümü" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7390,6 +7390,10 @@ msgid "Mono" msgstr "Tekli" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "C# Çözümü oluÅŸtur" @@ -7405,6 +7409,10 @@ msgstr "Projeyi Ä°nÅŸa et" msgid "Warnings" msgstr "Uyarılar" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7955,6 +7963,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin bir ARVRCamera çocuk düğümü gerektirir" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "Örüntüler Haritalanıyor: " @@ -8155,6 +8171,25 @@ msgstr "Yazıtipi yükleme hatası." msgid "Invalid font size." msgstr "Geçersiz yazıtipi boyutu." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Åžablonların içinde geçersiz version.txt formatı. Revizyon geçerli bir " +#~ "tanımlayıcı deÄŸil." + +#~ msgid "Can't write file." +#~ msgstr "Dosyaya yazılamıyor." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "Lütfen 'proje.godot' dosyası içermeyen bir klasör seçin." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "Proje yolunda proje.godot alınamadı." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "Proje yolunda proje.godot alınamadı." + #~ msgid "Next" #~ msgstr "Sonraki" diff --git a/editor/translations/uk.po b/editor/translations/uk.po index d01686aec4..685812f2d4 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: Ukrainian (Godot Engine)\n" -"PO-Revision-Date: 2018-01-24 17:51+0000\n" +"PO-Revision-Date: 2018-02-22 18:08+0000\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/" "godot/uk/>\n" @@ -22,7 +22,7 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 2.19-dev\n" +"X-Generator: Weblate 2.20-dev\n" #: editor/animation_editor.cpp msgid "Disabled" @@ -2456,14 +2456,6 @@ msgid "Invalid version.txt format inside templates." msgstr "Ðеправильний формат version.txt у шаблонах." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" -"Ðеправильний формат version.txt у шаблонах. Ідентифікатор ревізії не Ñ” " -"дійÑним." - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "Файл version.txt не знайдено у шаблонах." @@ -2518,10 +2510,6 @@ msgid "Failed:" msgstr "Ðе вдалоÑÑ:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл." - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð¾." @@ -3708,15 +3696,15 @@ msgid "Show Grid" msgstr "Показати Ñітку" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "Показати помічники" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "Показати лінійки" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "Показати напрÑмні" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4545,6 +4533,22 @@ msgid "Resource clipboard is empty!" msgstr "Ð’ буфері обміну немає реÑурÑу!" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "Відкрити в редакторі" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "ЕкземплÑÑ€:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "Тип:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "Завантажити реÑурÑ" @@ -4831,10 +4835,6 @@ msgid "Toggle Comment" msgstr "Перемкнути коментар" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "Клонувати вниз" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "Згорнути/розгорнути Ñ€Ñдок" @@ -4847,6 +4847,10 @@ msgid "Unfold All Lines" msgstr "Розгорнути вÑÑ– Ñ€Ñдки" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "Клонувати вниз" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "Завершити Ñимвол" @@ -5690,11 +5694,6 @@ msgstr "Вкладка 2" msgid "Tab 3" msgstr "Вкладка 3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "Тип:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "Тип даних:" @@ -5964,10 +5963,6 @@ msgid "Please choose an empty folder." msgstr "Будь лаÑка, виберіть порожню теку." #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "Будь лаÑка, виберіть теку, у Ñкій не міÑтитьÑÑ Ñ„Ð°Ð¹Ð»Ð° «project.godot»." - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "Імпортований проект" @@ -5988,8 +5983,12 @@ msgid "Invalid project path (changed anything?)." msgstr "Ðекоректний шлÑÑ… до проекту (щоÑÑŒ змінилоÑÑ?)." #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ project.godot з каталогу проекту." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "" +"Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ project.godot у каталозі проекту (помилка %d). " +"Можливо, файл вилучено або пошкоджено." #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -6008,10 +6007,6 @@ msgid "Rename Project" msgstr "Перейменувати проект" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ project.godot у каталозі проекту." - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "Ðовий проект гри" @@ -6716,10 +6711,6 @@ msgstr "ПідреÑурÑи" msgid "Clear Inheritance" msgstr "УÑунути уÑпадкуваннÑ" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "Відкрити в редакторі" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "Вилучити вузли" @@ -6837,10 +6828,6 @@ msgstr "" "Клацніть, щоб переглÑнути панель груп." #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "ЕкземплÑÑ€:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "Відкрити Ñкрипт" @@ -7270,32 +7257,44 @@ msgid "Object can't provide a length." msgstr "Об'єкт не може надавати довжину." #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "Ð’Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾Ð³Ð¾ GridMap" +msgid "Next Plane" +msgstr "ÐаÑтупна площина" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "Ð”ÑƒÐ±Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾Ð³Ð¾ GridMap" +msgid "Previous Plane" +msgstr "ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ð¿Ð»Ð¾Ñ‰Ð¸Ð½Ð°" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "Площина:" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "ÐаÑтупний поверх" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "Попередній поверх" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "Поверх:" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" -msgstr "Карта Ñітки" +msgid "GridMap Delete Selection" +msgstr "Ð’Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾Ð³Ð¾ GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "Миттєвий переглÑд" +msgid "GridMap Duplicate Selection" +msgstr "Ð”ÑƒÐ±Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾Ð³Ð¾ GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" -msgstr "Попередній поверх" +msgid "Grid Map" +msgstr "Карта Ñітки" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "ÐаÑтупний поверх" +msgid "Snap View" +msgstr "Миттєвий переглÑд" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7402,6 +7401,10 @@ msgid "Mono" msgstr "Моно" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "Про підтримку C#" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "Створити розв'Ñзок C#" @@ -7417,6 +7420,10 @@ msgstr "Зібрати проект" msgid "Warnings" msgstr "ПопередженнÑ" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7968,6 +7975,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin повинен мати дочірній вузол ARVRCamera" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "%d%%" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "(ЛишилоÑÑ Ñ‡Ð°Ñу: %d:%02d Ñ)" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "Побудова Ñітки: " @@ -8170,6 +8185,26 @@ msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑˆÑ€Ð¸Ñ„Ñ‚Ñƒ." msgid "Invalid font size." msgstr "Ðекоректний розмір шрифту." +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "" +#~ "Ðеправильний формат version.txt у шаблонах. Ідентифікатор ревізії не Ñ” " +#~ "дійÑним." + +#~ msgid "Can't write file." +#~ msgstr "Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл." + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "" +#~ "Будь лаÑка, виберіть теку, у Ñкій не міÑтитьÑÑ Ñ„Ð°Ð¹Ð»Ð° «project.godot»." + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ project.godot з каталогу проекту." + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ project.godot у каталозі проекту." + #~ msgid "Next" #~ msgstr "Далі" diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index 9fae520b55..96fbfbeee6 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -2377,12 +2377,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2435,11 +2429,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -#, fuzzy -msgid "Can't write file." -msgstr "سب سکریپشن بنائیں" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3610,15 +3599,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4449,6 +4438,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4732,10 +4737,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4748,6 +4749,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5595,11 +5600,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5860,10 +5860,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5885,7 +5881,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5906,10 +5904,6 @@ msgid "Rename Project" msgstr ".تمام کا انتخاب" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6601,10 +6595,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6717,10 +6707,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "سب سکریپشن بنائیں" @@ -7152,32 +7138,44 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "GridMap Delete Selection" -msgstr ".تمام کا انتخاب" +msgid "Next Plane" +msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +msgid "Previous Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Delete Selection" +msgstr ".تمام کا انتخاب" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "GridMap Duplicate Selection" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7286,6 +7284,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "سب سکریپشن بنائیں" @@ -7302,6 +7304,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7806,6 +7812,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -7967,5 +7981,9 @@ msgstr "" msgid "Invalid font size." msgstr "" +#, fuzzy +#~ msgid "Can't write file." +#~ msgstr "سب سکریپشن بنائیں" + #~ msgid "Samples" #~ msgstr "نمونے" diff --git a/editor/translations/vi.po b/editor/translations/vi.po index 018883dc91..c39ccc4db9 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -2368,12 +2368,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2426,10 +2420,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3594,15 +3584,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4425,6 +4415,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4707,10 +4713,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "" @@ -4723,6 +4725,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5563,11 +5569,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5827,10 +5828,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5851,7 +5848,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5871,10 +5870,6 @@ msgid "Rename Project" msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6564,10 +6559,6 @@ msgstr "" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6677,10 +6668,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "" @@ -7103,11 +7090,24 @@ msgid "Object can't provide a length." msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" +msgid "Next Plane" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" +#, fuzzy +msgid "Previous Plane" +msgstr "ThÆ° mục trÆ°á»›c" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7115,19 +7115,19 @@ msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "GridMap Delete Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "GridMap Duplicate Selection" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Grid Map" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7235,6 +7235,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7250,6 +7254,10 @@ msgstr "" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7749,6 +7757,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index debb1d60f3..9c55ece6db 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -3,6 +3,8 @@ # Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) # This file is distributed under the same license as the Godot source code. # +# 360119124 <360119124@qq.com>, 2018. +# æŸ æª¬æ€æ‰‹ <lemonkiller@gmail.com>, 2018. # 纯æ´çš„å蛋 <tqj.zyy@gmail.com>, 2016. # å¤æœˆè“风 <trlanfeng@foxmail.com>, 2016. # å´äº®å¼Ÿ <wu@liangdi.me>, 2017. @@ -23,8 +25,8 @@ msgid "" msgstr "" "Project-Id-Version: Chinese (Simplified) (Godot Engine)\n" "POT-Creation-Date: 2018-01-20 12:15+0200\n" -"PO-Revision-Date: 2018-01-20 12:54+0000\n" -"Last-Translator: Geequlim <geequlim@gmail.com>\n" +"PO-Revision-Date: 2018-02-03 05:35+0000\n" +"Last-Translator: 360119124 <360119124@qq.com>\n" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hans/>\n" "Language: zh_CN\n" @@ -48,11 +50,11 @@ msgstr "修改动画关键帧的时间" #: editor/animation_editor.cpp msgid "Anim Change Transition" -msgstr "动画å˜åŒ–过渡" +msgstr "修改动画过渡方å¼" #: editor/animation_editor.cpp msgid "Anim Change Transform" -msgstr "修改å˜æ¢" +msgstr "修改动画å˜æ¢" #: editor/animation_editor.cpp msgid "Anim Change Keyframe Value" @@ -100,7 +102,7 @@ msgstr "轨é“修改为值模å¼" #: editor/animation_editor.cpp msgid "Anim Track Change Wrap Mode" -msgstr "轨é“修改为包装模å¼" +msgstr "轨é“修改为包围模å¼" #: editor/animation_editor.cpp msgid "Edit Node Curve" @@ -108,7 +110,7 @@ msgstr "编辑节点曲线" #: editor/animation_editor.cpp msgid "Edit Selection Curve" -msgstr "编辑选项曲线" +msgstr "编辑所选曲线" #: editor/animation_editor.cpp msgid "Anim Delete Keys" @@ -133,7 +135,7 @@ msgstr "è¿žç»" #: editor/animation_editor.cpp msgid "Discrete" -msgstr "分离" +msgstr "离散" #: editor/animation_editor.cpp msgid "Trigger" @@ -198,7 +200,7 @@ msgstr "优化动画" #: editor/animation_editor.cpp msgid "Clean-Up Animation" -msgstr "清ç†åŠ¨ç”»" +msgstr "清空动画" #: editor/animation_editor.cpp msgid "Create NEW track for %s and insert key?" @@ -222,7 +224,7 @@ msgstr "创建|æ’入动画" #: editor/animation_editor.cpp msgid "Anim Insert Track & Key" -msgstr "创建|æ’å…¥ 轨é“和关键帧" +msgstr "æ’入轨é“和关键帧" #: editor/animation_editor.cpp msgid "Anim Insert Key" @@ -246,11 +248,11 @@ msgstr "æ’入动画" #: editor/animation_editor.cpp msgid "Anim Scale Keys" -msgstr "缩放键" +msgstr "缩放关键帧" #: editor/animation_editor.cpp msgid "Anim Add Call Track" -msgstr "æ·»åŠ å›žè°ƒè½¨é“" +msgstr "æ·»åŠ è°ƒç”¨è½¨é“" #: editor/animation_editor.cpp msgid "Animation zoom." @@ -298,11 +300,11 @@ msgstr "轨é“工具" #: editor/animation_editor.cpp msgid "Enable editing of individual keys by clicking them." -msgstr "å…许通过å•å‡»å¯ç”¨å„个键的编辑。" +msgstr "å…许通过å•å‡»ç¼–辑å„个关键帧。" #: editor/animation_editor.cpp msgid "Anim. Optimizer" -msgstr "优化动画" +msgstr "动画优化器" #: editor/animation_editor.cpp msgid "Max. Linear Error:" @@ -310,11 +312,11 @@ msgstr "最大线性错误:" #: editor/animation_editor.cpp msgid "Max. Angular Error:" -msgstr "最大角错误:" +msgstr "最大角度错误:" #: editor/animation_editor.cpp msgid "Max Optimizable Angle:" -msgstr "调整最大的角度:" +msgstr "调整最大的å¯ä¼˜åŒ–角度:" #: editor/animation_editor.cpp msgid "Optimize" @@ -338,7 +340,7 @@ msgstr "缩放比率:" #: editor/animation_editor.cpp msgid "Call Functions in Which Node?" -msgstr "在那个节点ä¸è°ƒç”¨å‡½æ•°ï¼Ÿ" +msgstr "在哪个节点ä¸è°ƒç”¨å‡½æ•°ï¼Ÿ" #: editor/animation_editor.cpp msgid "Remove invalid keys" @@ -358,7 +360,7 @@ msgstr "清除所有动画å—ï¼ˆæ— æ³•æ’¤é”€ï¼ï¼‰" #: editor/animation_editor.cpp msgid "Clean-Up" -msgstr "清ç†" +msgstr "清空" #: editor/array_property_edit.cpp msgid "Resize Array" @@ -430,13 +432,13 @@ 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:" @@ -1075,7 +1077,7 @@ msgstr "[空]" #: editor/editor_data.cpp msgid "[unsaved]" -msgstr "[ä½ä¿å˜]" +msgstr "[未ä¿å˜]" #: editor/editor_dir_dialog.cpp msgid "Please select a base directory first" @@ -1336,8 +1338,8 @@ msgid "" "$url]contribute one[/url][/color] or [color=$color][url=$url2]request one[/" "url][/color]." msgstr "" -"暂时没有æ¤ç±»åž‹çš„说明。请帮通过[color=$color][url=$url] 补充文档或æ交请求 [/" -"url][/color]çš„æ–¹å¼å¸®åŠ©æˆ‘们完善文档!" +"当å‰æ²¡æœ‰æ¤ç±»åž‹çš„教程。请通过[color=$color][url=$url] 补充文档或æ交请求 [/" +"url][/color]çš„æ–¹å¼å¸®åŠ©æˆ‘们完善文档。" #: editor/editor_help.cpp msgid "Properties" @@ -1368,7 +1370,7 @@ msgid "" "There is currently no description for this method. Please help us by [color=" "$color][url=$url]contributing one[/url][/color]!" msgstr "" -"当å‰æ²¡æœ‰æ¤æ–¹æ³•çš„说明。请帮助我们通过 [color=$color] [url=$url] 贡献一个 [/" +"当å‰æ²¡æœ‰æ¤æ–¹æ³•çš„æ述。请帮助我们通过 [color=$color] [url=$url] 贡献一个 [/" "url][/color]!" #: editor/editor_help.cpp @@ -2338,7 +2340,7 @@ msgstr "" #: editor/editor_run_script.cpp msgid "Write your logic in the _run() method." -msgstr "在_run()æ–¹ä¸å¡«å†™æ‚¨çš„逻辑代ç 。" +msgstr "在_run()方法ä¸å¡«å†™æ‚¨çš„逻辑代ç 。" #: editor/editor_run_script.cpp msgid "There is an edited scene already." @@ -2417,12 +2419,6 @@ msgid "Invalid version.txt format inside templates." msgstr "模æ¿æ–‡ä»¶ä¸çš„version.txtä¸åˆæ³•ã€‚" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "模æ¿ä¸çš„ version.txtæ–‡ä»¶æ ¼å¼ä¸åˆæ³•ï¼Œæ— æ•ˆçš„ç‰ˆæœ¬æ ‡è¯†ç¬¦ã€‚" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "模æ¿ä¸æ²¡æœ‰æ‰¾åˆ°version.txt文件。" @@ -2475,10 +2471,6 @@ msgid "Failed:" msgstr "失败:" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "æ— æ³•å†™å…¥æ–‡ä»¶ã€‚" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "下载完æˆ" @@ -2488,11 +2480,11 @@ msgstr "请求链接错误: " #: editor/export_template_manager.cpp msgid "Connecting to Mirror.." -msgstr "æ£åœ¨è¿žæŽ¥é•œåƒ..." +msgstr "æ£åœ¨è¿žæŽ¥é•œåƒâ€¦â€¦" #: editor/export_template_manager.cpp msgid "Disconnected" -msgstr "链接已æ–å¼€" +msgstr "å·²æ–å¼€" #: editor/export_template_manager.cpp msgid "Resolving" @@ -2518,7 +2510,7 @@ msgstr "已连接" #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Requesting.." -msgstr "æ£åœ¨è¯·æ±‚.." +msgstr "æ£åœ¨è¯·æ±‚……" #: editor/export_template_manager.cpp msgid "Downloading" @@ -3040,7 +3032,7 @@ msgstr "穿过" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Future" -msgstr "" +msgstr "未æ¥" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Depth" @@ -3650,15 +3642,15 @@ msgid "Show Grid" msgstr "æ˜¾ç¤ºç½‘æ ¼" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "显示辅助线" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "æ˜¾ç¤ºæ ‡å°º" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "æ˜¾ç¤ºæ ‡å°º " #: editor/plugins/canvas_item_editor_plugin.cpp @@ -3723,7 +3715,7 @@ msgstr "好的" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Cannot instantiate multiple nodes without root." -msgstr "" +msgstr "æ— æ³•å®žä¾‹åŒ–æ²¡æœ‰æ ¹çš„å¤šä¸ªèŠ‚ç‚¹ã€‚" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp @@ -3933,7 +3925,7 @@ msgstr "包å«çš„Meshä¸æ˜¯ArrayMesh类型。" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "UV Unwrap failed, mesh may not be manifold?" -msgstr "" +msgstr "UV展开失败,å¯èƒ½è¯¥ç½‘æ ¼å¹¶éžæµå½¢ï¼Ÿ" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "No mesh to debug." @@ -3993,7 +3985,7 @@ msgstr "查看UV2" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Unwrap UV2 for Lightmap/AO" -msgstr "" +msgstr "ä¸ºå…‰ç…§æ˜ å°„/环境光é®è”½å±•å¼€UV2" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Outline Mesh" @@ -4486,6 +4478,22 @@ msgid "Resource clipboard is empty!" msgstr "资æºå‰ªåˆ‡æ¿ä¸æ— 内容ï¼" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "在编辑器ä¸æ‰“å¼€" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "实例:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "类型:" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "åŠ è½½èµ„æº" @@ -4771,10 +4779,6 @@ msgid "Toggle Comment" msgstr "切æ¢æ³¨é‡Š" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "æ‹·è´åˆ°ä¸‹ä¸€è¡Œ" - -#: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" msgstr "切æ¢å è¡Œ" @@ -4787,6 +4791,10 @@ msgid "Unfold All Lines" msgstr "å–消折å 所有行" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "æ‹·è´åˆ°ä¸‹ä¸€è¡Œ" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "代ç 补全" @@ -5630,11 +5638,6 @@ msgstr "分页2" msgid "Tab 3" msgstr "分页3" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "类型:" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "æ•°æ®ç±»åž‹:" @@ -5761,7 +5764,7 @@ msgstr "错误" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Autotiles" -msgstr "" +msgstr "智能瓦片" #: editor/plugins/tile_set_editor_plugin.cpp msgid "" @@ -5897,10 +5900,6 @@ msgid "Please choose an empty folder." msgstr "请选择一个空目录。" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "请选择一个ä¸åŒ…å«'project.godot'文件的文件夹。" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "已导入的项目" @@ -5921,8 +5920,11 @@ msgid "Invalid project path (changed anything?)." msgstr "项目路径éžæ³•ï¼ˆè¢«å¤–部修改?)。" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." -msgstr "æ— æ³•åœ¨é¡¹ç›®ç›®å½•ä¸‹æ‰¾åˆ°project.godot文件。" +#, fuzzy +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." +msgstr "æ— æ³•åœ¨é¡¹ç›®ç›®å½•ä¸‹ç¼–è¾‘project.godot文件。" #: editor/project_manager.cpp msgid "Couldn't edit project.godot in project path." @@ -5941,10 +5943,6 @@ msgid "Rename Project" msgstr "é‡å‘½å项目" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "æ— æ³•åœ¨é¡¹ç›®ç›®å½•ä¸‹æ‰¾åˆ°project.godot文件。" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "新建游æˆé¡¹ç›®" @@ -6486,15 +6484,15 @@ msgstr "选择属性" #: editor/property_selector.cpp msgid "Select Virtual Method" -msgstr "选择虚拟方法 " +msgstr "选择虚方法" #: editor/property_selector.cpp msgid "Select Method" -msgstr "选择方å¼" +msgstr "选择方法" #: editor/pvrtc_compress.cpp msgid "Could not execute PVRTC tool:" -msgstr "æ— æ³•æ‰§è¡ŒPVPTC工具:" +msgstr "æ— æ³•æ‰§è¡ŒPVRTC工具:" #: editor/pvrtc_compress.cpp msgid "Can't load back converted image using PVRTC tool:" @@ -6641,10 +6639,6 @@ msgstr "å资æº" msgid "Clear Inheritance" msgstr "清除继承" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "在编辑器ä¸æ‰“å¼€" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "åˆ é™¤èŠ‚ç‚¹" @@ -6708,9 +6702,8 @@ msgid "Clear a script for the selected node." msgstr "清除选ä¸èŠ‚点的脚本。" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Remote" -msgstr "移除" +msgstr "远程" #: editor/scene_tree_dock.cpp msgid "Local" @@ -6761,10 +6754,6 @@ msgstr "" "å•å‡»æ˜¾ç¤ºåˆ†ç»„æ 。" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "实例:" - -#: editor/scene_tree_editor.cpp msgid "Open script" msgstr "打开脚本" @@ -7192,34 +7181,46 @@ msgid "Object can't provide a length." msgstr "å¯¹è±¡æ— æ³•æ供长度。" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Delete Selection" -msgstr "åˆ é™¤é€‰æ‹©çš„GridMap" +#, fuzzy +msgid "Next Plane" +msgstr "下一项" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "GridMap Duplicate Selection" -msgstr "å¤åˆ¶é€‰ä¸é¡¹" +#, fuzzy +msgid "Previous Plane" +msgstr "上一个目录" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Plane:" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Next Floor" +msgstr "下一层" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Previous Floor" +msgstr "上一个层" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Floor:" msgstr "层:" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "Grid Map" -msgstr "ç½‘æ ¼å¸é™„" +msgid "GridMap Delete Selection" +msgstr "åˆ é™¤é€‰æ‹©çš„GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" -msgstr "å¸é™„视图" +msgid "GridMap Duplicate Selection" +msgstr "å¤åˆ¶é€‰ä¸é¡¹" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy -msgid "Previous Floor" -msgstr "上一个目录" +msgid "Grid Map" +msgstr "ç½‘æ ¼æ˜ å°„" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" -msgstr "下一层" +msgid "Snap View" +msgstr "å¸é™„视图" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -7326,6 +7327,10 @@ msgid "Mono" msgstr "Mono" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "创建C#解决方案" @@ -7341,6 +7346,10 @@ msgstr "构建项目" msgid "Warnings" msgstr "è¦å‘Š" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7670,7 +7679,7 @@ msgstr "脚本ä¸æœªæ‰¾åˆ°VariableSet: " #: modules/visual_script/visual_script_nodes.cpp msgid "Custom node has no _step() method, can't process graph." -msgstr "自定义脚本节点ä¸åŒ…å«_step()方法,ä¸èƒ½ç”Ÿæˆå›¾ã€‚" +msgstr "自定义节点ä¸åŒ…å«_step()方法,ä¸èƒ½ç”Ÿæˆå›¾åƒã€‚" #: modules/visual_script/visual_script_nodes.cpp msgid "" @@ -7858,23 +7867,28 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "ARVROrigin 必须拥有 ARVRCamera å节点" #: scene/3d/baked_lightmap.cpp -#, fuzzy +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " -msgstr "æ£åœ¨ç»˜åˆ¶ç½‘æ ¼" +msgstr "æ£åœ¨ç»˜åˆ¶ç½‘æ ¼ï¼š " #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Plotting Lights:" -msgstr "æ£åœ¨ç»˜åˆ¶ç½‘æ ¼" +msgstr "æ£åœ¨ç»˜åˆ¶ç¯å…‰ï¼š" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp msgid "Finishing Plot" msgstr "æ£åœ¨å®Œæˆåˆ’分" #: scene/3d/baked_lightmap.cpp -#, fuzzy msgid "Lighting Meshes: " -msgstr "æ£åœ¨ç»˜åˆ¶ç½‘æ ¼" +msgstr "æ£åœ¨å¯¹ç½‘æ ¼è¿›è¡Œç…§æ˜Ž " #: scene/3d/collision_object.cpp msgid "" @@ -8045,6 +8059,23 @@ msgstr "åŠ è½½å—体出错。" msgid "Invalid font size." msgstr "å—体大å°éžæ³•ã€‚" +#~ msgid "" +#~ "Invalid version.txt format inside templates. Revision is not a valid " +#~ "identifier." +#~ msgstr "模æ¿ä¸çš„ version.txtæ–‡ä»¶æ ¼å¼ä¸åˆæ³•ï¼Œæ— æ•ˆçš„ç‰ˆæœ¬æ ‡è¯†ç¬¦ã€‚" + +#~ msgid "Can't write file." +#~ msgstr "æ— æ³•å†™å…¥æ–‡ä»¶ã€‚" + +#~ msgid "Please choose a folder that does not contain a 'project.godot' file." +#~ msgstr "请选择一个ä¸åŒ…å«'project.godot'文件的文件夹。" + +#~ msgid "Couldn't get project.godot in project path." +#~ msgstr "æ— æ³•åœ¨é¡¹ç›®ç›®å½•ä¸‹æ‰¾åˆ°project.godot文件。" + +#~ msgid "Couldn't get project.godot in the project path." +#~ msgstr "æ— æ³•åœ¨é¡¹ç›®ç›®å½•ä¸‹æ‰¾åˆ°project.godot文件。" + #~ msgid "Next" #~ msgstr "下一项" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index 3b380305d0..6e2e5ac502 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -2520,12 +2520,6 @@ msgid "Invalid version.txt format inside templates." msgstr "無效的 version.txt æ ¼å¼ inside templates." #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp #, fuzzy msgid "No version.txt found inside templates." msgstr "找ä¸åˆ°version.txt inside templates." @@ -2583,11 +2577,6 @@ msgstr "失敗:" #: editor/export_template_manager.cpp #, fuzzy -msgid "Can't write file." -msgstr "無法新增資料夾" - -#: editor/export_template_manager.cpp -#, fuzzy msgid "Download Complete." msgstr "下載出ç¾éŒ¯èª¤" @@ -3792,15 +3781,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4637,6 +4626,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4930,10 +4935,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "跳到行" @@ -4947,6 +4948,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5805,11 +5810,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -6080,10 +6080,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -6105,7 +6101,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -6126,10 +6124,6 @@ msgid "Rename Project" msgstr "專案" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6837,10 +6831,6 @@ msgstr "資æº" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6955,10 +6945,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "下一個腳本" @@ -7400,32 +7386,46 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "刪除é¸ä¸æª”案" +msgid "Next Plane" +msgstr "下一個" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "複製 Selection" +msgid "Previous Plane" +msgstr "上一個tab" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +msgid "Previous Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Previous Floor" +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Delete Selection" +msgstr "刪除é¸ä¸æª”案" + +#: modules/gridmap/grid_map_editor_plugin.cpp +#, fuzzy +msgid "GridMap Duplicate Selection" +msgstr "複製 Selection" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7540,6 +7540,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp #, fuzzy msgid "Create C# solution" msgstr "縮放selection" @@ -7557,6 +7561,10 @@ msgstr "專案" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -8078,6 +8086,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" @@ -8240,6 +8256,10 @@ msgstr "載入å—形出ç¾éŒ¯èª¤" msgid "Invalid font size." msgstr "無效å—åž‹" +#, fuzzy +#~ msgid "Can't write file." +#~ msgstr "無法新增資料夾" + #~ msgid "Next" #~ msgstr "下一個" diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index abdbf6dc2b..2d67ef98c1 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -2400,12 +2400,6 @@ msgid "Invalid version.txt format inside templates." msgstr "" #: editor/export_template_manager.cpp -msgid "" -"Invalid version.txt format inside templates. Revision is not a valid " -"identifier." -msgstr "" - -#: editor/export_template_manager.cpp msgid "No version.txt found inside templates." msgstr "" @@ -2460,10 +2454,6 @@ msgid "Failed:" msgstr "" #: editor/export_template_manager.cpp -msgid "Can't write file." -msgstr "" - -#: editor/export_template_manager.cpp msgid "Download Complete." msgstr "" @@ -3650,15 +3640,15 @@ msgid "Show Grid" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show helpers" +msgid "Show Helpers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show rulers" +msgid "Show Rulers" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp -msgid "Show guides" +msgid "Show Guides" msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp @@ -4492,6 +4482,22 @@ msgid "Resource clipboard is empty!" msgstr "" #: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp +msgid "Open in Editor" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/scene_tree_editor.cpp +msgid "Instance:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp +#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp +#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp +msgid "Type:" +msgstr "" + +#: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Load Resource" msgstr "" @@ -4780,10 +4786,6 @@ msgid "Toggle Comment" msgstr "" #: editor/plugins/script_text_editor.cpp -msgid "Clone Down" -msgstr "" - -#: editor/plugins/script_text_editor.cpp #, fuzzy msgid "Fold/Unfold Line" msgstr "å‰å¾€ç¬¬...è¡Œ" @@ -4797,6 +4799,10 @@ msgid "Unfold All Lines" msgstr "" #: editor/plugins/script_text_editor.cpp +msgid "Clone Down" +msgstr "" + +#: editor/plugins/script_text_editor.cpp msgid "Complete Symbol" msgstr "" @@ -5646,11 +5652,6 @@ msgstr "" msgid "Tab 3" msgstr "" -#: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp -#: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp -msgid "Type:" -msgstr "" - #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" msgstr "" @@ -5916,10 +5917,6 @@ msgid "Please choose an empty folder." msgstr "" #: editor/project_manager.cpp -msgid "Please choose a folder that does not contain a 'project.godot' file." -msgstr "" - -#: editor/project_manager.cpp msgid "Imported Project" msgstr "" @@ -5941,7 +5938,9 @@ msgid "Invalid project path (changed anything?)." msgstr "" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in project path." +msgid "" +"Couldn't load project.godot in project path (error %d). It may be missing or " +"corrupted." msgstr "" #: editor/project_manager.cpp @@ -5962,10 +5961,6 @@ msgid "Rename Project" msgstr "專案è¨å®š" #: editor/project_manager.cpp -msgid "Couldn't get project.godot in the project path." -msgstr "" - -#: editor/project_manager.cpp msgid "New Game Project" msgstr "" @@ -6664,10 +6659,6 @@ msgstr "複製資æº" msgid "Clear Inheritance" msgstr "" -#: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp -msgid "Open in Editor" -msgstr "" - #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" msgstr "" @@ -6779,10 +6770,6 @@ msgid "" msgstr "" #: editor/scene_tree_editor.cpp -msgid "Instance:" -msgstr "" - -#: editor/scene_tree_editor.cpp #, fuzzy msgid "Open script" msgstr "開啟最近å˜å–" @@ -7224,33 +7211,47 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Delete Selection" -msgstr "複製所é¸" +msgid "Next Plane" +msgstr "下個分é " #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "GridMap Duplicate Selection" -msgstr "複製所é¸" +msgid "Previous Plane" +msgstr "上個分é " #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Floor:" +msgid "Plane:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Grid Map" +msgid "Next Floor" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Snap View" +#, fuzzy +msgid "Previous Floor" +msgstr "上個分é " + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Floor:" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp #, fuzzy -msgid "Previous Floor" -msgstr "上個分é " +msgid "GridMap Delete Selection" +msgstr "複製所é¸" #: modules/gridmap/grid_map_editor_plugin.cpp -msgid "Next Floor" +#, fuzzy +msgid "GridMap Duplicate Selection" +msgstr "複製所é¸" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Grid Map" +msgstr "" + +#: modules/gridmap/grid_map_editor_plugin.cpp +msgid "Snap View" msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp @@ -7363,6 +7364,10 @@ msgid "Mono" msgstr "" #: modules/mono/editor/godotsharp_editor.cpp +msgid "About C# support" +msgstr "" + +#: modules/mono/editor/godotsharp_editor.cpp msgid "Create C# solution" msgstr "" @@ -7379,6 +7384,10 @@ msgstr "專案è¨å®š" msgid "Warnings" msgstr "" +#: modules/mono/mono_gd/gd_mono_utils.cpp +msgid "End of inner exception stack trace" +msgstr "" + #: modules/visual_script/visual_script.cpp msgid "" "A node yielded without working memory, please read the docs on how to yield " @@ -7893,6 +7902,14 @@ msgid "ARVROrigin requires an ARVRCamera child node" msgstr "" #: scene/3d/baked_lightmap.cpp +msgid "%d%%" +msgstr "" + +#: scene/3d/baked_lightmap.cpp +msgid "(Time Left: %d:%02d s)" +msgstr "" + +#: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " msgstr "" diff --git a/main/SCsub b/main/SCsub index 5748bc38d2..9eddc4f5b6 100644 --- a/main/SCsub +++ b/main/SCsub @@ -2,71 +2,139 @@ Import('env') from compat import byte_to_str - +from collections import OrderedDict def make_splash(target, source, env): src = source[0].srcnode().abspath dst = target[0].srcnode().abspath - f = open(src, "rb") - g = open(dst, "w") - buf = f.read() + with open(src, "rb") as f: + buf = f.read() - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef BOOT_SPLASH_H\n") - g.write("#define BOOT_SPLASH_H\n") - g.write('static const Color boot_splash_bg_color = Color::html("#232323");\n') - g.write("static const unsigned char boot_splash_png[] = {\n") - for i in range(len(buf)): - g.write(byte_to_str(buf[i]) + ",\n") - g.write("};\n") - g.write("#endif") + with open(dst, "w") as g: + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef BOOT_SPLASH_H\n") + g.write("#define BOOT_SPLASH_H\n") + g.write('static const Color boot_splash_bg_color = Color::html("#232323");\n') + g.write("static const unsigned char boot_splash_png[] = {\n") + for i in range(len(buf)): + g.write(byte_to_str(buf[i]) + ",\n") + g.write("};\n") + g.write("#endif") def make_splash_editor(target, source, env): src = source[0].srcnode().abspath dst = target[0].srcnode().abspath - f = open(src, "rb") - g = open(dst, "w") - buf = f.read() - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef BOOT_SPLASH_EDITOR_H\n") - g.write("#define BOOT_SPLASH_EDITOR_H\n") - g.write('static const Color boot_splash_editor_bg_color = Color::html("#232323");\n') - g.write("static const unsigned char boot_splash_editor_png[] = {\n") - for i in range(len(buf)): - g.write(byte_to_str(buf[i]) + ",\n") - g.write("};\n") - g.write("#endif") + with open(src, "rb") as f: + buf = f.read() + with open(dst, "w") as g: + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef BOOT_SPLASH_EDITOR_H\n") + g.write("#define BOOT_SPLASH_EDITOR_H\n") + g.write('static const Color boot_splash_editor_bg_color = Color::html("#232323");\n') + g.write("static const unsigned char boot_splash_editor_png[] = {\n") + for i in range(len(buf)): + g.write(byte_to_str(buf[i]) + ",\n") + g.write("};\n") + g.write("#endif") def make_app_icon(target, source, env): src = source[0].srcnode().abspath dst = target[0].srcnode().abspath - f = open(src, "rb") - g = open(dst, "w") - buf = f.read() + with open(src, "rb") as f: + buf = f.read() + + with open(dst, "w") as g: + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#ifndef APP_ICON_H\n") + g.write("#define APP_ICON_H\n") + g.write("static const unsigned char app_icon_png[] = {\n") + for i in range(len(buf)): + g.write(byte_to_str(buf[i]) + ",\n") + g.write("};\n") + g.write("#endif") + +def make_default_controller_mappings(target, source, env): + dst = target[0].srcnode().abspath + g = open(dst, "w") g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#ifndef APP_ICON_H\n") - g.write("#define APP_ICON_H\n") - g.write("static const unsigned char app_icon_png[] = {\n") - for i in range(len(buf)): - g.write(byte_to_str(buf[i]) + ",\n") - g.write("};\n") - g.write("#endif") + g.write("#include \"default_controller_mappings.h\"\n") + g.write("#include \"typedefs.h\"\n") + + # ensure mappings have a consistent order + platform_mappings = OrderedDict() + for src in source: + src_path = src.srcnode().abspath + with open(src_path, "r") as f: + # read mapping file and skip header + mapping_file_lines = f.readlines()[2:] + + current_platform = None + for line in mapping_file_lines: + if not line: + continue + line = line.strip() + if len(line) == 0: + continue + if line[0] == "#": + current_platform = line[1:].strip() + if current_platform not in platform_mappings: + platform_mappings[current_platform] = {} + elif current_platform: + line_parts = line.split(",") + guid = line_parts[0] + if guid in platform_mappings[current_platform]: + g.write("// WARNING - DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format(src_path, current_platform, platform_mappings[current_platform][guid])) + valid_mapping = True + for input_map in line_parts[2:]: + if "+" in input_map or "-" in input_map or "~" in input_map: + g.write("// WARNING - DISCARDED UNSUPPORTED MAPPING TYPE FROM DATABASE {}: {} {}\n".format(src_path, current_platform, line)) + valid_mapping = False + break + if valid_mapping: + platform_mappings[current_platform][guid] = line + + platform_variables = { + "Linux": "#if X11_ENABLED", + "Windows": "#ifdef WINDOWS_ENABLED", + "Mac OS X": "#ifdef OSX_ENABLED", + "Android": "#if defined(__ANDROID__)", + "iOS": "#ifdef IPHONE_ENABLED", + "Javascript": "#ifdef JAVASCRIPT_ENABLED", + "UWP": "#ifdef UWP_ENABLED", + } + + g.write("const char* DefaultControllerMappings::mappings[] = {\n") + for platform, mappings in platform_mappings.items(): + variable = platform_variables[platform] + g.write("{}\n".format(variable)) + for mapping in mappings.values(): + g.write("\t\"{}\",\n".format(mapping)) + g.write("#endif\n") + g.write("};\n") + g.close() env.main_sources = [] env.add_source_files(env.main_sources, "*.cpp") +# order matters here. higher index controller database files write on top of lower index database files +controller_databases = ["#main/gamecontrollerdb.txt", "#main/gamecontrollerdb_205.txt", "#main/gamecontrollerdb_204.txt", "#main/godotcontrollerdb.txt"] + +env.Depends("#main/default_controller_mappings.gen.cpp", controller_databases) +env.Command("#main/default_controller_mappings.gen.cpp", controller_databases, make_default_controller_mappings) + +env.main_sources.append("#main/default_controller_mappings.gen.cpp") + Export('env') env.Depends("#main/splash.gen.h", "#main/splash.png") diff --git a/main/default_controller_mappings.h b/main/default_controller_mappings.h new file mode 100644 index 0000000000..6319b875eb --- /dev/null +++ b/main/default_controller_mappings.h @@ -0,0 +1,39 @@ +/*************************************************************************/ +/* default_controller_mappings.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 DEFAULT_CONTROLLER_MAPPINGS_H +#define DEFAULT_CONTROLLER_MAPPINGS_H + +class DefaultControllerMappings { +public: + static const char *mappings[]; +}; + +#endif // DEFAULT_CONTROLLER_MAPPINGS_H diff --git a/main/gamecontrollerdb.txt b/main/gamecontrollerdb.txt new file mode 100644 index 0000000000..80687bd037 --- /dev/null +++ b/main/gamecontrollerdb.txt @@ -0,0 +1,423 @@ +# Game Controller DB for SDL in 2.0.6 format +# Source: https://github.com/gabomdq/SDL_GameControllerDB + +# Windows +03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, +03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, +030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows, +03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, +030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, +030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows, +03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows, +030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, +03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, +0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows, +03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows, +03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows, +03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, +03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, +03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, +03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows, +03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows, +03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, +030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows, +03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, +030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, + +# Mac OS X +03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X, +03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X, +0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, +03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X, +030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, +03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, +030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000005e0400008e02000001000000,Steam Virtual GamePad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, +03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, +03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, +050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, +050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, +030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, + +# Linux +03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, +03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, +03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux, +03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, +03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux, +030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, +03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, +030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux, +03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, +050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, +030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, +03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux, +030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, +05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, +03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +03000000250900006688000000010000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux, +050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux, +03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c0500006802000000800000,PS3 Controller (Bluetooth),a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, +030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, +030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, +03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, +03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, +03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux, +03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux, +03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000ad1b000038f0000090040000,Street Fighter IV FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, +030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, +05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, +0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux, +03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, + +# Android +64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, +5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android, +34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, + +# iOS +4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, +4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,
\ No newline at end of file diff --git a/main/gamecontrollerdb_204.txt b/main/gamecontrollerdb_204.txt new file mode 100644 index 0000000000..7f3068d1b1 --- /dev/null +++ b/main/gamecontrollerdb_204.txt @@ -0,0 +1,269 @@ +# Game Controller DB for SDL in 2.0.4 format +# Source: https://github.com/gabomdq/SDL_GameControllerDB + +# Windows +02200090000000000000504944564944,8Bitdo NES30 PRO USB,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +8f0e1200000000000000504944564944,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +c0111352000000000000504944564944,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, +d81d0b00000000000000504944564944,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +e8206058000000000000504944564944,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +5e048e02000000000000504944564944,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +791d0103000000000000504944564944,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +0d0f8500000000000000504944564944,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0d0f5e00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:a3,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +0d0f5f00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0d0f8400000000000000504944564944,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +0d0f8700000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +0d0f8800000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +0d0f2700000000000000504944564944,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +28040140000000000000504944564944,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +45130010000000000000504944564944,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +d8140862000000000000504944564944,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +0d0f4000000000000000504944564944,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0d0fee00000000000000504944564944,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +0d0f4d00000000000000504944564944,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +25090017000000000000504944564944,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, +d81d0f00000000000000504944564944,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +d81d1000000000000000504944564944,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows, +6f0e2401000000000000504944564944,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +6d0418c2000000000000504944564944,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +38075032000000000000504944564944,Mad Catz FightPad PRO PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +38075082000000000000504944564944,Mad Catz FightPad PRO PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +38078433000000000000504944564944,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +38078483000000000000504944564944,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +38078134000000000000504944564944,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +38078184000000000000504944564944,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +38078034000000000000504944564944,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +38078084000000000000504944564944,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +38078532000000000000504944564944,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +38073888000000000000504944564944,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +38071888000000000000504944564944,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +25090128000000000000504944564944,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, +79004318000000000000504944564944,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +8f0e1030000000000000504944564944,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, +2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +8f0e0d31000000000000504944564944,Multilaser JS071 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b9,platform:Windows, +bd1215d0000000000000504944564944,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows, +36280100000000000000504944564944,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b15,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b14,x:b1,y:b2,platform:Windows, +4d6963726f736f66742050432d6a6f79,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a5,righty:a4,x:b1,y:b2,platform:Windows, +120cf60e000000000000504944564944,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +8f0e0300000000000000504944564944,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +10080100000000000000504944564944,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +10080300000000000000504944564944,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, +10008200000000000000504944564944,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +300f0011000000000000504944564944,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, +300f1611000000000000504944564944,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +222c0020000000000000504944564944,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, +300f1210000000000000504944564944,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +341a0104000000000000504944564944,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, +222c0223000000000000504944564944,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +222c0023000000000000504944564944,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +0d0f1100000000000000504944564944,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +0d0f6a00000000000000504944564944,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +0d0f6b00000000000000504944564944,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0d0f8a00000000000000504944564944,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +0d0f8b00000000000000504944564944,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0d0f7000000000000000504944564944,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +0d0f2200000000000000504944564944,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +300f1201000000000000504944564944,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b9,rightx:a2,righty:a3,start:b4,x:b0,y:b1,platform:Windows, +300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +9b280500000000000000504944564944,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +79001100000000000000504944564944,Sega Saturn Gamepad,a:b1,b:b2,leftshoulder:b6,lefttrigger:b3,leftx:a0,lefty:a4,rightshoulder:b7,righttrigger:b0,start:b8,x:b4,y:b5,platform:Windows, +4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +ff113133000000000000504944564944,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows, +4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, +66660488000000000000504944564944,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +38076652000000000000504944564944,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +63252305000000000000504944564944,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +79001b18000000000000504944564944,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, + +# Mac OS X +10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +830500000000000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X, +AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +0d0f0000000000004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, +79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +d814000000000000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +8f0e0000000000000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, +4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +79000000000000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +81170000000000007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, +b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, +351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +4c05000000000000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +11010000000000002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, +11010000000000001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, +4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, +4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, +bd1200000000000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +10080000000000000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, +050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, +050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, +5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +5e04000000000000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +5e04000000000000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +5e04000000000000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, + +# Linux +05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b1,y:b3,platform:Linux, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, +03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, +030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, +03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, +030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, +03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000016c2000010010000,Logitech Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, +05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, +03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000dd02000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b9,platform:Linux, +050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, +030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000790000001100000010010000,RetroLink Saturn Classic Controller,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, +0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, +03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, +03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux, +030000004c050000c405000011810000,Sony DualShock 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000cc09000000810000,Sony DualShock 4 (CUH-ZCT2U) (Bluetooth),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000cc09000011810000,Sony DualShock 4 (CUH-ZCT2U) (USB),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, +030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, + +# Android +4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, + +# iOS +4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, +4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,
\ No newline at end of file diff --git a/main/gamecontrollerdb_205.txt b/main/gamecontrollerdb_205.txt new file mode 100644 index 0000000000..4c3eae623c --- /dev/null +++ b/main/gamecontrollerdb_205.txt @@ -0,0 +1,337 @@ +# Game Controller DB for SDL in 2.0.5 format +# Source: https://github.com/gabomdq/SDL_GameControllerDB + +# Windows +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +e8206058000000000000504944564944,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows, +6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +6d0418c2000000000000504944564944,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +4d6963726f736f66742050432d6a6f79,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a5,righty:a4,x:b1,y:b2,platform:Windows, +4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, +10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows, +03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, +03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000a30600000cff000000000000,Saitek P2500,a:b2,b:b3,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b9,rightx:a2,righty:a3,start:b4,x:b0,y:b1,platform:Windows, +03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, +030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000888800000803000000000000,PS3,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows, +030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000790000001100000000000000,Sega Saturn Gamepad,a:b1,b:b2,leftshoulder:b6,lefttrigger:b3,leftx:a0,lefty:a4,rightshoulder:b7,righttrigger:b0,start:b8,x:b4,y:b5,platform:Windows, +03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000019c2000000000000,Logitech Cordless RumblePad 2 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000018c2000000000000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000016c2000000000000,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows, +030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, +030000004c050000cc09000000000000,Sony DualShock 4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows, +03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005082000000000000,Mad Catz FightPad PRO PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005032000000000000,Mad Catz FightPad PRO PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b15,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b14,x:b1,y:b2,platform:Windows, +03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, +03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, +03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, +0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, +03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, +03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, +03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000203800000900000000000000,8Bitdo NES30 PRO Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000001008000001e5000000000000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b9,platform:Windows, +03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006e00000000000000,HORIPAD 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005f00000000000000,Fighting Commander 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005e00000000000000,Fighting Commander 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:a3,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000022000000090000000000000,8Bitdo NES30 PRO USB,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, + +# Mac OS X +830500000000000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +11010000000000002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, +11010000000000001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, +10280000000000000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, +050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, +03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, +030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, +03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000790000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, +030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, +03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, +030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, + +# Linux +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +050000004c050000cc09000000810000,Sony DualShock 4 (CUH-ZCT2U) (Bluetooth),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c0500006802000000810000,Sony PLAYSTATION(R)3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, +03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, +03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, +03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux, +03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, +03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, +03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, +03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, +030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, +030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, +03000000790000001100000010010000,RetroLink Saturn Classic Controller,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, +03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, +03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, +03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, +030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000010010000,Logitech Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, +03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, +03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000005e040000dd02000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, +030000004c050000cc09000011810000,Sony DualShock 4 (CUH-ZCT2U) (USB),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000c405000011810000,Sony DualShock 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c0500006802000011810000,Sony PLAYSTATION(R)3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b1,y:b3,platform:Linux, +03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b9,platform:Linux, +03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, +0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, + +# Android +4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, + +# iOS +4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, +4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, diff --git a/main/godotcontrollerdb.txt b/main/godotcontrollerdb.txt new file mode 100644 index 0000000000..031a761f30 --- /dev/null +++ b/main/godotcontrollerdb.txt @@ -0,0 +1,38 @@ +# Game Controller DB for SDL in 2.0.6 format +# Source: https://github.com/godotengine/godot + +# Windows +9000318000000000000504944564944,Mayflash Wiimote PC Adapter,a:b2,b:h0.4,x:b0,y:b1,back:b4,start:b5,guide:b11,leftshoulder:b6,rightshoulder:b3,leftx:a0,lefty:a1,platform:Windows, +c911f055000000000000504944564944,GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +__XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Windows, + +# Linux +030000005e040000e302000003020000,Microsoft X-Box One Elite pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001302000000010000,Afterglow Gamepad for Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +05000000362800000100000004010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,platform:Windows, +030000005e0400001907000000010000,X360 Wireless Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.8,lefttrigger:a2,x:b2,dpup:h0.1,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,platform:Windows, +030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftstick:b9,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,platform:Windows, +03000000fd0500002a26000000010000,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b5,rightshoulder:b7,rightx:a2,start:b11,righty:a3,dpleft:h0.8,lefttrigger:b8,x:b0,dpup:h0.1,back:b10,leftstick:b2,leftshoulder:b6,y:b1,a:b3,dpright:h0.2,righttrigger:b9,b:b4,platform:Windows, +030000006f0e00002801000011010000,PDP Rock Candy Wireless Controller for PS3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b0,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:h0.2,righttrigger:b7,b:b2,platform:Windows, +030000000d0f00004d00000011010000,HORI Gem Pad 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows, + +# Android +4f5559412047616d6520436f6e74726f,OUYA Game Controller,leftx:a1,lefty:a3,dpdown:b12,rightstick:b8,rightshoulder:b10,rightx:a6,start:b-86,righty:a7,dpleft:b13,lefttrigger:b15,x:b2,dpup:b11,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:b14,righttrigger:b16,b:b1,platform:Windows, +Default Android Gamepad,Default Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,back:b4,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,platform:Windows, +532e542e442e20496e74657261637420,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b25,rightshoulder:b27,rightx:a2,start:b31,righty:a3,dpleft:h0.8,lefttrigger:b28,x:b20,dpup:h0.1,back:b30,leftstick:b22,leftshoulder:b26,y:b21,a:b23,dpright:h0.2,righttrigger:b29,b:b24,platform:Windows, +506572666f726d616e63652044657369,PDP Rock Candy Wireless Controller for PS3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b6,rightshoulder:b18,rightx:a2,start:b16,righty:a3,dpleft:h0.8,lefttrigger:b9,x:b0,dpup:h0.1,back:h0.2,leftstick:b4,leftshoulder:b3,y:b2,a:b1,dpright:h0.2,righttrigger:b10,b:b17,platform:Windows, +4d6963726f736f667420582d426f7820,Microsoft X-Box 360 pad,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,platform:Windows, +484f524920434f2e2c4c544420205041,Hori Gem Pad 3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b6,rightshoulder:b18,rightx:a2,start:b16,righty:a3,dpleft:h0.8,lefttrigger:b9,x:b0,dpup:h0.1,back:b15,leftstick:b4,leftshoulder:b3,y:b2,a:b1,dpright:h0.2,righttrigger:b10,b:b17,platform:Windows, +47656e6572696320582d426f78207061,Logitech F-310,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a5,x:b2,dpup:h0.1,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a4,b:b1,platform:Windows, + +# Javascript +Default HTML5 Gamepad, Default Mapping,leftx:a0,lefty:a1,dpdown:b13,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:b14,lefttrigger:a6,x:b2,dpup:b12,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:b15,righttrigger:a7,b:b1,platform:Windows, +c2a94d6963726f736f66742058626f78,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,platform:Windows, +303534632d303563342d576972656c65,PS4 Controller USB/Win,leftx:a0,lefty:a1,dpdown:b15,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,lefttrigger:a3,x:b0,dpup:b14,dpleft:b16,dpright:b17,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,righttrigger:b7,b:b2,platform:Windows, +303534632d303563342d536f6e792043,PS4 Controller USB/Linux,leftx:a0,lefty:a1,dpdown:a7,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,dpleft:a6,lefttrigger:a3,x:b0,dpup:a7,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:a6,righttrigger:a4,b:b2,platform:Windows, +303534632d303236382d536f6e792050,PS3 Controller USB/Linux,leftx:a0,lefty:a1,dpdown:b6,rightstick:b2,rightshoulder:b11,rightx:a2,start:b3,righty:a3,dpleft:b7,lefttrigger:b8,x:b15,dpup:b4,back:b0,leftstick:b1,leftshoulder:b10,y:b12,a:b14,dpright:b5,righttrigger:b9,b:b13,platform:Windows, +303435652d303731392d58626f782033,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,platform:Windows, +303435652d303238652d4d6963726f73,Wired X360 Controller,leftx:a0,lefty:a1,dpdown:a7,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:a6,lefttrigger:a2,x:b2,dpup:a7,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:a6,righttrigger:a5,b:b1,platform:Windows, + +# UWP +__UWP_GAMEPAD__,Xbox Controller,a:b2,b:b3,x:b4,y:b5,start:b0,back:b1,leftstick:b12,rightstick:b13,leftshoulder:b10,rightshoulder:b11,dpup:b6,dpdown:b7,dpleft:b8,dpright:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Windows,
\ No newline at end of file diff --git a/main/input_default.cpp b/main/input_default.cpp index 5057c5f53a..c3bc83b2de 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -30,6 +30,7 @@ #include "input_default.h" +#include "default_controller_mappings.h" #include "input_map.h" #include "os/os.h" #include "scene/resources/texture.h" @@ -429,7 +430,7 @@ Point2 InputDefault::get_last_mouse_speed() const { int InputDefault::get_mouse_button_mask() const { - return mouse_button_mask; // do not trust OS implementaiton, should remove it - OS::get_singleton()->get_mouse_button_state(); + return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state(); } void InputDefault::warp_mouse_position(const Vector2 &p_to) { @@ -525,292 +526,6 @@ void InputDefault::set_mouse_in_window(bool p_in_window) { */ } -// from github.com/gabomdq/SDL_GameControllerDB -static const char *s_ControllerMappings[] = { -#ifdef WINDOWS_ENABLED - "00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "02200090000000000000504944564944,8Bitdo NES30 PRO USB,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", - "03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,", - "0d0f1100000000000000504944564944,REAL ARCADE PRO.3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,", - "0d0f2200000000000000504944564944,REAL ARCADE Pro.V3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "0d0f2700000000000000504944564944,FIGHTING STICK V3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,", - "0d0f4000000000000000504944564944,Hori Fighting Stick Mini 3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b4,righttrigger:b6,", - "0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "0d0f4d00000000000000504944564944,HORIPAD3 A,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "0d0f5e00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a4,righttrigger:a3,", - "0d0f5f00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "0d0f6a00000000000000504944564944,Real Arcade Pro.4,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", - "0d0f6b00000000000000504944564944,Real Arcade Pro.4,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "0d0f7000000000000000504944564944,REAL ARCADE PRO.4 VLX,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,", - "0d0f8400000000000000504944564944,Fighting Commander 5,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,", - "0d0f8500000000000000504944564944,Fighting Commander 2016 PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "0d0f8700000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,", - "0d0f8800000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,x:b0,y:b3,back:b9,guide:b12,start:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,", - "0d0f8a00000000000000504944564944,Real Arcade Pro.4,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", - "0d0f8b00000000000000504944564944,Real Arcade Pro.4,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "10008200000000000000504944564944,PS360+ v1.66,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:h0.4,lefttrigger:b6,righttrigger:b7,", - "10080100000000000000504944564944,PS1 USB,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", - "100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,", - "10080300000000000000504944564944,PS2 USB,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,", - "10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,", - "120cf60e000000000000504944564944,P4 Wired Gamepad,a:b1,b:b2,x:b0,y:b3,back:b12,guide:b8,start:b9,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:h0.0,lefttrigger:b7,righttrigger:b6,", - "20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", - "222c0020000000000000504944564944,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:a3,righttrigger:a4,", - "222c0023000000000000504944564944,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,x:b0,y:b3,back:b13,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "222c0223000000000000504944564944,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "25090017000000000000504944564944,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b5,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b6,", - "25090128000000000000504944564944,Mayflash Arcade Stick,a:b1,b:b2,x:b5,y:b6,back:b8,start:b9,leftshoulder:b0,rightshoulder:b3,leftx:a0,lefty:a1,rightx:h0.4,righty:h0.0,lefttrigger:b4,righttrigger:b7,", - "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,", - "2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "28040140000000000000504944564944,GamePad Pro USB,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,", - "300f0011000000000000504944564944,QanBa Arcade JoyStick 1008,x:b0,a:b1,b:b2,y:b3,back:b8,start:b10,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,", - "300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,", - "300f1201000000000000504944564944,Saitek Dual Analog Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,", - "300f1210000000000000504944564944,QanBa Joystick Plus,a:b0,b:b1,x:b2,y:b3,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,", - "300f1611000000000000504944564944,QanBa Arcade JoyStick 4018,a:b1,b:b2,x:b0,y:b3,back:b10,guide:b9,start:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,", - "341a0104000000000000504944564944,QanBa Joystick Q4RAF,a:b5,b:b6,x:b1,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b0,rightshoulder:b3,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b7,", - "341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", - "36280100000000000000504944564944,OUYA Controller,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,", - "38071888000000000000504944564944,MadCatz SFIV FightStick PS3,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b6,", - "38073888000000000000504944564944,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "38075032000000000000504944564944,Mad Catz FightPad PRO PS3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "38075082000000000000504944564944,Mad Catz FightPad PRO PS4,x:b0,a:b1,b:b2,y:b3,back:b13,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", - "38076652000000000000504944564944,UnKnown,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "38078034000000000000504944564944,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "38078084000000000000504944564944,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "38078134000000000000504944564944,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b7,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b4,", - "38078184000000000000504944564944,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b5,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a4,righttrigger:b7,", - "38078433000000000000504944564944,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,", - "38078483000000000000504944564944,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:b6,", - "38078532000000000000504944564944,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "45130010000000000000504944564944,Generic USB Joystick,a:b0,b:b1,x:b2,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,", - "4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,", - "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", - "4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", - "4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", - "4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,", - "5e048e02000000000000504944564944,Controller (XBOX 360 For Windows),x:b2,a:b0,b:b1,y:b3,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,righttrigger:a2,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "63252305000000000000504944564944,USB Vibration Joystick (BM),x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "66660488000000000000504944564944,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:b12,dpdown:b14,dpleft:b15,dpright:b13,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,", - "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", - "6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", - "6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", - "6f0e2401000000000000504944564944,INJUSTICE FightStick for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2", - "79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,", - "79001100000000000000504944564944,Sega Saturn Gamepad,a:b1,b:b2,x:b4,y:b5,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a4,lefttrigger:b3,righttrigger:b0,", - "79001b18000000000000504944564944,Venom Arcade Joystick,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,", - "79004318000000000000504944564944,Mayflash GameCube Controller Adapter,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", - "83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,", - "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,", - "8f0e0300000000000000504944564944,Piranha xtreme,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", - "8f0e0d31000000000000504944564944,Multilaser JS071 USB,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "8f0e1030000000000000504944564944,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,x:b3,y:b4,start:b9,leftshoulder:b6,rightshoulder:b2,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b5,righttrigger:b7,", - "8f0e1200000000000000504944564944,Acme,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", - "9000318000000000000504944564944,Mayflash Wiimote PC Adapter,a:b2,b:h0.4,x:b0,y:b1,back:b4,start:b5,guide:b11,leftshoulder:b6,rightshoulder:b3,leftx:a0,lefty:a1,", - "9b280500000000000000504944564944,Saturn_Adapter_2.0,a:b1,b:b2,x:b0,y:b3,start:b9,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b5,", - "a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "bd1215d0000000000000504944564944,Nintendo Retrolink USB Super SNES Classic Controller,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,start:b9,back:b8,leftx:a0,lefty:a1,", - "c0111352000000000000504944564944,Battalife Joystick,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,", - "c911f055000000000000504944564944,GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", - "d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "d8140862000000000000504944564944,HitBox Edition Cthulhu+,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b5,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b4,righttrigger:b6,", - "d81d0b00000000000000504944564944,BUFFALO BSGP1601 Series ,x:b4,a:b5,b:b3,y:b2,back:b12,start:b13,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b6,rightshoulder:b9,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "d81d0f00000000000000504944564944,iBUFFALO BSGP1204 Series,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "d81d1000000000000000504944564944,iBUFFALO BSGP1204P Series,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "ff113133000000000000504944564944,SVEN X-PAD,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,", - "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", - "__XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", -#endif - -#ifdef OSX_ENABLED - "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", - "050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,", - "050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,", - "0d0f0000000000004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,", - "10080000000000000100000000000000,Twin USB Joystick,a:b4,b:b2,x:b6,y:b0,back:b16,start:b18,leftstick:b20,rightstick:b22,leftshoulder:b12,rightshoulder:b14,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a2,rightx:a6,righty:a4,lefttrigger:b8,righttrigger:b10,", - "10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", - "4c05000000000000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", - "4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", - "4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", - "5e04000000000000dd02000000000000,Xbox One Wired Controller,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "5e04000000000000e002000000000000,Xbox Wireless Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "5e04000000000000ea02000000000000,Xbox Wireless Controller,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", - "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", - "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", - "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", - "79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,", - "79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,", - "79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,", - "81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,", - "83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,", - "891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", - "8f0e0000000000000300000000000000,Piranha xtreme,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", - "AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", - "ad1b00000000000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", - "b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,", - "d814000000000000cecf000000000000,MC Cthulhu,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,", -#endif - -#if X11_ENABLED - "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "030000000d0f00000d00000000010000,hori,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,", - "030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7", - "030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,", - "030000000d0f00004d00000011010000,HORI Gem Pad 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,", - "030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,", - "03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,", - "03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,", - "03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", - "03000000280400000140000000010000,Gravis GamePad Pro USB ,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,", - "03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,x:b0,a:b2,b:b3,y:b1,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", - "03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,", - "03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,", - "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", - "030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,", - "030000004c050000c405000011810000,Sony DualShock 4,a:b0,b:b1,y:b2,x:b3,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", - "030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "030000004c050000cc09000011810000,Sony DualShock 4 (CUH-ZCT2U) (USB),a:b0,b:b1,y:b2,x:b3,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", - "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", - "030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,", - "030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", - "030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", - "030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", - "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e0400008502000000010000,Microsoft X-Box pad (Japan),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftstick:b9,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,", - "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", - "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000005e0400008e02000062230000,Microsoft X-Box 360 pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", - "030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e040000d102000001010000,Microsoft X-Box One pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000005e040000e302000003020000,Microsoft X-Box One Elite pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,", - "030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,", - "030000006d04000016c2000010010000,Logitech Logitech Dual Action,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", - "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", - "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "030000006f0e00000103000000020000,Logic3 Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000006f0e00001302000000010000,Afterglow Gamepad for Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000006f0e00001304000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", - "030000006f0e00001f01000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000006f0e00002801000011010000,PDP Rock Candy Wireless Controller for PS3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b0,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:h0.2,righttrigger:b7,b:b2,", - "030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "03000000780000000600000010010000,Microntek USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,", - "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "03000000790000001100000010010000,RetroLink Saturn Classic Controller,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,", - "030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", - "030000008916000001fd000024010000,Razer Onza Classic Edition,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", - "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", - "030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,x:b1,a:b0,b:b4,y:b5,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,", - "03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,", - "03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,", - "03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,", - "03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", - "03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", - "03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5,", - "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,", - "03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,", - "03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,x:b13,y:b11,back:b4,start:b5,leftstick:b14,rightstick:b15,leftshoulder:b9,rightshoulder:b8,dpup:b0,dpdown:b2,dpleft:b3,dpright:b1,leftx:a1,lefty:a0,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,y:b0,x:b1,b:b3,a:b4,leftshoulder:b2,rightshoulder:b5,back:b6,start:b7,guide:b9,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftx:a0,lefty:a1,", - "03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,", - "03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,", - "03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,", - "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,", - "03000000fd0500002a26000000010000,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b5,rightshoulder:b7,rightx:a2,start:b11,righty:a3,dpleft:h0.8,lefttrigger:b8,x:b0,dpup:h0.1,back:b10,leftstick:b2,leftshoulder:b6,y:b1,a:b3,dpright:h0.2,righttrigger:b9,b:b4,", - "03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", - "05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", - "05000000102800000900000000010000,8Bitdo SFC30 GamePad,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,", - "05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,", - "05000000362800000100000004010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,", - "05000000380700006652000025010000,Mad Catz C.T.R.L.R ,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", - "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", - "050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,", - "050000004c050000c405000000010000,Sony DualShock 4 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", - "050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,", - "050000004c050000cc09000000810000,Sony DualShock 4 (CUH-ZCT2U) (Bluetooth),a:b0,b:b1,y:b2,x:b3,leftshoulder:b4,rightshoulder:b5,back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", - "05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,", - "050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,", - "05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", - "05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,", - "05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,", - "060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,", - "06000000adde0000efbe000002010000,Hidromancer Game Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", -#endif - -#if defined(__ANDROID__) - "Default Android Gamepad,Default Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,back:b4,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,", - "47656e6572696320582d426f78207061,Logitech F-310,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a5,x:b2,dpup:h0.1,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a4,b:b1,", - "484f524920434f2e2c4c544420205041,Hori Gem Pad 3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b6,rightshoulder:b18,rightx:a2,start:b16,righty:a3,dpleft:h0.8,lefttrigger:b9,x:b0,dpup:h0.1,back:b15,leftstick:b4,leftshoulder:b3,y:b2,a:b1,dpright:h0.2,righttrigger:b10,b:b17,", - "4d6963726f736f667420582d426f7820,Microsoft X-Box 360 pad,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,", - "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", - "532e542e442e20496e74657261637420,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b25,rightshoulder:b27,rightx:a2,start:b31,righty:a3,dpleft:h0.8,lefttrigger:b28,x:b20,dpup:h0.1,back:b30,leftstick:b22,leftshoulder:b26,y:b21,a:b23,dpright:h0.2,righttrigger:b29,b:b24,", - "506572666f726d616e63652044657369,PDP Rock Candy Wireless Controller for PS3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b6,rightshoulder:b18,rightx:a2,start:b16,righty:a3,dpleft:h0.8,lefttrigger:b9,x:b0,dpup:h0.1,back:h0.2,leftstick:b4,leftshoulder:b3,y:b2,a:b1,dpright:h0.2,righttrigger:b10,b:b17,", - "4f5559412047616d6520436f6e74726f,OUYA Game Controller,leftx:a1,lefty:a3,dpdown:b12,rightstick:b8,rightshoulder:b10,rightx:a6,start:b-86,righty:a7,dpleft:b13,lefttrigger:b15,x:b2,dpup:b11,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:b14,righttrigger:b16,b:b1,", -#endif - -#ifdef JAVASCRIPT_ENABLED - "Default HTML5 Gamepad, Default Mapping,leftx:a0,lefty:a1,dpdown:b13,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:b14,lefttrigger:a6,x:b2,dpup:b12,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:b15,righttrigger:a7,b:b1,", - "303435652d303238652d4d6963726f73,Wired X360 Controller,leftx:a0,lefty:a1,dpdown:a7,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:a6,lefttrigger:a2,x:b2,dpup:a7,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:a6,righttrigger:a5,b:b1,", - "303435652d303731392d58626f782033,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,", - "303534632d303236382d536f6e792050,PS3 Controller USB/Linux,leftx:a0,lefty:a1,dpdown:b6,rightstick:b2,rightshoulder:b11,rightx:a2,start:b3,righty:a3,dpleft:b7,lefttrigger:b8,x:b15,dpup:b4,back:b0,leftstick:b1,leftshoulder:b10,y:b12,a:b14,dpright:b5,righttrigger:b9,b:b13,", - "303534632d303563342d536f6e792043,PS4 Controller USB/Linux,leftx:a0,lefty:a1,dpdown:a7,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,dpleft:a6,lefttrigger:a3,x:b0,dpup:a7,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:a6,righttrigger:a4,b:b2,", - "303534632d303563342d576972656c65,PS4 Controller USB/Win,leftx:a0,lefty:a1,dpdown:b15,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,lefttrigger:a3,x:b0,dpup:b14,dpleft:b16,dpright:b17,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,righttrigger:b7,b:b2,", - "c2a94d6963726f736f66742058626f78,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,", -#endif - -#ifdef UWP_ENABLED - "__UWP_GAMEPAD__,Xbox Controller,a:b2,b:b3,x:b4,y:b5,start:b0,back:b1,leftstick:b12,rightstick:b13,leftshoulder:b10,rightshoulder:b11,dpup:b6,dpdown:b7,dpleft:b8,dpright:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", -#endif - NULL -}; - InputDefault::InputDefault() { mouse_button_mask = 0; @@ -847,9 +562,9 @@ InputDefault::InputDefault() { }; int i = 0; - while (s_ControllerMappings[i]) { + while (DefaultControllerMappings::mappings[i]) { - parse_mapping(s_ControllerMappings[i++]); + parse_mapping(DefaultControllerMappings::mappings[i++]); }; } @@ -1109,6 +824,10 @@ void InputDefault::parse_mapping(String p_mapping) { mapping.hat[i].index = 1024 + i; Vector<String> entry = p_mapping.split(","); + if (entry.size() < 2) { + return; + } + CharString uid; uid.resize(17); diff --git a/main/main.cpp b/main/main.cpp index f6b3bafc5a..a59ca3da3b 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -122,13 +122,21 @@ static bool force_lowdpi = false; static int init_screen = -1; static bool use_vsync = true; static bool editor = false; -static bool project_manager = false; static bool show_help = false; static bool disable_render_loop = false; static int fixed_fps = -1; +static bool auto_build_solutions = false; +static bool auto_quit = false; +static bool print_fps = false; static OS::ProcessID allow_focus_steal_pid = 0; +static bool project_manager = false; + +bool Main::is_project_manager() { + return project_manager; +} + void initialize_physics() { /// 3D Physics Server @@ -168,7 +176,7 @@ static String get_full_version_string() { String hash = String(VERSION_HASH); if (hash.length() != 0) hash = "." + hash.left(7); - return String(VERSION_MKSTRING) + hash; + return String(VERSION_FULL_BUILD) + hash; } //#define DEBUG_INIT @@ -199,6 +207,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n"); OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n"); #endif + OS::get_singleton()->print(" -q, --quit Quit after the first iteration.\n"); OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n"); OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n"); OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n"); @@ -247,6 +256,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n"); OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n"); OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n"); + OS::get_singleton()->print(" --print-fps Print the frames per second to the stdout.\n"); OS::get_singleton()->print("\n"); OS::get_singleton()->print("Standalone tools:\n"); @@ -256,6 +266,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --export-debug Use together with --export, enables debug mode for the template.\n"); OS::get_singleton()->print(" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n"); OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n"); + OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects).\n"); #ifdef DEBUG_METHODS_ENABLED OS::get_singleton()->print(" --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n"); #endif @@ -340,6 +351,7 @@ 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; + bool found_project = false; packed_data = PackedData::get_singleton(); if (!packed_data) @@ -521,6 +533,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (I->get() == "-p" || I->get() == "--project-manager") { // starts project manager project_manager = true; + } else if (I->get() == "--build-solutions") { // Build the scripting solution such C# + + auto_build_solutions = true; #endif } else if (I->get() == "--no-window") { // disable window creation, Windows only @@ -547,6 +562,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } else if (I->get() == "-u" || I->get() == "--upwards") { // scan folders upwards upwards = true; + } else if (I->get() == "-q" || I->get() == "--quit") { // Auto quit at the end of the first main loop iteration + auto_quit = true; } else if (I->get().ends_with("project.godot")) { String path; String file = I->get(); @@ -650,6 +667,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->print("Missing fixed-fps argument, aborting.\n"); goto error; } + } else if (I->get() == "--print-fps") { + print_fps = true; } else if (I->get() == "--disable-crash-handler") { OS::get_singleton()->disable_crash_handler(); } else { @@ -674,6 +693,19 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph I = N; } + if (globals->setup(game_path, main_pack, upwards) == OK) { + found_project = true; + } else { + +#ifdef TOOLS_ENABLED + editor = false; +#else + OS::get_singleton()->print("Error: Could not load game path '%s'.\n", game_path.ascii().get_data()); + + goto error; +#endif + } + GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60); GLOBAL_DEF("network/limits/debugger_stdout/max_chars_per_second", 2048); GLOBAL_DEF("network/limits/debugger_stdout/max_messages_per_frame", 10); @@ -746,26 +778,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph #endif - if (globals->setup(game_path, main_pack, upwards) != OK) { - -#ifdef TOOLS_ENABLED - editor = false; -#else - OS::get_singleton()->print("Error: Could not load game path '%s'.\n", game_path.ascii().get_data()); - - goto error; -#endif - } else if (String(GLOBAL_DEF("application/run/main_scene", "")) == "") { -#ifdef TOOLS_ENABLED - if (!editor) { -#endif - OS::get_singleton()->print("Error: Can't run project: no main scene defined.\n"); - goto error; -#ifdef TOOLS_ENABLED - } -#endif - } - GLOBAL_DEF("logging/file_logging/enable_file_logging", false); GLOBAL_DEF("logging/file_logging/log_path", "user://logs/log.txt"); GLOBAL_DEF("logging/file_logging/max_log_files", 10); @@ -775,6 +787,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->add_logger(memnew(RotatedFileLogger(base_path, max_files))); } +#ifdef TOOLS_ENABLED if (editor) { Engine::get_singleton()->set_editor_hint(true); main_args.push_back("--editor"); @@ -782,7 +795,30 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph init_maximized = true; video_mode.maximized = true; } + } + + if (!project_manager) { + // Determine if the project manager should be requested + project_manager = main_args.size() == 0 && !found_project; + } +#endif + + if (main_args.size() == 0 && String(GLOBAL_DEF("application/run/main_scene", "")) == "") { +#ifdef TOOLS_ENABLED + if (!editor && !project_manager) { +#endif + OS::get_singleton()->print("Error: Can't run project: no main scene defined.\n"); + goto error; +#ifdef TOOLS_ENABLED + } +#endif + } + + if (editor || project_manager) { use_custom_res = false; + input_map->load_default(); //keys for editor + } else { + input_map->load_from_globals(); //keys for game } if (bool(ProjectSettings::get_singleton()->get("application/run/disable_stdout"))) { @@ -797,31 +833,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->set_cmdline(execpath, main_args); -#ifdef TOOLS_ENABLED - - if (!project_manager) { - // Determine if the project manager should be requested - project_manager = - main_args.size() == 0 && - !ProjectSettings::get_singleton()->has_setting("application/run/main_loop_type") && - (!ProjectSettings::get_singleton()->has_setting("application/run/main_scene") || - String(ProjectSettings::get_singleton()->get("application/run/main_scene")) == ""); - } - - if (project_manager) { - use_custom_res = false; //project manager (run without arguments) + GLOBAL_DEF("rendering/quality/driver/driver_name", "GLES3"); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/driver/driver_name", PropertyInfo(Variant::STRING, "rendering/quality/driver/driver_name", PROPERTY_HINT_ENUM, "GLES3,GLES2")); + if (video_driver == "") { + video_driver = GLOBAL_GET("rendering/quality/driver/driver_name"); } -#endif - - if (editor) - input_map->load_default(); //keys for editor - else - input_map->load_from_globals(); //keys for game - - //if (video_driver == "") // useless for now, so removing - // video_driver = GLOBAL_DEF("display/driver/name", Variant((const char *)OS::get_singleton()->get_video_driver_name(0))); - GLOBAL_DEF("display/window/size/width", 1024); GLOBAL_DEF("display/window/size/height", 600); GLOBAL_DEF("display/window/size/resizable", true); @@ -940,7 +957,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF("physics/common/physics_fps", 60)); Engine::get_singleton()->set_target_fps(GLOBAL_DEF("debug/settings/fps/force_fps", 0)); - GLOBAL_DEF("debug/settings/stdout/print_fps", OS::get_singleton()->is_stdout_verbose()); + GLOBAL_DEF("debug/settings/stdout/print_fps", false); if (!OS::get_singleton()->_verbose_stdout) //overridden OS::get_singleton()->_verbose_stdout = GLOBAL_DEF("debug/settings/stdout/verbose_stdout", false); @@ -1099,7 +1116,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { MAIN_PRINT("Main: Create bootsplash"); #if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH) - Ref<Image> splash = editor ? memnew(Image(boot_splash_editor_png)) : memnew(Image(boot_splash_png)); + Ref<Image> splash = (editor || project_manager) ? memnew(Image(boot_splash_editor_png)) : memnew(Image(boot_splash_png)); #else Ref<Image> splash = memnew(Image(boot_splash_png)); #endif @@ -1125,7 +1142,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { ProjectSettings::get_singleton()->set_custom_property_info("application/config/icon", PropertyInfo(Variant::STRING, "application/config/icon", PROPERTY_HINT_FILE, "*.png,*.webp")); if (bool(GLOBAL_DEF("display/window/handheld/emulate_touchscreen", false))) { - if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton() && !editor) { + if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton() && !(editor || project_manager)) { //only if no touchscreen ui hint, set emulation InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton()); if (id) @@ -1213,7 +1230,6 @@ bool Main::start() { ERR_FAIL_COND_V(!_start_success, false); bool hasicon = false; - bool editor = false; String doc_tool; List<String> removal_docs; bool doc_base = true; @@ -1447,7 +1463,7 @@ bool Main::start() { { } - if (!editor) { + if (!editor && !project_manager) { //standard helpers that can be changed from main config String stretch_mode = GLOBAL_DEF("display/window/stretch/mode", "disabled"); @@ -1558,7 +1574,7 @@ bool Main::start() { #endif } - if (!project_manager && !editor) { + if (!project_manager && !editor) { // game if (game_path != "" || script != "") { //autoload List<PropertyInfo> props; @@ -1640,7 +1656,6 @@ bool Main::start() { sml->get_root()->add_child(E->get()); } - //singletons } if (game_path != "") { @@ -1815,9 +1830,13 @@ bool Main::iteration() { if (frame > 1000000) { - if (GLOBAL_DEF("debug/settings/stdout/print_fps", OS::get_singleton()->is_stdout_verbose()) && !editor) { - print_line("FPS: " + itos(frames)); - }; + if (editor || project_manager) { + if (print_fps) { + print_line("Editor FPS: " + itos(frames)); + } + } else if (GLOBAL_GET("debug/settings/stdout/print_fps") || print_fps) { + print_line("Game FPS: " + itos(frames)); + } Engine::get_singleton()->_fps = frames; performance->set_process_time(USEC_TO_SEC(idle_process_max)); @@ -1850,7 +1869,16 @@ bool Main::iteration() { target_ticks = MIN(MAX(target_ticks, current_ticks - time_step), current_ticks + time_step); } - return exit; +#ifdef TOOLS_ENABLED + if (auto_build_solutions) { + auto_build_solutions = false; + if (!EditorNode::get_singleton()->call_build()) { + ERR_FAIL_V(true); + } + } +#endif + + return exit || auto_quit; } void Main::force_redraw() { diff --git a/main/main.h b/main/main.h index 1165c79494..8b805fa1d0 100644 --- a/main/main.h +++ b/main/main.h @@ -56,6 +56,7 @@ public: static bool iteration(); static void cleanup(); static void force_redraw(); + static bool is_project_manager(); }; #endif diff --git a/methods.py b/methods.py index f4d33fb6d8..6f03f79be3 100644 --- a/methods.py +++ b/methods.py @@ -19,637 +19,6 @@ def add_source_files(self, sources, filetype, lib_env=None, shared=False): sources.append(self.Object(f)) -def build_shader_header(target, source, env): - - for x in source: - print(x) - - name = str(x) - name = name[name.rfind("/") + 1:] - name = name[name.rfind("\\") + 1:] - name = name.replace(".", "_") - - fs = open(str(x), "r") - fd = open(str(x) + ".gen.h", "w") - fd.write("/* this file has been generated by SCons, do not edit! */\n") - fd.write("static const char *" + name + "=\n") - line = fs.readline() - while(line): - line = line.replace("\r", "") - line = line.replace("\n", "") - line = line.replace("\\", "\\\\") - line = line.replace("\"", "\\\"") - fd.write("\"" + line + "\\n\"\n") - line = fs.readline() - - fd.write(";\n") - - return 0 - - -def build_glsl_header(filename): - - fs = open(filename, "r") - line = fs.readline() - - vertex_lines = [] - fragment_lines = [] - uniforms = [] - attributes = [] - fbos = [] - conditionals = [] - texunits = [] - texunit_names = [] - ubos = [] - ubo_names = [] - - reading = "" - line_offset = 0 - vertex_offset = 0 - fragment_offset = 0 - - while(line): - - if (line.find("[vertex]") != -1): - reading = "vertex" - line = fs.readline() - line_offset += 1 - vertex_offset = line_offset - continue - - if (line.find("[fragment]") != -1): - reading = "fragment" - line = fs.readline() - line_offset += 1 - fragment_offset = line_offset - continue - - if (line.find("#ifdef ") != -1): - ifdefline = line.replace("#ifdef ", "").strip() - if (not ifdefline in conditionals): - conditionals += [ifdefline] - - if (line.find("#elif defined(") != -1): - ifdefline = line.replace("#elif defined(", "").strip() - ifdefline = ifdefline.replace(")", "").strip() - if (not ifdefline in conditionals): - conditionals += [ifdefline] - - import re - if re.search(r"^\s*uniform", line): - - if (line.lower().find("texunit:") != -1): - # texture unit - texunit = str(int(line[line.find(":") + 1:].strip())) - uline = line[:line.lower().find("//")] - uline = uline.replace("uniform", "") - uline = uline.replace(";", "") - lines = uline.split(",") - for x in lines: - - x = x.strip() - x = x[x.rfind(" ") + 1:] - if (x.find("[") != -1): - # unfiorm array - x = x[:x.find("[")] - - if (not x in texunit_names): - texunits += [(x, texunit)] - texunit_names += [x] - - elif (line.lower().find("ubo:") != -1): - # ubo - uboidx = str(int(line[line.find(":") + 1:].strip())) - uline = line[:line.lower().find("//")] - uline = uline[uline.find("uniform") + len("uniform"):] - uline = uline.replace(";", "") - uline = uline.replace("{", "").strip() - lines = uline.split(",") - for x in lines: - - x = x.strip() - x = x[x.rfind(" ") + 1:] - if (x.find("[") != -1): - # unfiorm array - x = x[:x.find("[")] - - if (not x in ubo_names): - ubos += [(x, uboidx)] - ubo_names += [x] - - else: - uline = line.replace("uniform", "") - uline = uline.replace(";", "") - lines = uline.split(",") - for x in lines: - - x = x.strip() - x = x[x.rfind(" ") + 1:] - if (x.find("[") != -1): - # unfiorm array - x = x[:x.find("[")] - - if (not x in uniforms): - uniforms += [x] - - if ((line.strip().find("in ") == 0 or line.strip().find("attribute ") == 0) and line.find("attrib:") != -1): - uline = line.replace("in ", "") - uline = uline.replace("attribute ", "") - uline = uline.replace(";", "") - uline = uline[uline.find(" "):].strip() - - if (uline.find("//") != -1): - name, bind = uline.split("//") - if (bind.find("attrib:") != -1): - name = name.strip() - bind = bind.replace("attrib:", "").strip() - attributes += [(name, bind)] - - if (line.strip().find("out ") == 0): - uline = line.replace("out", "").strip() - uline = uline.replace(";", "") - uline = uline[uline.find(" "):].strip() - - if (uline.find("//") != -1): - name, bind = uline.split("//") - if (bind.find("drawbuffer:") != -1): - name = name.strip() - bind = bind.replace("drawbuffer:", "").strip() - fbos += [(name, bind)] - - line = line.replace("\r", "") - line = line.replace("\n", "") - line = line.replace("\\", "\\\\") - line = line.replace("\"", "\\\"") - # line=line+"\\n\\" no need to anymore - - if (reading == "vertex"): - vertex_lines += [line] - if (reading == "fragment"): - fragment_lines += [line] - - line = fs.readline() - line_offset += 1 - - fs.close() - - out_file = filename + ".gen.h" - fd = open(out_file, "w") - - fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n") - - out_file_base = out_file - out_file_base = out_file_base[out_file_base.rfind("/") + 1:] - out_file_base = out_file_base[out_file_base.rfind("\\") + 1:] -# print("out file "+out_file+" base " +out_file_base) - out_file_ifdef = out_file_base.replace(".", "_").upper() - fd.write("#ifndef " + out_file_ifdef + "\n") - fd.write("#define " + out_file_ifdef + "\n") - - out_file_class = out_file_base.replace(".glsl.h", "").title().replace("_", "").replace(".", "") + "ShaderGL" - fd.write("\n\n") - fd.write("#include \"drivers/opengl/shader_gl.h\"\n\n\n") - fd.write("class " + out_file_class + " : public ShaderGL {\n\n") - fd.write("\t virtual String get_shader_name() const { return \"" + out_file_class + "\"; }\n") - fd.write("public:\n\n") - - if (len(conditionals)): - fd.write("\tenum Conditionals {\n") - for x in conditionals: - fd.write("\t\t" + x + ",\n") - fd.write("\t};\n\n") - if (len(uniforms)): - fd.write("\tenum Uniforms {\n") - for x in uniforms: - fd.write("\t\t" + x.upper() + ",\n") - fd.write("\t};\n\n") - - fd.write("\t_FORCE_INLINE_ int get_uniform(Uniforms p_uniform) const { return _get_uniform(p_uniform); }\n\n") - if (len(conditionals)): - - fd.write("\t_FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); }\n\n") - fd.write("\t#define _FU if (get_uniform(p_uniform)<0) return; ERR_FAIL_COND( get_active()!=this );\n\n ") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, bool p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value?1:0); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n") - #fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint64_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n"); - #fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int64_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n"); - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, unsigned long p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, long p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU GLfloat col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; glUniform4fv(get_uniform(p_uniform),1,col); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU GLfloat vec2[2]={p_vec2.x,p_vec2.y}; glUniform2fv(get_uniform(p_uniform),1,vec2); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU GLfloat vec3[3]={p_vec3.x,p_vec3.y,p_vec3.z}; glUniform3fv(get_uniform(p_uniform),1,vec3); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Plane& p_plane) { _FU GLfloat plane[4]={p_plane.normal.x,p_plane.normal.y,p_plane.normal.z,p_plane.d}; glUniform4fv(get_uniform(p_uniform),1,plane); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU glUniform2f(get_uniform(p_uniform),p_a,p_b); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU glUniform3f(get_uniform(p_uniform),p_a,p_b,p_c); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU glUniform4f(get_uniform(p_uniform),p_a,p_b,p_c,p_d); }\n\n") - - fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) { _FU - - const Transform &tr = p_transform; - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.basis.elements[0][0], - tr.basis.elements[1][0], - tr.basis.elements[2][0], - 0, - tr.basis.elements[0][1], - tr.basis.elements[1][1], - tr.basis.elements[2][1], - 0, - tr.basis.elements[0][2], - tr.basis.elements[1][2], - tr.basis.elements[2][2], - 0, - tr.origin.x, - tr.origin.y, - tr.origin.z, - 1 - }; - - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - - - } - - """) - - fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform2D& p_transform) { _FU - - const Transform2D &tr = p_transform; - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.elements[0][0], - tr.elements[0][1], - 0, - 0, - tr.elements[1][0], - tr.elements[1][1], - 0, - 0, - 0, - 0, - 1, - 0, - tr.elements[2][0], - tr.elements[2][1], - 0, - 1 - }; - - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - - - } - - """) - - fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU - - GLfloat matrix[16]; - - for (int i=0;i<4;i++) { - for (int j=0;j<4;j++) { - - matrix[i*4+j]=p_matrix.matrix[i][j]; - } - } - - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - }; """) - - fd.write("\n\n#undef _FU\n\n\n") - - fd.write("\tvirtual void init() {\n\n") - if (len(conditionals)): - - fd.write("\t\tstatic const char* _conditional_strings[]={\n") - if (len(conditionals)): - for x in conditionals: - fd.write("\t\t\t\"#define " + x + "\\n\",\n") - fd.write("\t\t};\n\n") - else: - fd.write("\t\tstatic const char **_conditional_strings=NULL;\n") - - if (len(uniforms)): - - fd.write("\t\tstatic const char* _uniform_strings[]={\n") - if (len(uniforms)): - for x in uniforms: - fd.write("\t\t\t\"" + x + "\",\n") - fd.write("\t\t};\n\n") - else: - fd.write("\t\tstatic const char **_uniform_strings=NULL;\n") - - if (len(attributes)): - - fd.write("\t\tstatic AttributePair _attribute_pairs[]={\n") - for x in attributes: - fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n") - fd.write("\t\t};\n\n") - else: - fd.write("\t\tstatic AttributePair *_attribute_pairs=NULL;\n") - - if (len(fbos)): - fd.write("\t\tstatic FBOPair _fbo_pairs[]={\n") - for x in fbos: - fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n") - fd.write("\t\t};\n\n") - else: - fd.write("\t\tstatic FBOPair *_fbo_pairs=NULL;\n") - - if (len(ubos)): - fd.write("\t\tstatic UBOPair _ubo_pairs[]={\n") - for x in ubos: - fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n") - fd.write("\t\t};\n\n") - else: - fd.write("\t\tstatic UBOPair *_ubo_pairs=NULL;\n") - - if (len(texunits)): - fd.write("\t\tstatic TexUnitPair _texunit_pairs[]={\n") - for x in texunits: - fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n") - fd.write("\t\t};\n\n") - else: - fd.write("\t\tstatic TexUnitPair *_texunit_pairs=NULL;\n") - - fd.write("\t\tstatic const char* _vertex_code=\"\\\n") - for x in vertex_lines: - fd.write("\t\t\t" + x + "\n") - fd.write("\t\t\";\n\n") - - fd.write("\t\tstatic const int _vertex_code_start=" + str(vertex_offset) + ";\n") - - fd.write("\t\tstatic const char* _fragment_code=\"\\\n") - for x in fragment_lines: - fd.write("\t\t\t" + x + "\n") - fd.write("\t\t\";\n\n") - - fd.write("\t\tstatic const int _fragment_code_start=" + str(fragment_offset) + ";\n") - - fd.write("\t\tsetup(_conditional_strings," + str(len(conditionals)) + ",_uniform_strings," + str(len(uniforms)) + ",_attribute_pairs," + str(len(attributes)) + ",_fbo_pairs," + str(len(fbos)) + ",_ubo_pairs," + str(len(ubos)) + ",_texunit_pairs," + str(len(texunits)) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") - fd.write("\t};\n\n") - - fd.write("};\n\n") - fd.write("#endif\n\n") - fd.close() - - -def build_glsl_headers(target, source, env): - - for x in source: - - build_glsl_header(str(x)) - - return 0 - - -def build_hlsl_dx9_header(filename): - - fs = open(filename, "r") - line = fs.readline() - - vertex_lines = [] - fragment_lines = [] - uniforms = [] - fragment_uniforms = [] - attributes = [] - fbos = [] - conditionals = [] - - reading = "" - line_offset = 0 - vertex_offset = 0 - fragment_offset = 0 - - while(line): - - if (line.find("[vertex]") != -1): - reading = "vertex" - line = fs.readline() - line_offset += 1 - vertex_offset = line_offset - continue - - if (line.find("[fragment]") != -1): - reading = "fragment" - line = fs.readline() - line_offset += 1 - fragment_offset = line_offset - continue - - if (line.find("#ifdef ") != -1): - ifdefline = line.replace("#ifdef ", "").strip() - if (not ifdefline in conditionals): - conditionals += [ifdefline] - - if (line.find("#elif defined(") != -1): - ifdefline = line.replace("#elif defined(", "").strip() - ifdefline = ifdefline.replace(")", "").strip() - if (not ifdefline in conditionals): - conditionals += [ifdefline] - if (line.find("uniform") != -1): - uline = line.replace("uniform", "") - uline = uline.replace(";", "") - lines = uline.split(",") - for x in lines: - - x = x.strip() - x = x[x.rfind(" ") + 1:] - if (x.find("[") != -1): - # unfiorm array - x = x[:x.find("[")] - - if (not x in uniforms): - uniforms += [x] - fragment_uniforms += [reading == "fragment"] - line = line.replace("\r", "") - line = line.replace("\n", "") - line = line.replace("\\", "\\\\") - line = line.replace("\"", "\\\"") - line = line + "\\n\\" - - if (reading == "vertex"): - vertex_lines += [line] - if (reading == "fragment"): - fragment_lines += [line] - - line = fs.readline() - line_offset += 1 - - fs.close() - - out_file = filename + ".gen.h" - fd = open(out_file, "w") - - fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n") - - out_file_base = out_file - out_file_base = out_file_base[out_file_base.rfind("/") + 1:] - out_file_base = out_file_base[out_file_base.rfind("\\") + 1:] -# print("out file "+out_file+" base " +out_file_base) - out_file_ifdef = out_file_base.replace(".", "_").upper() - fd.write("#ifndef " + out_file_ifdef + "\n") - fd.write("#define " + out_file_ifdef + "\n") - - out_file_class = out_file_base.replace(".hlsl.h", "").title().replace("_", "").replace(".", "") + "ShaderDX9" - fd.write("\n\n") - fd.write("#include \"drivers/directx9/shader_dx9.h\"\n\n\n") - fd.write("class " + out_file_class + " : public ShaderDX9 {\n\n") - fd.write("\t virtual String get_shader_name() const { return \"" + out_file_class + "\"; }\n") - fd.write("public:\n\n") - - if (len(conditionals)): - fd.write("\tenum Conditionals {\n") - for x in conditionals: - fd.write("\t\t" + x + ",\n") - fd.write("\t};\n\n") - if (len(uniforms)): - fd.write("\tenum Uniforms {\n") - for x in uniforms: - fd.write("\t\t" + x.upper() + ",\n") - fd.write("\t};\n\n") - - if (len(conditionals)): - fd.write("\t_FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); }\n\n") - - fd.write("\t#define _FU if (!_uniform_valid(p_uniform)) return; ERR_FAIL_COND( get_active()!=this );\n\n ") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, bool p_value) { _FU set_uniformb(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU set_uniformf(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU set_uniformf(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n") - #fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint64_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n"); - #fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int64_t p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n"); - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, unsigned long p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, long p_value) { _FU set_uniformi(p_uniform,p_value); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU float col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; set_uniformfv(p_uniform,col); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU float vec2[4]={p_vec2.x,p_vec2.y,0,0}; set_uniformfv(p_uniform,vec2); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU float vec3[4]={p_vec3.x,p_vec3.y,p_vec3.z,0}; set_uniformfv(p_uniform,vec3); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU float vec2[4]={p_a,p_b,0,0}; set_uniformfv(p_uniform,vec2); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU float vec3[4]={p_a,p_b,p_c,0}; set_uniformfv(p_uniform,vec3); }\n\n") - fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU float vec4[4]={p_a,p_b,p_c,p_d}; set_uniformfv(p_uniform,vec4); }\n\n") - - fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) { _FU - - const Transform &tr = p_transform; - - float matrix[16]={ /* build a 16x16 matrix */ - tr.basis.elements[0][0], - tr.basis.elements[0][1], - tr.basis.elements[0][2], - tr.origin.x, - tr.basis.elements[1][0], - tr.basis.elements[1][1], - tr.basis.elements[1][2], - tr.origin.y, - tr.basis.elements[2][0], - tr.basis.elements[2][1], - tr.basis.elements[2][2], - tr.origin.z, - 0, - 0, - 0, - 1 - }; - - set_uniformfv(p_uniform,&matrix[0],4); - - } - - """) - - fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU - - float matrix[16]; - - for (int i=0;i<4;i++) { - for (int j=0;j<4;j++) { - - matrix[i*4+j]=p_matrix.matrix[j][i]; - } - } - - set_uniformfv(p_uniform,&matrix[0],4); - }; """) - - fd.write("\n\n#undef _FU\n\n\n") - - fd.write("\tvirtual void init(IDirect3DDevice9 *p_device,ShaderSupport p_version) {\n\n") - if (len(conditionals)): - - fd.write("\t\tstatic const char* _conditional_strings[]={\n") - if (len(conditionals)): - for x in conditionals: - fd.write("\t\t\t\"" + x + "\",\n") - fd.write("\t\t};\n\n") - else: - fd.write("\t\tstatic const char **_conditional_strings=NULL;\n") - - if (len(uniforms)): - - fd.write("\t\tstatic const char* _uniform_strings[]={\n") - if (len(uniforms)): - for x in uniforms: - fd.write("\t\t\t\"" + x + "\",\n") - fd.write("\t\t};\n\n") - - fd.write("\t\tstatic const bool _fragment_uniforms[]={\n") - - if (len(uniforms)): - for x in fragment_uniforms: - if (x): - fd.write("\t\t\ttrue,\n") - else: - fd.write("\t\t\tfalse,\n") - fd.write("\t\t};\n\n") - else: - fd.write("\t\tstatic const char **_uniform_strings=NULL;\n") - fd.write("\t\tstatic const bool *_fragment_uniforms=NULL;\n") - - fd.write("\t\tstatic const char* _vertex_code=\"\\\n") - for x in vertex_lines: - fd.write("\t\t\t" + x + "\n") - fd.write("\t\t\";\n\n") - - fd.write("\t\tstatic const int _vertex_code_start=" + str(vertex_offset) + ";\n") - - fd.write("\t\tstatic const char* _fragment_code=\"\\\n") - for x in fragment_lines: - fd.write("\t\t\t" + x + "\n") - fd.write("\t\t\";\n\n") - - fd.write("\t\tstatic const int _fragment_code_start=" + str(fragment_offset) + ";\n") - - fd.write("\t\tsetup(p_device,p_version,_conditional_strings," + str(len(conditionals)) + ",_uniform_strings," + str(len(uniforms)) + ",_fragment_uniforms,_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") - fd.write("\t};\n\n") - - fd.write("};\n\n") - fd.write("#endif\n\n") - fd.close() - - -def build_hlsl_dx9_headers(target, source, env): - - for x in source: - - build_hlsl_dx9_header(str(x)) - - return 0 - class LegacyGLHeaderStruct: @@ -840,7 +209,7 @@ def include_file_in_legacygl_header(filename, header_data, depth): return header_data -def build_legacygl_header(filename, include, class_suffix, output_attribs): +def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2=False): header_data = LegacyGLHeaderStruct() include_file_in_legacygl_header(filename, header_data, 0) @@ -928,14 +297,14 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs): }; - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); + glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); } """) - fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform2D& p_transform) { _FU + fd.write("""_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform2D& p_transform) { _FU const Transform2D &tr = p_transform; @@ -959,14 +328,14 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs): }; - glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); + glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); } """) - fd.write("""\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU + fd.write("""_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU GLfloat matrix[16]; @@ -978,7 +347,7 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs): } glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix); - }; """) + } """) fd.write("\n\n#undef _FU\n\n\n") @@ -1061,7 +430,7 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs): feedback_count = 0 - if (len(header_data.feedbacks)): + if (not gles2 and len(header_data.feedbacks)): fd.write("\t\tstatic const Feedback _feedbacks[]={\n") for x in header_data.feedbacks: @@ -1076,7 +445,10 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs): fd.write("\t\t};\n\n") else: - fd.write("\t\tstatic const Feedback* _feedbacks=NULL;\n") + if gles2: + pass + else: + fd.write("\t\tstatic const Feedback* _feedbacks=NULL;\n") if (len(header_data.texunits)): fd.write("\t\tstatic TexUnitPair _texunit_pairs[]={\n") @@ -1086,13 +458,16 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs): else: fd.write("\t\tstatic TexUnitPair *_texunit_pairs=NULL;\n") - if (len(header_data.ubos)): + if (not gles2 and len(header_data.ubos)): fd.write("\t\tstatic UBOPair _ubo_pairs[]={\n") for x in header_data.ubos: fd.write("\t\t\t{\"" + x[0] + "\"," + x[1] + "},\n") fd.write("\t\t};\n\n") else: - fd.write("\t\tstatic UBOPair *_ubo_pairs=NULL;\n") + if gles2: + pass + else: + fd.write("\t\tstatic UBOPair *_ubo_pairs=NULL;\n") fd.write("\t\tstatic const char _vertex_code[]={\n") for x in header_data.vertex_lines: @@ -1115,11 +490,17 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs): fd.write("\t\tstatic const int _fragment_code_start=" + str(header_data.fragment_offset) + ";\n") if output_attribs: - fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_attribute_pairs," + str(len(header_data.attributes)) + ", _texunit_pairs," + str(len(header_data.texunits)) + ",_ubo_pairs," + str(len(header_data.ubos)) + ",_feedbacks," + str(feedback_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") + if gles2: + fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_attribute_pairs," + str(len(header_data.attributes)) + ", _texunit_pairs," + str(len(header_data.texunits)) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") + else: + fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_attribute_pairs," + str(len(header_data.attributes)) + ", _texunit_pairs," + str(len(header_data.texunits)) + ",_ubo_pairs," + str(len(header_data.ubos)) + ",_feedbacks," + str(feedback_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") else: - fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_texunit_pairs," + str(len(header_data.texunits)) + ",_enums," + str(len(header_data.enums)) + ",_enum_values," + str(enum_value_count) + ",_ubo_pairs," + str(len(header_data.ubos)) + ",_feedbacks," + str(feedback_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") + if gles2: + fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_texunit_pairs," + str(len(header_data.texunits)) + ",_enums," + str(len(header_data.enums)) + ",_enum_values," + str(enum_value_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") + else: + fd.write("\t\tsetup(_conditional_strings," + str(len(header_data.conditionals)) + ",_uniform_strings," + str(len(header_data.uniforms)) + ",_texunit_pairs," + str(len(header_data.texunits)) + ",_enums," + str(len(header_data.enums)) + ",_enum_values," + str(enum_value_count) + ",_ubo_pairs," + str(len(header_data.ubos)) + ",_feedbacks," + str(feedback_count) + ",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n") - fd.write("\t};\n\n") + fd.write("\t}\n\n") if (len(enum_constants)): @@ -1134,20 +515,16 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs): fd.close() -def build_legacygl_headers(target, source, env): +def build_gles3_headers(target, source, env): for x in source: - - build_legacygl_header(str(x), include="drivers/legacygl/shader_lgl.h", class_suffix="LGL", output_attribs=False) - - return 0 + build_legacygl_header(str(x), include="drivers/gles3/shader_gles3.h", class_suffix="GLES3", output_attribs=True) -def build_gles3_headers(target, source, env): +def build_gles2_headers(target, source, env): for x in source: - build_legacygl_header(str(x), include="drivers/gles3/shader_gles3.h", class_suffix="GLES3", output_attribs=True) - + build_legacygl_header(str(x), include="drivers/gles2/shader_gles2.h", class_suffix="GLES2", output_attribs=True, gles2=True) def add_module_version_string(self,s): self.module_version_string += "." + s @@ -1220,43 +597,7 @@ def parse_cg_file(fname, uniforms, sizes, conditionals): line = fs.readline() - -def build_cg_shader(sname): - - vp_uniforms = [] - vp_uniform_sizes = [] - vp_conditionals = [] - - parse_cg_file("vp_" + sname + ".cg", vp_uniforms, vp_uniform_sizes, vp_conditionals) - - fp_uniforms = [] - fp_uniform_sizes = [] - fp_conditionals = [] - - parse_cg_file("fp_" + sname + ".cg", fp_uniforms, fp_uniform_sizes, fp_conditionals) - - fd = open("shader_" + sname + ".cg.gen.h", "w") - - fd.write('\n#include "shader_cell.h"\n') - fd.write("\nclass Shader_" + sname + " : public ShaderCell {\n") - fd.write("\n\tstatic struct VertexUniforms[] = {\n") - - offset = 0 - for i in range(0, len(vp_uniforms)): - - fd.write('\t\t{ "%s", %d, %d },\n' % (vp_uniforms[i], offset, vp_uniform_sizes[i])) - offset = offset + vp_uniform_sizes[i] - fd.write("\t};\n\n") - - fd.write("public:\n\n") - - fd.write("\tenum {\n") - - for i in range(0, len(vp_uniforms)): - - fd.write('\t\tVP_%s,\n' % vp_uniforms[i].upper()) - - fd.write("\t};\n") + fs.close() import glob @@ -1306,8 +647,8 @@ void unregister_module_types() { } """ - f = open("modules/register_module_types.gen.cpp", "w") - f.write(modules_cpp) + with open("modules/register_module_types.gen.cpp", "w") as f: + f.write(modules_cpp) return module_list @@ -1406,18 +747,18 @@ def android_add_default_config(self, config): def android_add_to_manifest(self, file): base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file - f = open(base_path, "r") - self.android_manifest_chunk += f.read() + with open(base_path, "r") as f: + self.android_manifest_chunk += f.read() def android_add_to_permissions(self, file): base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file - f = open(base_path, "r") - self.android_permission_chunk += f.read() + with open(base_path, "r") as f: + self.android_permission_chunk += f.read() def android_add_to_attributes(self, file): base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file - f = open(base_path, "r") - self.android_appattributes_chunk += f.read() + with open(base_path, "r") as f: + self.android_appattributes_chunk += f.read() def disable_module(self): self.disabled_modules.append(self.current_module) @@ -1432,7 +773,7 @@ def use_windows_spawn_fix(self, platform=None): # that makes object files with same names to be overwritten so the last wins and # the library looses symbols defined by overwritten objects. # By enabling quick append instead of the default mode (replacing), libraries will - # got built correctly regardless the invokation strategy. + # got built correctly regardless the invocation strategy. # Furthermore, since SCons will rebuild the library from scratch when an object file # changes, no multiple versions of the same object file will be present. self.Replace(ARFLAGS='q') @@ -1548,9 +889,11 @@ def save_active_platforms(apnames, ap): str += "};\n" + pngf.close() + wf = x + "/" + name + ".gen.h" - pngw = open(wf, "w") - pngw.write(str) + with open(wf, "w") as pngw: + pngw.write(str) def no_verbose(sys, env): @@ -1607,7 +950,7 @@ def detect_visual_c_compiler_version(tools_env): # There is no flag to give to visual c compilers to set the architecture, ie scons bits argument (32,64,ARM etc) # There are many different cl.exe files that are run, and each one compiles & links to a different architecture # As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program() - # is to check the PATH variable and figure out which one will be called first. Code bellow does that and returns: + # is to check the PATH variable and figure out which one will be called first. Code below does that and returns: # the following string values: # "" Compiler not detected @@ -1627,7 +970,7 @@ def detect_visual_c_compiler_version(tools_env): if 'VCINSTALLDIR' in tools_env: # print("Checking VCINSTALLDIR") - # find() works with -1 so big ifs bellow are needed... the simplest solution, in fact + # find() works with -1 so big ifs below are needed... the simplest solution, in fact # First test if amd64 and amd64_x86 compilers are present in the path vc_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"] + "BIN\\amd64;") if(vc_amd64_compiler_detection_index > -1): @@ -1710,8 +1053,8 @@ def generate_cpp_hint_file(filename): pass else: try: - fd = open(filename, "w") - fd.write("#define GDCLASS(m_class, m_inherits)\n") + with open(filename, "w") as fd: + fd.write("#define GDCLASS(m_class, m_inherits)\n") except IOError: print("Could not write cpp.hint file.") diff --git a/misc/dist/html/default.html b/misc/dist/html/default.html index a1a4e89d02..4e3515a7b6 100644 --- a/misc/dist/html/default.html +++ b/misc/dist/html/default.html @@ -244,9 +244,6 @@ $GODOT_HEAD_INCLUDE var statusMode = 'hidden'; var indeterminiateStatusAnimationId = 0; - setStatusMode('indeterminate'); - engine.setCanvas(canvas); - function setStatusMode(mode) { if (statusMode === mode || !initializing) @@ -367,18 +364,27 @@ $GODOT_HEAD_INCLUDE }); } - engine.startGame(BASENAME + '.pck').then(() => { - setStatusMode('hidden'); - initializing = false; - }, err => { + function displayFailureNotice(err) { + var msg = err.message || err; if (DEBUG_ENABLED) { - printError(err.message); - console.warn(err); + printError(msg); } - setStatusNotice(err.message); + console.error(msg); + setStatusNotice(msg); setStatusMode('notice'); initializing = false; - }); + }; + + if (!Engine.isWebGLAvailable()) { + displayFailureNotice("WebGL not available"); + } else { + setStatusMode('indeterminate'); + engine.setCanvas(canvas); + engine.startGame(BASENAME + '.pck').then(() => { + setStatusMode('hidden'); + initializing = false; + }, displayFailureNotice); + } })(); //]]></script> </body> diff --git a/misc/dist/linux/godot.6 b/misc/dist/linux/godot.6 index 22836e03ed..86abdf6ef2 100644 --- a/misc/dist/linux/godot.6 +++ b/misc/dist/linux/godot.6 @@ -1,4 +1,4 @@ -.TH GODOT "6" "January 2018" "godot 3.0" "Games" +.TH GODOT "6" "February 2018" "godot 3.1" "Games" .SH NAME godot \- multi\-platform 2D and 3D game engine with a feature\-rich editor .SH SYNOPSIS @@ -31,6 +31,9 @@ Start the editor instead of running the scene. \fB\-p\fR, \fB\-\-project\-manager\fR Start the project manager, even if a project is auto\-detected. .TP +\fB\-q\fR, \fB\-\-quit\fR +Quit after the first iteration. +.TP \fB\-l\fR, \fB\-\-language\fR <locale> Use a specific locale (<locale> being a two\-letter code). .TP @@ -68,6 +71,9 @@ Request a maximized window. \fB\-w\fR, \fB\-\-windowed\fR Request windowed mode. .TP +\fB\-t\fR, \fB\-\-always\-on\-top\fR +Request an always\-on\-top window. +.TP \fB\-\-resolution\fR <W>x<H> Request window resolution. .TP @@ -113,6 +119,9 @@ Disable crash handler when supported by the platform code. .TP \fB\-\-fixed\-fps\fR <fps> Force a fixed number of frames per second. This setting disables real\-time synchronization. +.TP +\fB\-\-print\-fps\fR +Print the frames per second to the stdout. .SS "Standalone tools:" .TP \fB\-s\fR, \fB\-\-script\fR <script> @@ -130,6 +139,9 @@ Dump the engine API reference to the given <path> in XML format, merging if exis \fB\-\-no\-docbase\fR Disallow dumping the base types (used with \fB\-\-doctool\fR). .TP +\fB\-\-build\-solutions\fR +Build the scripting solutions (e.g. for C# projects). +.TP \fB\-\-gdnative\-generate\-json\-api\fR Generate JSON dump of the Godot API for GDNative bindings. .TP diff --git a/misc/dist/linux/godot.appdata.xml b/misc/dist/linux/godot.appdata.xml index 907fe1f3be..a381556025 100644 --- a/misc/dist/linux/godot.appdata.xml +++ b/misc/dist/linux/godot.appdata.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright 2017 Rémi Verschelde <akien@godotengine.org> --> +<!-- Copyright 2017-2018 Rémi Verschelde <akien@godotengine.org> --> <component type="desktop"> <id>godot.desktop</id> <metadata_license>CC0-1.0</metadata_license> diff --git a/misc/dist/linux/godot.desktop b/misc/dist/linux/godot.desktop index 545c491256..974352b117 100644 --- a/misc/dist/linux/godot.desktop +++ b/misc/dist/linux/godot.desktop @@ -2,7 +2,7 @@ Name=Godot Engine GenericName=Libre game engine Comment=Multi-platform 2D and 3D game engine with a feature rich editor -Exec=godot -pm +Exec=godot -p Icon=godot Terminal=false Type=Application diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format index 8ef4e27748..016a43038b 100755 --- a/misc/hooks/pre-commit-clang-format +++ b/misc/hooks/pre-commit-clang-format @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # git pre-commit hook that runs a clang-format stylecheck. # Features: diff --git a/misc/scripts/fix_headers.py b/misc/scripts/fix_headers.py index 809820c20f..48b9628b1f 100644 --- a/misc/scripts/fix_headers.py +++ b/misc/scripts/fix_headers.py @@ -92,9 +92,11 @@ while (fname != ""): fileread.close() # Write - fileread = open(fname.strip(), "wb") - fileread.write(text) - fileread.close() + filewrite = open(fname.strip(), "wb") + filewrite.write(text) + filewrite.close() # Next file fname = files.readline() + +files.close()
\ No newline at end of file diff --git a/misc/scripts/make_glwrapper.py b/misc/scripts/make_glwrapper.py index 5694d2327e..15b66a950b 100644 --- a/misc/scripts/make_glwrapper.py +++ b/misc/scripts/make_glwrapper.py @@ -16,9 +16,7 @@ READ_CONSTANTS = 2 read_what = READ_TYPES -for x in (range(len(sys.argv) - 1)): - f = open(sys.argv[x + 1], "r") - +def read_file(f): while(True): line = f.readline() @@ -86,6 +84,9 @@ for x in (range(len(sys.argv) - 1)): functions.append(funcdata) print(funcdata) +for path in sys.argv[1:]: + with open(path, "r") as f: + read_file(f) # print(types) # print(constants) @@ -156,6 +157,7 @@ f.write("void glWrapperInit( GLWrapperFuncPtr (*wrapperFunc)(const char*) );\n") f.write("#ifdef __cplusplus\n}\n#endif\n") f.write("#endif\n\n") +f.close() f = open("glwrapper.c", "w") @@ -176,3 +178,4 @@ for x in functions: f.write("\n\n") f.write("}\n") f.write("\n\n") +f.close() diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp index 4164450cd2..8707096038 100644 --- a/modules/bullet/btRayShape.cpp +++ b/modules/bullet/btRayShape.cpp @@ -54,6 +54,11 @@ void btRayShape::setLength(btScalar p_length) { reload_cache(); } +void btRayShape::setSlipsOnSlope(bool p_slipsOnSlope) { + + slipsOnSlope = p_slipsOnSlope; +} + btVector3 btRayShape::localGetSupportingVertex(const btVector3 &vec) const { return localGetSupportingVertexWithoutMargin(vec) + (m_shapeAxis * m_collisionMargin); } diff --git a/modules/bullet/btRayShape.h b/modules/bullet/btRayShape.h index 99a9412dbe..a44c30db4b 100644 --- a/modules/bullet/btRayShape.h +++ b/modules/bullet/btRayShape.h @@ -44,6 +44,7 @@ ATTRIBUTE_ALIGNED16(class) btRayShape : public btConvexInternalShape { btScalar m_length; + bool slipsOnSlope; /// The default axis is the z btVector3 m_shapeAxis; @@ -59,6 +60,9 @@ public: void setLength(btScalar p_length); btScalar getLength() const { return m_length; } + void setSlipsOnSlope(bool p_slipOnSlope); + bool getSlipsOnSlope() const { return slipsOnSlope; } + const btTransform &getSupportPoint() const { return m_cacheSupportPoint; } const btScalar &getScaledLength() const { return m_cacheScaledLength; } diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index b646fc164d..6246a295ec 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -89,7 +89,9 @@ BulletPhysicsServer::BulletPhysicsServer() : active(true), active_spaces_count(0) {} -BulletPhysicsServer::~BulletPhysicsServer() {} +BulletPhysicsServer::~BulletPhysicsServer() { + bulletdelete(emptyShape); +} RID BulletPhysicsServer::shape_create(ShapeType p_shape) { ShapeBullet *shape = NULL; @@ -619,11 +621,11 @@ uint32_t BulletPhysicsServer::body_get_collision_mask(RID p_body) const { } void BulletPhysicsServer::body_set_user_flags(RID p_body, uint32_t p_flags) { - WARN_PRINT("This function si not currently supported by bullet and Godot"); + // This function si not currently supported } uint32_t BulletPhysicsServer::body_get_user_flags(RID p_body) const { - WARN_PRINT("This function si not currently supported by bullet and Godot"); + // This function si not currently supported return 0; } @@ -783,22 +785,27 @@ int BulletPhysicsServer::body_get_max_contacts_reported(RID p_body) const { return body->get_max_collisions_detection(); } -void BulletPhysicsServer::body_set_contacts_reported_depth_threshold(RID p_body, float p_treshold) { - WARN_PRINT("Not supported by bullet and even Godot"); +void BulletPhysicsServer::body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) { + // Not supported by bullet and even Godot } float BulletPhysicsServer::body_get_contacts_reported_depth_threshold(RID p_body) const { - WARN_PRINT("Not supported by bullet and even Godot"); + // Not supported by bullet and even Godot return 0.; } void BulletPhysicsServer::body_set_omit_force_integration(RID p_body, bool p_omit) { - WARN_PRINT("Not supported by bullet"); + RigidBodyBullet *body = rigid_body_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_omit_forces_integration(p_omit); } bool BulletPhysicsServer::body_is_omitting_force_integration(RID p_body) const { - WARN_PRINT("Not supported by bullet"); - return false; + RigidBodyBullet *body = rigid_body_owner.get(p_body); + ERR_FAIL_COND_V(!body, false); + + return body->get_omit_forces_integration(); } void BulletPhysicsServer::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { @@ -825,12 +832,12 @@ PhysicsDirectBodyState *BulletPhysicsServer::body_get_direct_state(RID p_body) { return BulletPhysicsDirectBodyState::get_singleton(body); } -bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result) { +bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result) { RigidBodyBullet *body = rigid_body_owner.get(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); - return body->get_space()->test_body_motion(body, p_from, p_motion, r_result); + return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result); } RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) { @@ -979,11 +986,11 @@ PhysicsServer::JointType BulletPhysicsServer::joint_get_type(RID p_joint) const } void BulletPhysicsServer::joint_set_solver_priority(RID p_joint, int p_priority) { - //WARN_PRINTS("Joint priority not supported by bullet"); + // Joint priority not supported by bullet } int BulletPhysicsServer::joint_get_solver_priority(RID p_joint) const { - //WARN_PRINTS("Joint priority not supported by bullet"); + // Joint priority not supported by bullet return 0; } diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 764ec2387c..e931915bba 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -239,7 +239,7 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); virtual int body_get_max_contacts_reported(RID p_body) const; - virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_treshold); + virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold); virtual float body_get_contacts_reported_depth_threshold(RID p_body) const; virtual void body_set_omit_force_integration(RID p_body, bool p_omit); @@ -253,7 +253,7 @@ public: // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); - virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL); + virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL); /* SOFT BODY API */ diff --git a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml index c7909c7d72..a4dc61d0bc 100644 --- a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml +++ b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.0-stable"> +<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/bullet/doc_classes/BulletPhysicsServer.xml b/modules/bullet/doc_classes/BulletPhysicsServer.xml index a59abb0ebb..1486936cf4 100644 --- a/modules/bullet/doc_classes/BulletPhysicsServer.xml +++ b/modules/bullet/doc_classes/BulletPhysicsServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.0-stable"> +<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/bullet/godot_motion_state.h b/modules/bullet/godot_motion_state.h index fe5d8418b7..fa58e86589 100644 --- a/modules/bullet/godot_motion_state.h +++ b/modules/bullet/godot_motion_state.h @@ -87,7 +87,7 @@ public: public: /// Use this function to move kinematic body - /// -- or set initial transfom before body creation. + /// -- or set initial transform before body creation. void moveBody(const btTransform &newWorldTransform) { bodyKinematicWorldTransf = newWorldTransform; } diff --git a/modules/bullet/godot_ray_world_algorithm.cpp b/modules/bullet/godot_ray_world_algorithm.cpp index 4a511b39a7..53d0ab7e3c 100644 --- a/modules/bullet/godot_ray_world_algorithm.cpp +++ b/modules/bullet/godot_ray_world_algorithm.cpp @@ -100,14 +100,16 @@ void GodotRayWorldAlgorithm::processCollision(const btCollisionObjectWrapper *bo if (btResult.hasHit()) { - btVector3 ray_normal(ray_transform.getOrigin() - to.getOrigin()); - ray_normal.normalize(); btScalar depth(ray_shape->getScaledLength() * (btResult.m_closestHitFraction - 1)); if (depth >= -RAY_STABILITY_MARGIN) depth = 0; - resultOut->addContactPoint(ray_normal, btResult.m_hitPointWorld, depth); + if (ray_shape->getSlipsOnSlope()) + resultOut->addContactPoint(btResult.m_hitNormalWorld, btResult.m_hitPointWorld, depth); + else { + resultOut->addContactPoint((ray_transform.getOrigin() - to.getOrigin()).normalize(), btResult.m_hitPointWorld, depth); + } } } diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 8d4ca6d6a7..72c982bb0b 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -98,11 +98,16 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox if (gObj == m_self_object) { return false; } else { - if (m_ignore_areas && gObj->getType() == CollisionObjectBullet::TYPE_AREA) { + + // A kinematic body can't be stopped by a rigid body since the mass of kinematic body is infinite + if (m_infinite_inertia && !btObj->isStaticOrKinematicObject()) return false; - } else if (m_self_object->has_collision_exception(gObj)) { + + if (gObj->getType() == CollisionObjectBullet::TYPE_AREA) + return false; + + if (m_self_object->has_collision_exception(gObj)) return false; - } } return true; } else { @@ -252,18 +257,15 @@ btScalar GodotRestInfoContactResultCallback::addSingleResult(btManifoldPoint &cp void GodotDeepPenetrationContactResultCallback::addContactPoint(const btVector3 &normalOnBInWorld, const btVector3 &pointInWorldOnB, btScalar depth) { - if (depth < 0) { - // Has penetration - if (m_most_penetrated_distance > depth) { + // Has penetration + if (m_penetration_distance < ABS(depth)) { - bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); + bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); - m_most_penetrated_distance = depth; - m_pointCollisionObject = (isSwapped ? m_body0Wrap : m_body1Wrap)->getCollisionObject(); - m_other_compound_shape_index = isSwapped ? m_index1 : m_index0; - m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld; - m_pointWorld = isSwapped ? (pointInWorldOnB + normalOnBInWorld * depth) : pointInWorldOnB; - m_penetration_distance = depth; - } + m_penetration_distance = depth; + m_pointCollisionObject = (isSwapped ? m_body0Wrap : m_body1Wrap)->getCollisionObject(); + m_other_compound_shape_index = isSwapped ? m_index1 : m_index0; + m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld; + m_pointWorld = isSwapped ? (pointInWorldOnB + normalOnBInWorld * depth) : pointInWorldOnB; } } diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h index e1b0b1b421..60493d4788 100644 --- a/modules/bullet/godot_result_callbacks.h +++ b/modules/bullet/godot_result_callbacks.h @@ -93,12 +93,12 @@ public: struct GodotKinClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { public: const RigidBodyBullet *m_self_object; - const bool m_ignore_areas; + const bool m_infinite_inertia; - GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_ignore_areas) : + GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_infinite_inertia) : btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld), m_self_object(p_self_object), - m_ignore_areas(p_ignore_areas) {} + m_infinite_inertia(p_infinite_inertia) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; }; @@ -187,18 +187,15 @@ struct GodotDeepPenetrationContactResultCallback : public btManifoldResult { int m_other_compound_shape_index; const btCollisionObject *m_pointCollisionObject; - btScalar m_most_penetrated_distance; - GodotDeepPenetrationContactResultCallback(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap) : btManifoldResult(body0Wrap, body1Wrap), m_pointCollisionObject(NULL), m_penetration_distance(0), - m_other_compound_shape_index(0), - m_most_penetrated_distance(1e20) {} + m_other_compound_shape_index(0) {} void reset() { m_pointCollisionObject = NULL; - m_most_penetrated_distance = 1e20; + m_penetration_distance = 0; } bool hasHit() { diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index f96218ef46..2494063c22 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -114,10 +114,18 @@ Transform BulletPhysicsDirectBodyState::get_transform() const { return body->get_transform(); } +void BulletPhysicsDirectBodyState::add_central_force(const Vector3 &p_force) { + body->apply_central_force(p_force); +} + void BulletPhysicsDirectBodyState::add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->apply_force(p_force, p_pos); } +void BulletPhysicsDirectBodyState::add_torque(const Vector3 &p_torque) { + body->apply_torque(p_torque); +} + void BulletPhysicsDirectBodyState::apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { body->apply_impulse(p_pos, p_j); } @@ -247,6 +255,7 @@ RigidBodyBullet::RigidBodyBullet() : linearDamp(0), angularDamp(0), can_sleep(true), + omit_forces_integration(false), force_integration_callback(NULL), isTransformChanged(false), previousActiveState(true), @@ -326,6 +335,9 @@ void RigidBodyBullet::dispatch_callbacks() { /// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent if ((btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) { + if (omit_forces_integration) + btBody->clearForces(); + BulletPhysicsDirectBodyState *bodyDirect = BulletPhysicsDirectBodyState::get_singleton(this); Variant variantBodyDirect = bodyDirect; @@ -429,6 +441,10 @@ bool RigidBodyBullet::is_active() const { return btBody->isActive(); } +void RigidBodyBullet::set_omit_forces_integration(bool p_omit) { + omit_forces_integration = p_omit; +} + void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { switch (p_param) { case PhysicsServer::BODY_PARAM_BOUNCE: diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index c4a9676bdd..b9511243c7 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -110,7 +110,9 @@ public: virtual void set_transform(const Transform &p_transform); virtual Transform get_transform() const; + virtual void add_central_force(const Vector3 &p_force); virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos); + virtual void add_torque(const Vector3 &p_torque); virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j); virtual void apply_torque_impulse(const Vector3 &p_j); @@ -196,6 +198,7 @@ private: real_t linearDamp; real_t angularDamp; bool can_sleep; + bool omit_forces_integration; Vector<CollisionData> collisions; // these parameters are used to avoid vector resize @@ -252,6 +255,9 @@ public: void set_activation_state(bool p_active); bool is_active() const; + void set_omit_forces_integration(bool p_omit); + _FORCE_INLINE_ bool get_omit_forces_integration() const { return omit_forces_integration; } + void set_param(PhysicsServer::BodyParameter p_param, real_t); real_t get_param(PhysicsServer::BodyParameter p_param) const; diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index c6b9695d96..5d8d391bd9 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -135,8 +135,10 @@ btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(PoolVector<rea return bulletnew(btHeightfieldTerrainShape(p_width, p_depth, heightsPtr, ignoredHeightScale, -fieldHeight, fieldHeight, YAxis, PHY_FLOAT, flipQuadEdges)); } -btRayShape *ShapeBullet::create_shape_ray(real_t p_length) { - return bulletnew(btRayShape(p_length)); +btRayShape *ShapeBullet::create_shape_ray(real_t p_length, bool p_slips_on_slope) { + btRayShape *r(bulletnew(btRayShape(p_length))); + r->setSlipsOnSlope(p_slips_on_slope); + return r; } /* PLANE */ @@ -435,25 +437,33 @@ btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_impli /* Ray shape */ RayShapeBullet::RayShapeBullet() : ShapeBullet(), - length(1) {} + length(1), + slips_on_slope(false) {} void RayShapeBullet::set_data(const Variant &p_data) { - setup(p_data); + + Dictionary d = p_data; + setup(d["length"], d["slips_on_slope"]); } Variant RayShapeBullet::get_data() const { - return length; + + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + return d; } PhysicsServer::ShapeType RayShapeBullet::get_type() const { return PhysicsServer::SHAPE_RAY; } -void RayShapeBullet::setup(real_t p_length) { +void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) { length = p_length; + slips_on_slope = p_slips_on_slope; notifyShapeChanged(); } btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { - return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_margin)); + return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_margin, slips_on_slope)); } diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index e04a3c808a..2acba90e36 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -86,7 +86,7 @@ public: static class btConvexPointCloudShape *create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling = btVector3(1, 1, 1)); static class btScaledBvhTriangleMeshShape *create_shape_concave(btBvhTriangleMeshShape *p_mesh_shape, const btVector3 &p_local_scaling = btVector3(1, 1, 1)); static class btHeightfieldTerrainShape *create_shape_height_field(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size); - static class btRayShape *create_shape_ray(real_t p_length); + static class btRayShape *create_shape_ray(real_t p_length, bool p_slips_on_slope); }; class PlaneShapeBullet : public ShapeBullet { @@ -216,6 +216,7 @@ class RayShapeBullet : public ShapeBullet { public: real_t length; + bool slips_on_slope; RayShapeBullet(); @@ -225,6 +226,6 @@ public: virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); private: - void setup(real_t p_length); + void setup(real_t p_length, bool p_slips_on_slope); }; #endif diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 88d9c20eba..8c15758e0f 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -628,7 +628,7 @@ void SpaceBullet::destroy_world() { void SpaceBullet::check_ghost_overlaps() { - /// Algorith support variables + /// Algorithm support variables btConvexShape *other_body_shape; btConvexShape *area_shape; btGjkPairDetector::ClosestPointInput gjk_input; @@ -790,7 +790,7 @@ void SpaceBullet::update_gravity() { /// I'm leaving this here just for future tests. /// Debug motion and normal vector drawing #define debug_test_motion 0 -#define PERFORM_INITIAL_UNSTACK 0 + #define RECOVERING_MOVEMENT_SCALE 0.4 #define RECOVERING_MOVEMENT_CYCLES 4 @@ -804,8 +804,7 @@ static Ref<SpatialMaterial> red_mat; static Ref<SpatialMaterial> blue_mat; #endif -#define IGNORE_AREAS_TRUE true -bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, PhysicsServer::MotionResult *r_result) { +bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result) { #if debug_test_motion /// Yes I know this is not good, but I've used it as fast debugging hack. @@ -839,25 +838,14 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f } #endif - ///// Release all generated manifolds - //{ - // if(p_body->get_kinematic_utilities()){ - // for(int i= p_body->get_kinematic_utilities()->m_generatedManifold.size()-1; 0<=i; --i){ - // dispatcher->releaseManifold( p_body->get_kinematic_utilities()->m_generatedManifold[i] ); - // } - // p_body->get_kinematic_utilities()->m_generatedManifold.clear(); - // } - //} - btTransform body_safe_position; G_TO_B(p_from, body_safe_position); UNSCALE_BT_BASIS(body_safe_position); -#if PERFORM_INITIAL_UNSTACK btVector3 recover_initial_position(0, 0, 0); { /// Phase one - multi shapes depenetration using margin for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - if (!recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, recover_initial_position)) { + if (!recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, recover_initial_position)) { break; } } @@ -865,7 +853,6 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f // Add recover movement in order to make it safe body_safe_position.getOrigin() += recover_initial_position; } -#endif btVector3 motion; G_TO_B(p_motion, motion); @@ -900,11 +887,11 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f btTransform shape_world_to(shape_world_from); shape_world_to.getOrigin() += motion; - GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, IGNORE_AREAS_TRUE); + GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, p_infinite_inertia); btResult.m_collisionFilterGroup = p_body->get_collision_layer(); btResult.m_collisionFilterMask = p_body->get_collision_mask(); - dynamicsWorld->convexSweepTest(convex_shape_test, shape_world_from, shape_world_to, btResult, 0.002); + dynamicsWorld->convexSweepTest(convex_shape_test, shape_world_from, shape_world_to, btResult, dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration); if (btResult.hasHit()) { /// Since for each sweep test I fix the motion of new shapes in base the recover result, @@ -926,14 +913,11 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f real_t l_penetration_distance = 1e20; for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, delta_recover_movement, &r_recover_result); + l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, delta_recover_movement, &r_recover_result); if (r_result) { -#if PERFORM_INITIAL_UNSTACK B_TO_G(motion + delta_recover_movement + recover_initial_position, r_result->motion); -#else - B_TO_G(motion + delta_recover_movement, r_result->motion); -#endif + if (l_has_penetration) { has_penetration = true; if (l_penetration_distance <= r_recover_result.penetration_distance) { @@ -955,15 +939,6 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f r_result->collider_shape = r_recover_result.other_compound_shape_index; r_result->collision_local_shape = r_recover_result.local_shape_most_recovered; - //{ /// Add manifold point to manage collisions - // btPersistentManifold* manifold = dynamicsWorld->getDispatcher()->getNewManifold(p_body->getBtBody(), btRigid); - // btManifoldPoint manifoldPoint(result_callabck.m_pointWorld, result_callabck.m_pointWorld, result_callabck.m_pointNormalWorld, result_callabck.m_penetration_distance); - // manifoldPoint.m_index0 = r_result->collision_local_shape; - // manifoldPoint.m_index1 = r_result->collider_shape; - // manifold->addManifoldPoint(manifoldPoint); - // p_body->get_kinematic_utilities()->m_generatedManifold.push_back(manifold); - //} - #if debug_test_motion Vector3 sup_line2; B_TO_G(motion, sup_line2); @@ -1022,7 +997,7 @@ public: } }; -bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) { +bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) { RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask()); @@ -1053,7 +1028,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran for (int i = recover_broad_result.result_collision_objects.size() - 1; 0 <= i; --i) { btCollisionObject *otherObject = recover_broad_result.result_collision_objects[i]; - if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object())) + if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object()) || (p_infinite_inertia && !otherObject->isStaticOrKinematicObject())) continue; if (otherObject->getCollisionShape()->isCompound()) { @@ -1132,7 +1107,7 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC btCollisionObjectWrapper obA(NULL, p_shapeA, p_objectA, tA, -1, p_shapeId_A); btCollisionObjectWrapper obB(NULL, p_shapeB, p_objectB, p_transformB, -1, p_shapeId_B); - btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CLOSEST_POINT_ALGORITHMS); + btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CONTACT_POINT_ALGORITHMS); if (algorithm) { GodotDeepPenetrationContactResultCallback contactPointResult(&obA, &obB); //discrete collision detection query @@ -1142,7 +1117,7 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC dispatcher->freeCollisionAlgorithm(algorithm); if (contactPointResult.hasHit()) { - r_delta_recover_movement += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * -1 * p_recover_movement_scale); + r_delta_recover_movement += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * p_recover_movement_scale); if (r_recover_result) { if (contactPointResult.m_penetration_distance < r_recover_result->penetration_distance) { diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 2b97f0b274..a6c2786878 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -172,7 +172,7 @@ public: void update_gravity(); - bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, PhysicsServer::MotionResult *r_result); + bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result); private: void create_empty_world(bool p_create_soft_world); @@ -199,7 +199,7 @@ private: local_shape_most_recovered(0) {} }; - bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); + bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); /// This is an API that recover a kinematic object from penetration /// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, 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); diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index 23ee327cc5..7bee63019b 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -1,12 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.0-stable"> +<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1"> <brief_description> PacketPeer implementation using the ENet library. </brief_description> <description> - A connection (or a listening server) that should be passed to [method SceneTree.set_network_peer]. Socket events can be handled by connecting to [SceneTree] signals. + A PacketPeer implementation that should be passed to [method SceneTree.set_network_peer] after being initialized as either a client or server. Events can then be handled by connecting to [SceneTree] signals. </description> <tutorials> + http://docs.godotengine.org/en/3.0/tutorials/networking/high_level_multiplayer.html + http://enet.bespin.org/usergroup0.html </tutorials> <demos> </demos> @@ -15,6 +17,7 @@ <return type="void"> </return> <description> + Closes the connection. Ignored if no connection is currently established. If this is a server it tries to notify all clients before forcibly disconnecting them. If this is a client it simply closes the connection to the server. </description> </method> <method name="create_client"> @@ -29,7 +32,7 @@ <argument index="3" name="out_bandwidth" type="int" default="0"> </argument> <description> - Create client that connects to a server at address [code]ip[/code] using specified [code]port[/code]. + Create client that connects to a server at address [code]ip[/code] using specified [code]port[/code]. The given IP needs to be in IPv4 or IPv6 address format, for example: [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. </description> </method> <method name="create_server"> @@ -44,7 +47,7 @@ <argument index="3" name="out_bandwidth" type="int" default="0"> </argument> <description> - Create server that listens to connections via [code]port[/code]. + Create server that listens to connections via [code]port[/code]. The port needs to be an available, unused port between 0 and 65535. Note that ports below 1024 are privileged and may require elevated permissions depending on the platform. To change the interface the server listens on, use [method set_bind_ip]. The default IP is the wildcard [code]*[/code], which listens on all available interfaces. [code]max_clients[/code] is the maximum number of clients that are allowed at once, any number up to 4096 may be used, although the achievable number of simultaneous clients may be far lower and depends on the application. For additional details on the bandwidth parameters, see [method create_client]. Returns [code]OK[/code] if a server 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 server could not be created. </description> </method> <method name="set_bind_ip"> @@ -53,23 +56,30 @@ <argument index="0" name="ip" type="String"> </argument> <description> + The IP used when creating a server. This is set to the wildcard [code]*[/code] by default, which binds to all available interfaces. The given IP needs to be in IPv4 or IPv6 address format, for example: [code]192.168.1.1[/code]. </description> </method> </methods> <members> <member name="compression_mode" type="int" setter="set_compression_mode" getter="get_compression_mode" enum="NetworkedMultiplayerENet.CompressionMode"> + The compression method used for network packets. Default is no compression. These have different tradeoffs of compression speed versus bandwidth, you may need to test which one works best for your use case if you use compression at all. </member> </members> <constants> <constant name="COMPRESS_NONE" value="0" enum="CompressionMode"> + No compression. </constant> <constant name="COMPRESS_RANGE_CODER" value="1" enum="CompressionMode"> + ENet's buildin range encoding. </constant> <constant name="COMPRESS_FASTLZ" value="2" enum="CompressionMode"> + FastLZ compression. </constant> <constant name="COMPRESS_ZLIB" value="3" enum="CompressionMode"> + zlib compression. </constant> <constant name="COMPRESS_ZSTD" value="4" enum="CompressionMode"> + ZStandard compression. </constant> </constants> </class> diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index f69b632e76..8a7c2a773a 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -49,7 +49,6 @@ if env['builtin_freetype']: "src/pshinter/pshinter.c", "src/psnames/psnames.c", "src/raster/raster.c", - "src/sfnt/sfnt.c", "src/smooth/smooth.c", "src/truetype/truetype.c", "src/type1/type1.c", @@ -58,9 +57,18 @@ if env['builtin_freetype']: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - # Include header for UWP to fix build issues - if "platform" in env and env["platform"] == "uwp": - env.Append(CCFLAGS=['/FI', '"modules/freetype/uwpdef.h"']) + sfnt = thirdparty_dir + 'src/sfnt/sfnt.c' + + if 'platform' in env: + if env['platform'] == 'uwp': + # Include header for UWP to fix build issues + env.Append(CCFLAGS=['/FI', '"modules/freetype/uwpdef.h"']) + elif env['platform'] == 'javascript': + # Forcibly undefine this macro so SIMD is not used in this file, + # since currently unsuported in WASM + sfnt = env.Object(sfnt, CPPFLAGS=['-U__OPTIMIZE__']) + + thirdparty_sources += [sfnt] env.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include"]) @@ -87,6 +95,6 @@ if env['builtin_freetype']: # Godot source files env.add_source_files(env.modules_sources, "*.cpp") -env.Append(CCFLAGS=['-DFREETYPE_ENABLED']) +env.Append(CCFLAGS=['-DFREETYPE_ENABLED', '-DFT_CONFIG_OPTION_USE_PNG']) Export('env') diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml index bceb4f1f4c..be86ff0541 100644 --- a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml +++ b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.0-stable"> +<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.1"> <brief_description> GDNative wrapper for an ARVR interface </brief_description> diff --git a/modules/gdnative/doc_classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml index 7e4d956604..ca0457623f 100644 --- a/modules/gdnative/doc_classes/GDNative.xml +++ b/modules/gdnative/doc_classes/GDNative.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDNative" inherits="Reference" category="Core" version="3.0-stable"> +<class name="GDNative" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml index a6874c9ae8..308d8defc3 100644 --- a/modules/gdnative/doc_classes/GDNativeLibrary.xml +++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.0-stable"> +<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/NativeScript.xml b/modules/gdnative/doc_classes/NativeScript.xml index 6a71cd8d4d..1d3053244b 100644 --- a/modules/gdnative/doc_classes/NativeScript.xml +++ b/modules/gdnative/doc_classes/NativeScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NativeScript" inherits="Script" category="Core" version="3.1-dev"> +<class name="NativeScript" inherits="Script" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/PluginScript.xml b/modules/gdnative/doc_classes/PluginScript.xml index fbdd8f09e6..27c6adae3f 100644 --- a/modules/gdnative/doc_classes/PluginScript.xml +++ b/modules/gdnative/doc_classes/PluginScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PluginScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="PluginScript" inherits="Script" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h index 671be3bbb9..d1671c014e 100644 --- a/modules/gdnative/include/pluginscript/godot_pluginscript.h +++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h @@ -64,7 +64,7 @@ typedef struct { //this is used by script languages that keep a reference counter of their own //you can make make Ref<> not die when it reaches zero, so deleting the reference //depends entirely from the script. - // Note: You can set thoses function pointer to NULL if not needed. + // Note: You can set those function pointer to NULL if not needed. void (*refcount_incremented)(godot_pluginscript_instance_data *p_data); bool (*refcount_decremented)(godot_pluginscript_instance_data *p_data); // return true if it can die } godot_pluginscript_instance_desc; diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index f2e9bef467..5806ee3f3f 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -958,6 +958,7 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) { NativeScriptLanguage::NativeScriptLanguage() { NativeScriptLanguage::singleton = this; #ifndef NO_THREADS + has_objects_to_register = false; mutex = Mutex::create(); #endif } diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml index 59cb00e3f6..40a435f459 100644 --- a/modules/gdscript/doc_classes/GDScript.xml +++ b/modules/gdscript/doc_classes/GDScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="GDScript" inherits="Script" category="Core" version="3.1"> <brief_description> A script implemented in the GDScript programming language. </brief_description> diff --git a/modules/gdscript/doc_classes/GDScriptFunctionState.xml b/modules/gdscript/doc_classes/GDScriptFunctionState.xml index 8510136f68..c205cedef5 100644 --- a/modules/gdscript/doc_classes/GDScriptFunctionState.xml +++ b/modules/gdscript/doc_classes/GDScriptFunctionState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.0-stable"> +<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.1"> <brief_description> State of a function call after yielding. </brief_description> diff --git a/modules/gdscript/doc_classes/GDScriptNativeClass.xml b/modules/gdscript/doc_classes/GDScriptNativeClass.xml index 48826ec1e0..90935b5c22 100644 --- a/modules/gdscript/doc_classes/GDScriptNativeClass.xml +++ b/modules/gdscript/doc_classes/GDScriptNativeClass.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.0-stable"> +<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 1649fb52f2..048948dada 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -181,7 +181,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: //wait, identifier could be a local variable or something else... careful here, must reference properly //as stack may be more interesting to work with - //This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases peformance a lot. + //This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases performance a lot. const GDScriptParser::IdentifierNode *in = static_cast<const GDScriptParser::IdentifierNode *>(p_expression); diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 505562324f..5f72dca866 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -60,7 +60,7 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str "# var a = 2\n" + "# var b = \"textvar\"\n\n" + "func _ready():\n" + - "%TS%# Called every time the node is added to the scene.\n" + + "%TS%# Called when the node is added to the scene for the first time.\n" + "%TS%# Initialization here\n" + "%TS%pass\n\n" + "#func _process(delta):\n" + @@ -410,13 +410,11 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na String s = "func " + p_name + "("; if (p_args.size()) { - s += " "; for (int i = 0; i < p_args.size(); i++) { if (i > 0) s += ", "; s += p_args[i].get_slice(":", 0); } - s += " "; } s += "):\n" + _get_indentation() + "pass # replace with function body\n"; diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index a2f449909f..f83bec0c7f 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -1535,15 +1535,21 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar // then the function did yield again after resuming. if (ret.is_ref()) { GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret); - if (gdfs && gdfs->function == function) + if (gdfs && gdfs->function == function) { completed = false; + gdfs->previous_state = Ref<GDScriptFunctionState>(this); + } } function = NULL; //cleaned up; state.result = Variant(); if (completed) { - emit_signal("completed", ret); + GDScriptFunctionState *state = this; + while (state != NULL) { + state->emit_signal("completed", ret); + state = *(state->previous_state); + } } return ret; @@ -1591,15 +1597,21 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { // then the function did yield again after resuming. if (ret.is_ref()) { GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret); - if (gdfs && gdfs->function == function) + if (gdfs && gdfs->function == function) { completed = false; + gdfs->previous_state = Ref<GDScriptFunctionState>(this); + } } function = NULL; //cleaned up; state.result = Variant(); if (completed) { - emit_signal("completed", ret); + GDScriptFunctionState *state = this; + while (state != NULL) { + state->emit_signal("completed", ret); + state = *(state->previous_state); + } } return ret; diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 9310444c7a..dff4bdfaf2 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -234,6 +234,7 @@ class GDScriptFunctionState : public Reference { GDScriptFunction *function; GDScriptFunction::CallState state; Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error); + Ref<GDScriptFunctionState> previous_state; protected: static void _bind_methods(); diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index c067d5409f..278585cb01 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -358,13 +358,16 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = Math::dectime((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]); } break; case MATH_RANDOMIZE: { + VALIDATE_ARG_COUNT(0); Math::randomize(); r_ret = Variant(); } break; case MATH_RAND: { + VALIDATE_ARG_COUNT(0); r_ret = Math::rand(); } break; case MATH_RANDF: { + VALIDATE_ARG_COUNT(0); r_ret = Math::randf(); } break; case MATH_RANDOM: { @@ -593,7 +596,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = String(result); } break; case TEXT_STR: { + if (p_arg_count < 1) { + r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + r_ret = Variant(); + return; + } String str; for (int i = 0; i < p_arg_count; i++) { @@ -1180,6 +1189,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case PRINT_STACK: { + VALIDATE_ARG_COUNT(0); ScriptLanguage *script = GDScriptLanguage::get_singleton(); for (int i = 0; i < script->debug_get_stack_level_count(); i++) { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 1392323d56..435bc327dc 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -456,23 +456,26 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (!validating) { //this can be too slow for just validating code - if (for_completion && ScriptCodeCompletionCache::get_singleton()) { + if (for_completion && ScriptCodeCompletionCache::get_singleton() && FileAccess::exists(path)) { res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path); - } else { // essential; see issue 15902 + } else if (!for_completion || FileAccess::exists(path)) { res = ResourceLoader::load(path); } - if (!res.is_valid()) { - _set_error("Can't preload resource at path: " + path); - return NULL; - } } else { if (!FileAccess::exists(path)) { _set_error("Can't preload resource at path: " + path); return NULL; + } else if (ScriptCodeCompletionCache::get_singleton()) { + res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path); } } + if (!res.is_valid()) { + _set_error("Can't preload resource at path: " + path); + return NULL; + } + if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ')' after 'preload' path"); return NULL; @@ -576,18 +579,47 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (identifier == StringName()) { - _set_error("Built-in type constant expected after '.'"); + _set_error("Built-in type constant or static function expected after '.'"); return NULL; } if (!Variant::has_numeric_constant(bi_type, identifier)) { - _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); - return NULL; - } + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN && + Variant::is_method_const(bi_type, identifier) && + Variant::get_method_return_type(bi_type, identifier) == bi_type) { + + tokenizer->advance(); + + OperatorNode *construct = alloc_node<OperatorNode>(); + construct->op = OperatorNode::OP_CALL; + + TypeNode *tn = alloc_node<TypeNode>(); + tn->vtype = bi_type; + construct->arguments.push_back(tn); + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op = OperatorNode::OP_CALL; + op->arguments.push_back(construct); + + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name = identifier; + op->arguments.push_back(id); + + if (!_parse_arguments(op, op->arguments, p_static, true)) + return NULL; + + expr = op; + } else { + + _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); + return NULL; + } + } else { - ConstantNode *cn = alloc_node<ConstantNode>(); - cn->value = Variant::get_numeric_constant_value(bi_type, identifier); - expr = cn; + ConstantNode *cn = alloc_node<ConstantNode>(); + cn->value = Variant::get_numeric_constant_value(bi_type, identifier); + expr = cn; + } } else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_PARENTHESIS_OPEN && tokenizer->is_token_literal()) { // We check with is_token_literal, as this allows us to use match/sync/etc. as a name @@ -1516,11 +1548,11 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to String errwhere; if (op->arguments[0]->type == Node::TYPE_TYPE) { TypeNode *tn = static_cast<TypeNode *>(op->arguments[0]); - errwhere = "'" + Variant::get_type_name(tn->vtype) + "'' constructor"; + errwhere = "'" + Variant::get_type_name(tn->vtype) + "' constructor"; } else { GDScriptFunctions::Function func = static_cast<BuiltInFunctionNode *>(op->arguments[0])->function; - errwhere = String("'") + GDScriptFunctions::get_func_name(func) + "'' intrinsic function"; + errwhere = String("'") + GDScriptFunctions::get_func_name(func) + "' intrinsic function"; } switch (ce.error) { @@ -4069,7 +4101,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { ConstantNode *cn = static_cast<ConstantNode *>(subexpr); if (cn->value.get_type() == Variant::NIL) { - _set_error("Can't accept a null constant expression for infering export type."); + _set_error("Can't accept a null constant expression for inferring export type."); return; } member._export.type = cn->value.get_type(); @@ -4205,7 +4237,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } break; case GDScriptTokenizer::TK_PR_ENUM: { - //mutiple constant declarations.. + //multiple constant declarations.. int last_assign = -1; // Incremented by 1 right before the assingment. String enum_name; @@ -4356,8 +4388,6 @@ Error GDScriptParser::_parse(const String &p_base_path) { base_path = p_base_path; - clear(); - //assume class ClassNode *main_class = alloc_node<ClassNode>(); main_class->initializer = alloc_node<BlockNode>(); @@ -4382,17 +4412,7 @@ Error GDScriptParser::_parse(const String &p_base_path) { Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &p_base_path, const String &p_self_path) { - for_completion = false; - validating = false; - completion_type = COMPLETION_NONE; - completion_node = NULL; - completion_class = NULL; - completion_function = NULL; - completion_block = NULL; - completion_found = false; - current_block = NULL; - current_class = NULL; - current_function = NULL; + clear(); self_path = p_self_path; GDScriptTokenizerBuffer *tb = memnew(GDScriptTokenizerBuffer); @@ -4406,16 +4426,7 @@ Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const St Error GDScriptParser::parse(const String &p_code, const String &p_base_path, bool p_just_validate, const String &p_self_path, bool p_for_completion) { - completion_type = COMPLETION_NONE; - completion_node = NULL; - completion_class = NULL; - completion_function = NULL; - completion_block = NULL; - completion_found = false; - current_block = NULL; - current_class = NULL; - - current_function = NULL; + clear(); self_path = p_self_path; GDScriptTokenizerText *tt = memnew(GDScriptTokenizerText); diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index 44685220b3..bb652f3bdf 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GridMap" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="GridMap" inherits="Spatial" category="Core" version="3.1"> <brief_description> Node for 3D tile-based maps. </brief_description> diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 7b7bc0fa2a..869492232c 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -99,6 +99,20 @@ void GridMapEditor::_menu_option(int p_option) { int idx = options->get_popup()->get_item_index(MENU_OPTION_X_AXIS + i); options->get_popup()->set_item_checked(idx, i == new_axis); } + + if (edit_axis != new_axis) { + int item1 = options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL); + int item2 = options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL); + if (edit_axis == Vector3::AXIS_Y) { + options->get_popup()->set_item_text(item1, TTR("Next Plane")); + options->get_popup()->set_item_text(item2, TTR("Previous Plane")); + spin_box_label->set_text(TTR("Plane:")); + } else if (new_axis == Vector3::AXIS_Y) { + options->get_popup()->set_item_text(item1, TTR("Next Floor")); + options->get_popup()->set_item_text(item2, TTR("Previous Floor")); + spin_box_label->set_text(TTR("Floor:")); + } + } edit_axis = Vector3::Axis(new_axis); update_grid(); _update_clip(); @@ -627,12 +641,21 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid()) { - if (pan_gesture->get_command() || pan_gesture->get_shift()) { - const real_t delta = pan_gesture->get_delta().y; - floor->set_value(floor->get_value() + SGN(delta)); + if (pan_gesture->get_alt() && (pan_gesture->get_command() || pan_gesture->get_shift())) { + const real_t delta = pan_gesture->get_delta().y * 0.5; + accumulated_floor_delta += delta; + int step = 0; + if (ABS(accumulated_floor_delta) > 1.0) { + step = SGN(accumulated_floor_delta); + accumulated_floor_delta -= step; + } + if (step) { + floor->set_value(floor->get_value() + step); + } return true; } } + accumulated_floor_delta = 0.0; return false; } @@ -756,7 +779,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) { set_process(true); - Vector3 edited_floor = p_gridmap->get_meta("_editor_floor_"); + Vector3 edited_floor = p_gridmap->has_meta("_editor_floor_") ? p_gridmap->get_meta("_editor_floor_") : Variant(); clip_mode = p_gridmap->has_meta("_editor_clip_") ? ClipMode(p_gridmap->get_meta("_editor_clip_").operator int()) : CLIP_DISABLED; for (int i = 0; i < 3; i++) { @@ -998,9 +1021,9 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { spatial_editor_hb->set_alignment(BoxContainer::ALIGN_END); SpatialEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); - Label *fl = memnew(Label); - fl->set_text(TTR("Floor:")); - spatial_editor_hb->add_child(fl); + spin_box_label = memnew(Label); + spin_box_label->set_text(TTR("Floor:")); + spatial_editor_hb->add_child(spin_box_label); floor = memnew(SpinBox); floor->set_min(-32767); @@ -1233,6 +1256,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { selection.active = false; updating = false; + accumulated_floor_delta = 0.0; } GridMapEditor::~GridMapEditor() { @@ -1245,9 +1269,10 @@ GridMapEditor::~GridMapEditor() { VisualServer::get_singleton()->free(grid_instance[i]); if (cursor_instance.is_valid()) VisualServer::get_singleton()->free(cursor_instance); - if (selection_level_instance[i].is_valid()) { + if (selection_level_instance[i].is_valid()) VisualServer::get_singleton()->free(selection_level_instance[i]); - } + if (selection_level_mesh[i].is_valid()) + VisualServer::get_singleton()->free(selection_level_mesh[i]); } VisualServer::get_singleton()->free(selection_mesh); diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index 3fc92bf7aa..f79d9aefa0 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -76,12 +76,14 @@ class GridMapEditor : public VBoxContainer { Panel *panel; MenuButton *options; SpinBox *floor; + double accumulated_floor_delta; ToolButton *mode_thumbnail; ToolButton *mode_list; HBoxContainer *spatial_editor_hb; ConfirmationDialog *settings_dialog; VBoxContainer *settings_vbc; SpinBox *settings_pick_distance; + Label *spin_box_label; struct SetItem { diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp index 3cc362b5d6..d592c19b97 100644 --- a/modules/hdr/image_loader_hdr.cpp +++ b/modules/hdr/image_loader_hdr.cpp @@ -42,14 +42,18 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force ERR_FAIL_COND_V(header != "#?RADIANCE" && header != "#?RGBE", ERR_FILE_UNRECOGNIZED); while (true) { - String format = f->get_token(); + String line = f->get_line(); ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_UNRECOGNIZED); - if (format.begins_with("FORMAT=") && format != "FORMAT=32-bit_rle_rgbe") { - ERR_EXPLAIN("Only 32-bit_rle_rgbe is supported for .hdr files."); - return ERR_FILE_UNRECOGNIZED; - } - if (format == "FORMAT=32-bit_rle_rgbe") + if (line == "") // empty line indicates end of header break; + if (line.begins_with("FORMAT=")) { // leave option to implement other commands + if (line != "FORMAT=32-bit_rle_rgbe") { + ERR_EXPLAIN("Only 32-bit_rle_rgbe is supported for HDR files."); + return ERR_FILE_UNRECOGNIZED; + } + } else if (!line.begins_with("#")) { // not comment + WARN_PRINTS("Ignoring unsupported header information in HDR : " + line); + } } String token = f->get_token(); diff --git a/modules/mbedtls/SCsub b/modules/mbedtls/SCsub index b846ae38ad..38198c9105 100755 --- a/modules/mbedtls/SCsub +++ b/modules/mbedtls/SCsub @@ -85,7 +85,7 @@ if env['builtin_mbedtls']: thirdparty_dir = "#thirdparty/mbedtls/library/" thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] env_mbed_tls.add_source_files(env.modules_sources, thirdparty_sources) - env_mbed_tls.Append(CPPPATH=["#thirdparty/mbedtls/include/"]) + env_mbed_tls.Prepend(CPPPATH=["#thirdparty/mbedtls/include/"]) # Module sources env_mbed_tls.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py index 4e1155f0c6..aa8ef111d3 100644 --- a/modules/mobile_vr/config.py +++ b/modules/mobile_vr/config.py @@ -1,6 +1,6 @@ def can_build(platform): # should probably change this to only be true on iOS and Android - return True + return False def configure(env): pass diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml index 82300e707a..359d654433 100644 --- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml +++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.0-stable"> +<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.1"> <brief_description> Generic mobile VR implementation </brief_description> diff --git a/modules/mono/SCsub b/modules/mono/SCsub index aa8626e6da..a1dfcf6377 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -31,11 +31,18 @@ def make_cs_files_header(src, dst): if i > 0: header.write(', ') header.write(byte_to_str(buf[buf_idx])) - inserted_files += '\tr_files.insert(\"' + file + '\", ' \ + inserted_files += '\tr_files.insert("' + file + '", ' \ 'CompressedFile(_cs_' + name + '_compressed_size, ' \ '_cs_' + name + '_uncompressed_size, ' \ '_cs_' + name + '_compressed));\n' header.write(' };\n') + version_file = os.path.join(src, 'VERSION.txt') + with open(version_file, 'r') as content_file: + try: + glue_version = int(content_file.read()) # make sure the format is valid + header.write('\n#define CS_GLUE_VERSION UINT32_C(' + str(glue_version) + ')\n') + except ValueError: + raise ValueError('Invalid C# glue version in: ' + version_file) header.write('\nstruct CompressedFile\n' '{\n' '\tint compressed_size;\n' '\tint uncompressed_size;\n' '\tconst unsigned char* data;\n' '\n\tCompressedFile(int p_comp_size, int p_uncomp_size, const unsigned char* p_data)\n' @@ -80,23 +87,23 @@ def find_msbuild_unix(filename): import sys hint_dirs = ['/opt/novell/mono/bin'] - if sys.platform == "darwin": + if sys.platform == 'darwin': hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin'] + hint_dirs for hint_dir in hint_dirs: hint_path = os.path.join(hint_dir, filename) if os.path.isfile(hint_path): return hint_path - elif os.path.isfile(hint_path + ".exe"): - return hint_path + ".exe" + elif os.path.isfile(hint_path + '.exe'): + return hint_path + '.exe' - for hint_dir in os.environ["PATH"].split(os.pathsep): + for hint_dir in os.environ['PATH'].split(os.pathsep): hint_dir = hint_dir.strip('"') hint_path = os.path.join(hint_dir, filename) if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): return hint_path - if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK): - return hint_path + ".exe" + if os.path.isfile(hint_path + '.exe') and os.access(hint_path + '.exe', os.X_OK): + return hint_path + '.exe' return None @@ -152,7 +159,7 @@ def mono_build_solution(source, target, env): xbuild_fallback = env['xbuild_fallback'] if xbuild_fallback and os.name == 'nt': - print("Option 'xbuild_fallback' not supported on Windows") + print('Option \'xbuild_fallback\' not supported on Windows') xbuild_fallback = False if xbuild_fallback: @@ -202,10 +209,16 @@ def mono_build_solution(source, target, env): copyfile(os.path.join(src_dir, asm_file), os.path.join(dst_dir, asm_file)) +output_dir = Dir('#bin').abspath +assemblies_output_dir = Dir(env['mono_assemblies_output_dir']).abspath -mono_sln_builder = Builder(action = mono_build_solution) +mono_sln_builder = Builder(action=mono_build_solution) env_mono.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder}) env_mono.MonoBuildSolution( - os.path.join(Dir('#bin').abspath, 'GodotSharpTools.dll'), + os.path.join(assemblies_output_dir, 'GodotSharpTools.dll'), 'editor/GodotSharpTools/GodotSharpTools.sln' ) + +if os.path.normpath(output_dir) != os.path.normpath(assemblies_output_dir): + rel_assemblies_output_dir = os.path.relpath(assemblies_output_dir, output_dir) + env_mono.Append(CPPDEFINES={'GD_MONO_EDITOR_ASSEMBLIES_DIR': rel_assemblies_output_dir}) diff --git a/modules/mono/config.py b/modules/mono/config.py index 7c1846dcc2..831d849ea6 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -2,8 +2,9 @@ import imp import os import sys +import subprocess -from SCons.Script import BoolVariable, Environment, Variables +from SCons.Script import BoolVariable, Dir, Environment, PathVariable, Variables monoreg = imp.load_source('mono_reg_utils', 'modules/mono/mono_reg_utils.py') @@ -29,20 +30,16 @@ def is_enabled(): return False -def copy_file_no_replace(src_dir, dst_dir, name): +def copy_file(src_dir, dst_dir, name): from shutil import copyfile src_path = os.path.join(src_dir, name) dst_path = os.path.join(dst_dir, name) - need_copy = True if not os.path.isdir(dst_dir): os.mkdir(dst_dir) - elif os.path.exists(dst_path): - need_copy = False - if need_copy: - copyfile(src_path, dst_path) + copyfile(src_path, dst_path) def configure(env): @@ -51,11 +48,13 @@ def configure(env): envvars = Variables() envvars.Add(BoolVariable('mono_static', 'Statically link mono', False)) + envvars.Add(PathVariable('mono_assemblies_output_dir', 'Path to the assemblies output directory', '#bin', PathVariable.PathIsDirCreate)) envvars.Update(env) bits = env['bits'] mono_static = env['mono_static'] + assemblies_output_dir = Dir(env['mono_assemblies_output_dir']).abspath mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0'] @@ -99,11 +98,14 @@ def configure(env): if not mono_dll_name: raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path) - copy_file_no_replace(mono_bin_path, 'bin', mono_dll_name + '.dll') + copy_file(mono_bin_path, 'bin', mono_dll_name + '.dll') + + copy_file(os.path.join(mono_lib_path, 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') else: sharedlib_ext = '.dylib' if sys.platform == 'darwin' else '.so' mono_root = '' + mono_lib_path = '' if bits == '32': if os.getenv('MONO32_PREFIX'): @@ -148,7 +150,9 @@ def configure(env): if not mono_so_name: raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path) - copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) + copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) + + copy_file(os.path.join(mono_lib_path, 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') else: if mono_static: raise RuntimeError('mono-static: Not supported with pkg-config. Specify a mono prefix manually') @@ -157,6 +161,7 @@ def configure(env): mono_lib_path = '' mono_so_name = '' + mono_prefix = subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip() tmpenv = Environment() tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH')) @@ -172,7 +177,8 @@ def configure(env): if not mono_so_name: raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH'])) - copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) + copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) + copy_file(os.path.join(mono_prefix, 'lib', 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') env.Append(LINKFLAGS='-rdynamic') diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index fb45136575..1d0afa7f2d 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -118,6 +118,8 @@ void CSharpLanguage::init() { #ifdef TOOLS_ENABLED EditorNode::add_init_callback(&gdsharp_editor_init_callback); + + GLOBAL_DEF("mono/export/include_scripts_content", true); #endif } @@ -280,6 +282,15 @@ void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const { p_delimiters->push_back("@\" \""); // verbatim string literal } +static String get_base_class_name(const String &p_base_class_name, const String p_class_name) { + + String base_class = p_base_class_name; + if (p_class_name == base_class) { + base_class = "Godot." + base_class; + } + return base_class; +} + Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { String script_template = "using " BINDINGS_NAMESPACE ";\n" @@ -306,7 +317,8 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin "// }\n" "}\n"; - script_template = script_template.replace("%BASE_CLASS_NAME%", p_base_class_name) + String base_class_name = get_base_class_name(p_base_class_name, p_class_name); + script_template = script_template.replace("%BASE_CLASS_NAME%", base_class_name) .replace("%CLASS_NAME%", p_class_name); Ref<CSharpScript> script; @@ -325,12 +337,24 @@ bool CSharpLanguage::is_using_templates() { void CSharpLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) { String src = p_script->get_source_code(); - src = src.replace("%BASE%", p_base_class_name) + String base_class_name = get_base_class_name(p_base_class_name, p_class_name); + src = src.replace("%BASE%", base_class_name) .replace("%CLASS%", p_class_name) .replace("%TS%", _get_indentation()); p_script->set_source_code(src); } +String CSharpLanguage::validate_path(const String &p_path) const { + + String class_name = p_path.get_file().get_basename(); + List<String> keywords; + get_reserved_words(&keywords); + if (keywords.find(class_name)) { + return TTR("Class name can't be a reserved keyword"); + } + return ""; +} + Script *CSharpLanguage::create_script() const { return memnew(CSharpScript); @@ -454,7 +478,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() #ifdef DEBUG_ENABLED // Printing an error here will result in endless recursion, so we must be careful - if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_api_assembly() || !GDMonoUtils::mono_cache.corlib_cache_updated) + if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_core_api_assembly() || !GDMonoUtils::mono_cache.corlib_cache_updated) return Vector<StackInfo>(); MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr()); @@ -1550,7 +1574,6 @@ bool CSharpScript::_update_exports() { } bool CSharpScript::_update_signals() { -#ifdef TOOLS_ENABLED if (!valid) return false; @@ -1581,8 +1604,6 @@ bool CSharpScript::_update_signals() { } return changed; -#endif - return false; } bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Vector<Argument> ¶ms) { @@ -2135,9 +2156,7 @@ void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const { } void CSharpScript::update_signals() { -#ifdef TOOLS_ENABLED _update_signals(); -#endif } Ref<Script> CSharpScript::get_base_script() const { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index ffb1d2e0f4..8666149111 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -90,15 +90,15 @@ class CSharpScript : public Script { Variant::Type type; }; + Map<StringName, Vector<Argument> > _signals; + bool signals_invalidated; + #ifdef TOOLS_ENABLED List<PropertyInfo> exported_members_cache; // members_cache Map<StringName, Variant> exported_members_defval_cache; // member_default_values_cache Set<PlaceHolderScriptInstance *> placeholders; bool source_changed_cache; bool exports_invalidated; - Map<StringName, Vector<Argument> > _signals; - bool signals_invalidated; - void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames); virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); #endif @@ -294,6 +294,7 @@ public: virtual bool is_using_templates(); virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script); /* TODO */ virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { return true; } + virtual String validate_path(const String &p_path) const; virtual Script *create_script() const; virtual bool has_named_classes() const; virtual bool supports_builtin_mode() const; diff --git a/modules/mono/doc_classes/@C#.xml b/modules/mono/doc_classes/@C#.xml index 0f33c76eb2..082bc30fd8 100644 --- a/modules/mono/doc_classes/@C#.xml +++ b/modules/mono/doc_classes/@C#.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="@C#" category="Core" version="3.0-stable"> +<class name="@C#" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml index 3efe71f1b3..a1f7399653 100644 --- a/modules/mono/doc_classes/CSharpScript.xml +++ b/modules/mono/doc_classes/CSharpScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSharpScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="CSharpScript" inherits="Script" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml index 1e5edf2a2a..985c66464b 100644 --- a/modules/mono/doc_classes/GodotSharp.xml +++ b/modules/mono/doc_classes/GodotSharp.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GodotSharp" inherits="Object" category="Core" version="3.0-stable"> +<class name="GodotSharp" inherits="Object" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 62c7a94755..a210b8e480 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -70,8 +70,6 @@ #define LOCAL_RET "ret" -#define CS_CLASS_NATIVECALLS "NativeCalls" -#define CS_CLASS_NATIVECALLS_EDITOR "EditorNativeCalls" #define CS_FIELD_MEMORYOWN "memoryOwn" #define CS_PARAM_METHODBIND "method" #define CS_PARAM_INSTANCE "ptr" @@ -105,6 +103,8 @@ #define C_METHOD_MANAGED_TO_DICT C_NS_MONOMARSHAL "::mono_object_to_Dictionary" #define C_METHOD_MANAGED_FROM_DICT C_NS_MONOMARSHAL "::Dictionary_to_mono_object" +#define BINDINGS_GENERATOR_VERSION UINT32_C(2) + const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n"; bool BindingsGenerator::verbose_output = false; @@ -529,7 +529,15 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo "using System.Collections.Generic;\n" "\n"); cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); - cs_icalls_content.push_back(INDENT1 "internal static class " CS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK); + cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK); + + cs_icalls_content.push_back(INDENT2 "internal static ulong godot_api_hash = "); + cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + ";\n"); + cs_icalls_content.push_back(INDENT2 "internal static uint bindings_version = "); + cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n"); + cs_icalls_content.push_back(INDENT2 "internal static uint cs_glue_version = "); + cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n"); + cs_icalls_content.push_back("\n"); #define ADD_INTERNAL_CALL(m_icall) \ if (!m_icall.editor_only) { \ @@ -551,7 +559,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo cs_icalls_content.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); - String internal_methods_file = path_join(core_dir, CS_CLASS_NATIVECALLS ".cs"); + String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs"); Error err = _save_file(internal_methods_file, cs_icalls_content); if (err != OK) @@ -626,7 +634,15 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, "using System.Collections.Generic;\n" "\n"); cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); - cs_icalls_content.push_back(INDENT1 "internal static class " CS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK); + cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK); + + cs_icalls_content.push_back(INDENT2 "internal static ulong godot_api_hash = "); + cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + ";\n"); + cs_icalls_content.push_back(INDENT2 "internal static uint bindings_version = "); + cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n"); + cs_icalls_content.push_back(INDENT2 "internal static uint cs_glue_version = "); + cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n"); + cs_icalls_content.push_back("\n"); #define ADD_INTERNAL_CALL(m_icall) \ if (m_icall.editor_only) { \ @@ -648,7 +664,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, cs_icalls_content.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); - String internal_methods_file = path_join(core_dir, CS_CLASS_NATIVECALLS_EDITOR ".cs"); + String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs"); Error err = _save_file(internal_methods_file, cs_icalls_content); if (err != OK) @@ -714,7 +730,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } output.push_back(INDENT1 "public "); - output.push_back(itype.is_singleton ? "static class " : "class "); + bool is_abstract = !ClassDB::can_instance(itype.name) && ClassDB::is_class_enabled(itype.name); // can_instance returns true if there's a constructor and the class is not 'disabled' + output.push_back(itype.is_singleton ? "static class " : (is_abstract ? "abstract class " : "class ")); output.push_back(itype.proxy_name); if (itype.is_singleton) { @@ -882,7 +899,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back("\";\n"); output.push_back(INDENT2 "internal static IntPtr " BINDINGS_PTR_FIELD " = "); - output.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); + output.push_back(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS); output.push_back("." ICALL_PREFIX); output.push_back(itype.name); output.push_back(SINGLETON_ICALL_SUFFIX "();\n"); @@ -912,7 +929,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // The engine will initialize the pointer field of the managed side before calling the constructor // This is why we only allocate a new native object from the constructor if the pointer field is not set output.push_back(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = "); - output.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); + output.push_back(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS); output.push_back("." + ctor_method); output.push_back("(this);\n" CLOSE_BLOCK_L2); } else { @@ -956,7 +973,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str "if (disposed) return;\n" INDENT3 "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN - " = false;\n" INDENT5 CS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR + " = false;\n" INDENT5 BINDINGS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR "(this, " BINDINGS_PTR_FIELD ");\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3 "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" INDENT3 "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2); @@ -1229,7 +1246,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf { if (p_itype.is_object_type && !p_imethod.is_virtual && !p_imethod.requires_object_call) { p_output.push_back(MEMBER_BEGIN "private static IntPtr "); - p_output.push_back(method_bind_field + " = " CS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); + p_output.push_back(method_bind_field + " = " BINDINGS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); p_output.push_back(p_imethod.name); p_output.push_back("\");\n"); } @@ -1310,7 +1327,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf const InternalCall *im_icall = match->value(); - String im_call = im_icall->editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS; + String im_call = im_icall->editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS; im_call += "." + im_icall->name + "(" + icall_params + ");\n"; if (p_imethod.arguments.size()) @@ -1400,25 +1417,33 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { } output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK); + output.push_back("uint64_t get_core_api_hash() { return "); - output.push_back(itos(GDMono::get_singleton()->get_api_core_hash()) + "; }\n"); + output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "; }\n"); + output.push_back("#ifdef TOOLS_ENABLED\n" "uint64_t get_editor_api_hash() { return "); - output.push_back(itos(GDMono::get_singleton()->get_api_editor_hash()) + + output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + "; }\n#endif // TOOLS_ENABLED\n"); + + output.push_back("uint32_t get_bindings_version() { return "); + output.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n"); + output.push_back("uint32_t get_cs_glue_version() { return "); + output.push_back(String::num_uint64(CS_GLUE_VERSION) + "; }\n"); + output.push_back("void register_generated_icalls() " OPEN_BLOCK); output.push_back("\tgodot_register_header_icalls();"); -#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \ - { \ - output.push_back("\tmono_add_internal_call("); \ - output.push_back("\"" BINDINGS_NAMESPACE "."); \ - output.push_back(m_icall.editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); \ - output.push_back("::"); \ - output.push_back(m_icall.name); \ - output.push_back("\", (void*)"); \ - output.push_back(m_icall.name); \ - output.push_back(");\n"); \ +#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \ + { \ + output.push_back("\tmono_add_internal_call("); \ + output.push_back("\"" BINDINGS_NAMESPACE "."); \ + output.push_back(m_icall.editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS); \ + output.push_back("::"); \ + output.push_back(m_icall.name); \ + output.push_back("\", (void*)"); \ + output.push_back(m_icall.name); \ + output.push_back(");\n"); \ } bool tools_sequence = false; @@ -1486,6 +1511,14 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { return OK; } +uint32_t BindingsGenerator::get_version() { + return BINDINGS_GENERATOR_VERSION; +} + +uint32_t BindingsGenerator::get_cs_glue_version() { + return CS_GLUE_VERSION; +} + Error BindingsGenerator::_save_file(const String &p_path, const List<String> &p_content) { FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE); @@ -1528,9 +1561,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte if (p_imethod.is_vararg) { if (i < p_imethod.arguments.size() - 1) { c_in_statements += sformat(arg_type->c_in.size() ? arg_type->c_in : TypeInterface::DEFAULT_VARARG_C_IN, "Variant", c_param_name); - c_in_statements += "\t" C_LOCAL_PTRCALL_ARGS ".set(0, "; - c_in_statements += sformat("&%s_in", c_param_name); - c_in_statements += ");\n"; + c_in_statements += "\t" C_LOCAL_PTRCALL_ARGS ".set("; + c_in_statements += itos(i); + c_in_statements += sformat(", &%s_in);\n", c_param_name); } } else { if (i > 0) @@ -2231,7 +2264,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2 MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2 MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2 - "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2); + "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2 + MEMBER_BEGIN "public override string ToString()\n" OPEN_BLOCK_L2 "return (string)this;\n" CLOSE_BLOCK_L2); builtin_types.insert(itype.cname, itype); // RID @@ -2365,7 +2399,7 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant:: imethod.name = mi.name; imethod.cname = imethod.name; - imethod.proxy_name = mi.name; + imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(mi.name)); for (int i = 0; i < mi.arguments.size(); i++) { ArgumentInterface iarg; diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 9b5a9cea88..f6194139af 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -536,6 +536,9 @@ public: Error generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output = true); Error generate_glue(const String &p_output_dir); + static uint32_t get_version(); + static uint32_t get_cs_glue_version(); + void initialize(); _FORCE_INLINE_ static BindingsGenerator *get_singleton() { diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index 6b41b10981..ad07f043b2 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -33,7 +33,6 @@ #include "main/main.h" #include "../godotsharp_dirs.h" -#include "../mono_gd/gd_mono.h" #include "../mono_gd/gd_mono_class.h" #include "../mono_gd/gd_mono_marshal.h" #include "../utils/path_utils.h" @@ -178,13 +177,15 @@ bool GodotSharpBuilds::build_api_sln(const String &p_name, const String &p_api_s return true; } -bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name) { +bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type) { String assembly_file = p_assembly_name + ".dll"; String assembly_src = p_src_dir.plus_file(assembly_file); String assembly_dst = p_dst_dir.plus_file(assembly_file); - if (!FileAccess::exists(assembly_dst) || FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst)) { + if (!FileAccess::exists(assembly_dst) || + FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst) || + GDMono::get_singleton()->metadata_is_api_assembly_invalidated(p_api_type)) { DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String xml_file = p_assembly_name + ".xml"; @@ -200,36 +201,49 @@ bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String & memdelete(da); if (err != OK) { - show_build_error_dialog("Failed to copy " API_ASSEMBLY_NAME ".dll"); + show_build_error_dialog("Failed to copy " + assembly_file); return false; } + + GDMono::get_singleton()->metadata_set_api_assembly_invalidated(p_api_type, false); } return true; } -bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { +String GodotSharpBuilds::_api_folder_name(APIAssembly::Type p_api_type) { + + uint64_t api_hash = p_api_type == APIAssembly::API_CORE ? + GDMono::get_singleton()->get_api_core_hash() : + GDMono::get_singleton()->get_api_editor_hash(); + return String::num_uint64(api_hash) + + "_" + String::num_uint64(BindingsGenerator::get_version()) + + "_" + String::num_uint64(BindingsGenerator::get_cs_glue_version()); +} + +bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) { - String api_name = p_api_type == API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME; + String api_name = p_api_type == APIAssembly::API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME; String api_build_config = "Release"; EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 4); pr.step("Generating " + api_name + " solution"); - uint64_t core_hash = GDMono::get_singleton()->get_api_core_hash(); - uint64_t editor_hash = GDMono::get_singleton()->get_api_editor_hash(); + String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir() + .plus_file(_api_folder_name(APIAssembly::API_CORE)) + .plus_file(API_ASSEMBLY_NAME); + String editor_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir() + .plus_file(_api_folder_name(APIAssembly::API_EDITOR)) + .plus_file(EDITOR_API_ASSEMBLY_NAME); - String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir().plus_file(API_ASSEMBLY_NAME "_" + itos(core_hash)); - String editor_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir().plus_file(EDITOR_API_ASSEMBLY_NAME "_" + itos(editor_hash)); - - String api_sln_dir = p_api_type == API_CORE ? core_api_sln_dir : editor_api_sln_dir; + String api_sln_dir = p_api_type == APIAssembly::API_CORE ? core_api_sln_dir : editor_api_sln_dir; String api_sln_file = api_sln_dir.plus_file(api_name + ".sln"); if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) { String core_api_assembly; - if (p_api_type == API_EDITOR) { + if (p_api_type == APIAssembly::API_EDITOR) { core_api_assembly = core_api_sln_dir.plus_file("bin") .plus_file(api_build_config) .plus_file(API_ASSEMBLY_NAME ".dll"); @@ -242,7 +256,7 @@ bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { BindingsGenerator *gen = BindingsGenerator::get_singleton(); bool gen_verbose = OS::get_singleton()->is_stdout_verbose(); - Error err = p_api_type == API_CORE ? + Error err = p_api_type == APIAssembly::API_CORE ? gen->generate_cs_core_project(api_sln_dir, gen_verbose) : gen->generate_cs_editor_project(api_sln_dir, core_api_assembly, gen_verbose); @@ -275,7 +289,7 @@ bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { // Copy the built assembly to the assemblies directory String api_assembly_dir = api_sln_dir.plus_file("bin").plus_file(api_build_config); - if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name)) + if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name, p_api_type)) return false; pr.step("Done"); @@ -283,22 +297,22 @@ bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { return true; } -bool GodotSharpBuilds::build_project_blocking() { +bool GodotSharpBuilds::build_project_blocking(const String &p_config) { if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) return true; // No solution to build - if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_CORE)) + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE)) return false; - if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR)) + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR)) return false; EditorProgress pr("mono_project_debug_build", "Building project solution...", 2); pr.step("Building project solution"); - MonoBuildInfo build_info(GodotSharpDirs::get_project_sln_path(), "Tools"); + MonoBuildInfo build_info(GodotSharpDirs::get_project_sln_path(), p_config); if (!GodotSharpBuilds::get_singleton()->build(build_info)) { GodotSharpBuilds::show_build_error_dialog("Failed to build project solution"); return false; @@ -309,6 +323,11 @@ bool GodotSharpBuilds::build_project_blocking() { return true; } +bool GodotSharpBuilds::editor_build_callback() { + + return build_project_blocking("Tools"); +} + GodotSharpBuilds *GodotSharpBuilds::singleton = NULL; void GodotSharpBuilds::build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code) { @@ -362,7 +381,7 @@ GodotSharpBuilds::GodotSharpBuilds() { singleton = this; - EditorNode::get_singleton()->add_build_callback(&GodotSharpBuilds::build_project_blocking); + EditorNode::get_singleton()->add_build_callback(&GodotSharpBuilds::editor_build_callback); // Build tool settings EditorSettings *ed_settings = EditorSettings::get_singleton(); @@ -462,6 +481,7 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { if (ex) { exited = true; + GDMonoUtils::print_unhandled_exception(ex); String message = "The build constructor threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex); build_tab->on_build_exec_failed(message); ERR_EXPLAIN(message); @@ -482,6 +502,7 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { if (ex) { exited = true; + GDMonoUtils::print_unhandled_exception(ex); String message = "The build method threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex); build_tab->on_build_exec_failed(message); ERR_EXPLAIN(message); diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h index 5d2390ecd9..27b771e324 100644 --- a/modules/mono/editor/godotsharp_builds.h +++ b/modules/mono/editor/godotsharp_builds.h @@ -31,6 +31,7 @@ #ifndef GODOTSHARP_BUILDS_H #define GODOTSHARP_BUILDS_H +#include "../mono_gd/gd_mono.h" #include "mono_bottom_panel.h" #include "mono_build_info.h" @@ -56,17 +57,14 @@ private: HashMap<MonoBuildInfo, BuildProcess, MonoBuildInfo::Hasher> builds; + static String _api_folder_name(APIAssembly::Type p_api_type); + static GodotSharpBuilds *singleton; friend class GDMono; static void _register_internal_calls(); public: - enum APIType { - API_CORE, - API_EDITOR - }; - enum BuildTool { MSBUILD_MONO, #ifdef WINDOWS_ENABLED @@ -89,11 +87,13 @@ public: bool build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback = NULL); static bool build_api_sln(const String &p_name, const String &p_api_sln_dir, const String &p_config); - static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name); + static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type); + + static bool make_api_sln(APIAssembly::Type p_api_type); - static bool make_api_sln(APIType p_api_type); + static bool build_project_blocking(const String &p_config); - static bool build_project_blocking(); + static bool editor_build_callback(); GodotSharpBuilds(); ~GodotSharpBuilds(); diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index 0ef3adfdd0..998da8bda3 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -41,6 +41,7 @@ #include "../utils/path_utils.h" #include "bindings_generator.h" #include "csharp_project.h" +#include "godotsharp_export.h" #include "net_solution.h" #ifdef WINDOWS_ENABLED @@ -84,10 +85,10 @@ bool GodotSharpEditor::_create_project_solution() { return false; } - if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_CORE)) + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE)) return false; - if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR)) + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR)) return false; pr.step(TTR("Done")); @@ -278,10 +279,11 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { String about_text = String("C# support in Godot Engine is a brand new feature and a work in progress.\n") + "It is at the alpha stage and thus not suitable for use in production.\n\n" + - "As of Godot 3.0, C# support is not feature-complete and can crash in some situations. " + - "Bugs and usability issues will be addressed gradually over 3.0.x and 3.x releases.\n" + + "As of Godot 3.0, C# support is not feature-complete and may crash in some situations. " + + "Bugs and usability issues will be addressed gradually over 3.0.x and 3.x releases, " + + "including compatibility breaking changes as new features are implemented for a better overall C# experience.\n\n" + "The main missing feature is the ability to export games using C# assemblies - you will therefore be able to develop and run games in the editor, " + - "but not to share them as standalone binaries. This feature is of course high on the priority list and should be available in 3.0.1.\n\n" + + "but not to share them as standalone binaries yet. This feature is of course high on the priority list and should be available as soon as possible.\n\n" + "If you experience issues with this Mono build, please report them on Godot's issue tracker with details about your system, Mono version, IDE, etc.:\n\n" + " https://github.com/godotengine/godot/issues\n\n" + "Your critical feedback at this stage will play a great role in shaping the C# support in future releases, so thank you!"; @@ -315,6 +317,11 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { EditorSettings *ed_settings = EditorSettings::get_singleton(); EDITOR_DEF("mono/editor/external_editor", EDITOR_NONE); ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio Code")); + + // Export plugin + Ref<GodotSharpExport> godotsharp_export; + godotsharp_export.instance(); + EditorExport::get_singleton()->add_export_plugin(godotsharp_export); } GodotSharpEditor::~GodotSharpEditor() { diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h index 81c49aec30..66da814c8b 100644 --- a/modules/mono/editor/godotsharp_editor.h +++ b/modules/mono/editor/godotsharp_editor.h @@ -32,7 +32,6 @@ #define GODOTSHARP_EDITOR_H #include "godotsharp_builds.h" - #include "monodevelop_instance.h" class GodotSharpEditor : public Node { diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp new file mode 100644 index 0000000000..cd09e6516a --- /dev/null +++ b/modules/mono/editor/godotsharp_export.cpp @@ -0,0 +1,166 @@ +/*************************************************************************/ +/* godotsharp_export.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "godotsharp_export.h" + +#include "../csharp_script.h" +#include "../godotsharp_defs.h" +#include "../godotsharp_dirs.h" +#include "godotsharp_builds.h" + +void GodotSharpExport::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { + + if (p_type != CSharpLanguage::get_singleton()->get_type()) + return; + + ERR_FAIL_COND(p_path.get_extension() != CSharpLanguage::get_singleton()->get_extension()); + + // TODO what if the source file is not part of the game's C# project + + if (!GLOBAL_GET("mono/export/include_scripts_content")) { + // We don't want to include the source code on exported games + add_file(p_path, Vector<uint8_t>(), false); + skip(); + } +} + +void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags) { + + // TODO right now there is no way to stop the export process with an error + + ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized()); + ERR_FAIL_NULL(GDMono::get_singleton()->get_tools_domain()); + + String build_config = p_debug ? "Debug" : "Release"; + + ERR_FAIL_COND(!GodotSharpBuilds::build_project_blocking(build_config)); + + // Add API assemblies + + String core_api_dll_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(API_ASSEMBLY_NAME ".dll"); + ERR_FAIL_COND(!_add_assembly(core_api_dll_path, core_api_dll_path)); + + String editor_api_dll_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); + ERR_FAIL_COND(!_add_assembly(editor_api_dll_path, editor_api_dll_path)); + + // Add project assembly + + String project_dll_name = ProjectSettings::get_singleton()->get("application/config/name"); + if (project_dll_name.empty()) { + project_dll_name = "UnnamedProject"; + } + + String project_dll_src_path = GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(build_config).plus_file(project_dll_name + ".dll"); + String project_dll_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(project_dll_name + ".dll"); + ERR_FAIL_COND(!_add_assembly(project_dll_src_path, project_dll_dst_path)); + + // Add dependencies + + MonoDomain *prev_domain = mono_domain_get(); + MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.ProjectExportDomain"); + + ERR_FAIL_COND(!export_domain); + ERR_FAIL_COND(!mono_domain_set(export_domain, false)); + + Map<String, String> dependencies; + dependencies.insert("mscorlib", GDMono::get_singleton()->get_corlib_assembly()->get_path()); + + GDMonoAssembly *scripts_assembly = GDMonoAssembly::load_from(project_dll_name, project_dll_src_path, /* refonly: */ true); + + ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name); + ERR_FAIL_COND(!scripts_assembly); + + Error depend_error = _get_assembly_dependencies(scripts_assembly, dependencies); + + GDMono::get_singleton()->finalize_and_unload_domain(export_domain); + mono_domain_set(prev_domain, false); + + ERR_FAIL_COND(depend_error != OK); + + for (Map<String, String>::Element *E = dependencies.front(); E; E = E->next()) { + String depend_src_path = E->value(); + String depend_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(depend_src_path.get_file()); + ERR_FAIL_COND(!_add_assembly(depend_src_path, depend_dst_path)); + } +} + +bool GodotSharpExport::_add_assembly(const String &p_src_path, const String &p_dst_path) { + + FileAccessRef f = FileAccess::open(p_src_path, FileAccess::READ); + ERR_FAIL_COND_V(!f, false); + + Vector<uint8_t> data; + data.resize(f->get_len()); + f->get_buffer(data.ptrw(), data.size()); + + add_file(p_dst_path, data, false); + + return true; +} + +Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, Map<String, String> &r_dependencies) { + + MonoImage *image = p_assembly->get_image(); + + for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) { + MonoAssemblyName *ref_aname = aname_prealloc; + mono_assembly_get_assemblyref(image, i, ref_aname); + String ref_name = mono_assembly_name_get_name(ref_aname); + + if (ref_name == "mscorlib" || r_dependencies.find(ref_name)) + continue; + + GDMonoAssembly *ref_assembly = NULL; + if (!GDMono::get_singleton()->load_assembly(ref_name, ref_aname, &ref_assembly, /* refonly: */ true)) { + ERR_EXPLAIN("Cannot load refonly assembly: " + ref_name); + ERR_FAIL_V(ERR_CANT_RESOLVE); + } + + r_dependencies.insert(ref_name, ref_assembly->get_path()); + + Error err = _get_assembly_dependencies(ref_assembly, r_dependencies); + if (err != OK) + return err; + } + + return OK; +} + +GodotSharpExport::GodotSharpExport() { + // MonoAssemblyName is an incomplete type (internal to mono), so we can't allocate it ourselves. + // There isn't any api to allocate an empty one either, so we need to do it this way. + aname_prealloc = mono_assembly_name_new("whatever"); + mono_assembly_name_free(aname_prealloc); // "it does not frees the object itself, only the name members" (typo included) +} + +GodotSharpExport::~GodotSharpExport() { + if (aname_prealloc) + mono_free(aname_prealloc); +} diff --git a/modules/mono/editor/godotsharp_export.h b/modules/mono/editor/godotsharp_export.h new file mode 100644 index 0000000000..b38db9660c --- /dev/null +++ b/modules/mono/editor/godotsharp_export.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* godotsharp_export.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 GODOTSHARP_EXPORT_H +#define GODOTSHARP_EXPORT_H + +#include <mono/metadata/image.h> + +#include "editor/editor_export.h" + +#include "../mono_gd/gd_mono_header.h" + +class GodotSharpExport : public EditorExportPlugin { + + MonoAssemblyName *aname_prealloc; + + bool _add_assembly(const String &p_src_path, const String &p_dst_path); + + Error _get_assembly_dependencies(GDMonoAssembly *p_assembly, Map<String, String> &r_dependencies); + +protected: + virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); + virtual void _export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags); + +public: + GodotSharpExport(); + ~GodotSharpExport(); +}; + +#endif // GODOTSHARP_EXPORT_H diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index 20378a0162..32aec2a3b5 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -142,7 +142,7 @@ void MonoBottomPanel::_errors_toggled(bool p_pressed) { void MonoBottomPanel::_build_project_pressed() { - GodotSharpBuilds::get_singleton()->build_project_blocking(); + GodotSharpBuilds::get_singleton()->build_project_blocking("Tools"); MonoReloadNode::get_singleton()->restart_reload_timer(); CSharpLanguage::get_singleton()->reload_assemblies_if_needed(true); diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs index ea92b1641b..c6cdc069ef 100644 --- a/modules/mono/glue/cs_files/Basis.cs +++ b/modules/mono/glue/cs_files/Basis.cs @@ -452,9 +452,9 @@ namespace Godot public Basis(float xx, float xy, float xz, float yx, float yy, float yz, float zx, float zy, float zz) { - this.x = new Vector3(xx, xy, xz); - this.y = new Vector3(yx, yy, yz); - this.z = new Vector3(zx, zy, zz); + this.x = new Vector3(xx, yx, zx); + this.y = new Vector3(xy, yy, zy); + this.z = new Vector3(xz, yz, zz); } public static Basis operator *(Basis left, Basis right) diff --git a/modules/mono/glue/cs_files/StringExtensions.cs b/modules/mono/glue/cs_files/StringExtensions.cs index 5c3ceff97d..cbc337ab19 100644 --- a/modules/mono/glue/cs_files/StringExtensions.cs +++ b/modules/mono/glue/cs_files/StringExtensions.cs @@ -287,7 +287,7 @@ namespace Godot if (sep == -1) return @base; - return @base + rs.substr(0, sep); + return @base + rs.Substr(0, sep); } // <summary> @@ -478,7 +478,7 @@ namespace Godot // </summary> public static bool IsValidIpAddress(this string instance) { - string[] ip = instance.split("."); + string[] ip = instance.Split("."); if (ip.Length != 4) return false; @@ -489,7 +489,7 @@ namespace Godot if (!n.IsValidInteger()) return false; - int val = n.to_int(); + int val = n.ToInt(); if (val < 0 || val > 255) return false; } @@ -571,7 +571,7 @@ namespace Godot // <summary> // Do a simple case insensitive expression match, using ? and * wildcards (see [method expr_match]). // </summary> - public static bool matchn(this string instance, string expr) + public static bool Matchn(this string instance, string expr) { return instance.ExprMatch(expr, false); } @@ -830,7 +830,7 @@ namespace Godot // <summary> // Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",". // </summary> - public static string[] split(this string instance, string divisor, bool allow_empty = true) + public static string[] Split(this string instance, string divisor, bool allow_empty = true) { return instance.Split(new string[] { divisor }, StringSplitOptions.RemoveEmptyEntries); } @@ -838,7 +838,7 @@ namespace Godot // <summary> // Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",". // </summary> - public static float[] split_floats(this string instance, string divisor, bool allow_empty = true) + public static float[] SplitFloats(this string instance, string divisor, bool allow_empty = true) { List<float> ret = new List<float>(); int from = 0; @@ -872,7 +872,7 @@ namespace Godot // <summary> // Return a copy of the string stripped of any non-printable character at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively. // </summary> - public static string strip_edges(this string instance, bool left = true, bool right = true) + public static string StripEdges(this string instance, bool left = true, bool right = true) { if (left) { @@ -890,7 +890,7 @@ namespace Godot // <summary> // Return part of the string from the position [code]from[/code], with length [code]len[/code]. // </summary> - public static string substr(this string instance, int from, int len) + public static string Substr(this string instance, int from, int len) { return instance.Substring(from, len); } @@ -898,7 +898,7 @@ namespace Godot // <summary> // Convert the String (which is a character array) to PoolByteArray (which is an array of bytes). The conversion is speeded up in comparison to to_utf8() with the assumption that all the characters the String contains are only ASCII characters. // </summary> - public static byte[] to_ascii(this string instance) + public static byte[] ToAscii(this string instance) { return Encoding.ASCII.GetBytes(instance); } @@ -906,7 +906,7 @@ namespace Godot // <summary> // Convert a string, containing a decimal number, into a [code]float[/code]. // </summary> - public static float to_float(this string instance) + public static float ToFloat(this string instance) { return float.Parse(instance); } @@ -914,7 +914,7 @@ namespace Godot // <summary> // Convert a string, containing an integer number, into an [code]int[/code]. // </summary> - public static int to_int(this string instance) + public static int ToInt(this string instance) { return int.Parse(instance); } @@ -922,7 +922,7 @@ namespace Godot // <summary> // Return the string converted to lowercase. // </summary> - public static string to_lower(this string instance) + public static string ToLower(this string instance) { return instance.ToLower(); } @@ -930,7 +930,7 @@ namespace Godot // <summary> // Return the string converted to uppercase. // </summary> - public static string to_upper(this string instance) + public static string ToUpper(this string instance) { return instance.ToUpper(); } @@ -938,7 +938,7 @@ namespace Godot // <summary> // Convert the String (which is an array of characters) to PoolByteArray (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii(). // </summary> - public static byte[] to_utf8(this string instance) + public static byte[] ToUtf8(this string instance) { return Encoding.UTF8.GetBytes(instance); } @@ -946,7 +946,7 @@ namespace Godot // <summary> // Return a copy of the string with special characters escaped using the XML standard. // </summary> - public static string xml_escape(this string instance) + public static string XmlEscape(this string instance) { return SecurityElement.Escape(instance); } @@ -954,7 +954,7 @@ namespace Godot // <summary> // Return a copy of the string with escaped characters replaced by their meanings according to the XML standard. // </summary> - public static string xml_unescape(this string instance) + public static string XmlUnescape(this string instance) { return SecurityElement.FromString(instance).Text; } diff --git a/modules/mono/glue/cs_files/Transform.cs b/modules/mono/glue/cs_files/Transform.cs index 5214100d36..9853721f98 100644 --- a/modules/mono/glue/cs_files/Transform.cs +++ b/modules/mono/glue/cs_files/Transform.cs @@ -24,7 +24,7 @@ namespace Godot public Transform LookingAt(Vector3 target, Vector3 up) { Transform t = this; - t.set_look_at(origin, target, up); + t.SetLookAt(origin, target, up); return t; } @@ -43,7 +43,7 @@ namespace Godot return new Transform(basis.Scaled(scale), origin * scale); } - public void set_look_at(Vector3 eye, Vector3 target, Vector3 up) + public void SetLookAt(Vector3 eye, Vector3 target, Vector3 up) { // Make rotation matrix // Z vector diff --git a/modules/mono/glue/cs_files/VERSION.txt b/modules/mono/glue/cs_files/VERSION.txt new file mode 100755 index 0000000000..0cfbf08886 --- /dev/null +++ b/modules/mono/glue/cs_files/VERSION.txt @@ -0,0 +1 @@ +2 diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h index 4c26c3e6bd..f604464e8f 100644 --- a/modules/mono/godotsharp_defs.h +++ b/modules/mono/godotsharp_defs.h @@ -39,4 +39,7 @@ #define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor" #define EDITOR_TOOLS_ASSEMBLY_NAME "GodotSharpTools" +#define BINDINGS_CLASS_NATIVECALLS "NativeCalls" +#define BINDINGS_CLASS_NATIVECALLS_EDITOR "EditorNativeCalls" + #endif // GODOTSHARP_DEFS_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index f5febd415b..0646580eaa 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -42,11 +42,15 @@ #include "project_settings.h" #include "../csharp_script.h" +#include "../godotsharp_dirs.h" #include "../utils/path_utils.h" +#include "gd_mono_class.h" +#include "gd_mono_marshal.h" #include "gd_mono_utils.h" #ifdef TOOLS_ENABLED #include "../editor/godotsharp_editor.h" +#include "main/main.h" #endif void gdmono_unhandled_exception_hook(MonoObject *exc, void *user_data) { @@ -70,7 +74,31 @@ void gdmono_MonoPrintCallback(const char *string, mono_bool is_stdout) { GDMono *GDMono::singleton = NULL; +namespace { + +void setup_runtime_main_args() { + CharString execpath = OS::get_singleton()->get_executable_path().utf8(); + + List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); + + List<CharString> cmdline_args_utf8; + Vector<char *> main_args; + main_args.resize(cmdline_args.size() + 1); + + main_args[0] = execpath.ptrw(); + + int i = 1; + for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) { + CharString &stored = cmdline_args_utf8.push_back(E->get().utf8())->get(); + main_args[i] = stored.ptrw(); + i++; + } + + mono_runtime_set_main_args(main_args.size(), main_args.ptrw()); +} + #ifdef DEBUG_ENABLED + static bool _wait_for_debugger_msecs(uint32_t p_msecs) { do { @@ -92,24 +120,7 @@ static bool _wait_for_debugger_msecs(uint32_t p_msecs) { return mono_is_debugger_attached(); } -#endif - -#ifdef TOOLS_ENABLED -// temporary workaround. should be provided from Main::setup/setup2 instead -bool _is_project_manager_requested() { - - List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); - for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) { - const String &arg = E->get(); - if (arg == "-p" || arg == "--project-manager") - return true; - } - - return false; -} -#endif -#ifdef DEBUG_ENABLED void gdmono_debug_init() { mono_debug_init(MONO_DEBUG_FORMAT_MONO); @@ -121,7 +132,7 @@ void gdmono_debug_init() { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint() || ProjectSettings::get_singleton()->get_resource_path().empty() || - _is_project_manager_requested()) { + Main::is_project_manager()) { return; } #endif @@ -136,8 +147,11 @@ void gdmono_debug_init() { }; mono_jit_parse_options(2, (char **)options); } + #endif +} // namespace + void GDMono::initialize() { ERR_FAIL_NULL(Engine::get_singleton()); @@ -190,6 +204,8 @@ void GDMono::initialize() { GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread()); + setup_runtime_main_args(); // Required for System.Environment.GetCommandLineArgs + runtime_initialized = true; OS::get_singleton()->print("Mono: Runtime initialized\n"); @@ -222,7 +238,46 @@ void GDMono::initialize() { _register_internal_calls(); // The following assemblies are not required at initialization - _load_all_script_assemblies(); +#ifndef MONO_GLUE_DISABLED + if (_load_api_assemblies()) { + if (!core_api_assembly_out_of_sync && !editor_api_assembly_out_of_sync && GDMonoUtils::mono_cache.godot_api_cache_updated) { + // Everything is fine with the api assemblies, load the project assembly + _load_project_assembly(); + } else { +#ifdef TOOLS_ENABLED + // The assembly was successfuly loaded, but the full api could not be cached. + // This is most likely an outdated assembly loaded because of an invalid version in the metadata, + // so we invalidate the version in the metadata and unload the script domain. + + if (core_api_assembly_out_of_sync) { + ERR_PRINT("The loaded Core API assembly is out of sync"); + metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); + } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { + ERR_PRINT("The loaded Core API assembly is in sync, but the cache update failed"); + metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); + } + + if (editor_api_assembly_out_of_sync) { + ERR_PRINT("The loaded Editor API assembly is out of sync"); + metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true); + } + + OS::get_singleton()->print("Mono: Proceeding to unload scripts domain because of invalid API assemblies\n"); + + Error err = _unload_scripts_domain(); + if (err != OK) { + WARN_PRINT("Mono: Failed to unload scripts domain"); + } +#else + ERR_PRINT("The loaded API assembly is invalid"); + CRASH_NOW(); +#endif + } + } +#else + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Mono: Glue disabled, ignoring script assemblies\n"); +#endif mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL); @@ -233,7 +288,11 @@ void GDMono::initialize() { namespace GodotSharpBindings { uint64_t get_core_api_hash(); +#ifdef TOOLS_ENABLED uint64_t get_editor_api_hash(); +#endif // TOOLS_ENABLED +uint32_t get_bindings_version(); +uint32_t get_cs_glue_version(); void register_generated_icalls(); } // namespace GodotSharpBindings @@ -285,43 +344,84 @@ GDMonoAssembly **GDMono::get_loaded_assembly(const String &p_name) { return assemblies[domain_id].getptr(p_name); } -bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) { +bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) { + + CRASH_COND(!r_assembly); + + MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); + bool result = load_assembly(p_name, aname, r_assembly, p_refonly); + mono_assembly_name_free(aname); + mono_free(aname); + + return result; +} + +bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { CRASH_COND(!r_assembly); if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print((String() + "Mono: Loading assembly " + p_name + "...\n").utf8()); + OS::get_singleton()->print((String() + "Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "...\n").utf8()); MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); - MonoAssembly *assembly = mono_assembly_load_full(aname, NULL, &status, false); - mono_assembly_name_free(aname); + MonoAssembly *assembly = mono_assembly_load_full(p_aname, NULL, &status, p_refonly); if (!assembly) return false; + ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); + uint32_t domain_id = mono_domain_get_id(mono_domain_get()); GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name); - ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); ERR_FAIL_COND_V(stored_assembly == NULL, false); - ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false); + *r_assembly = *stored_assembly; if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print(String("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8()); + OS::get_singleton()->print(String("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8()); return true; } +APIAssembly::Version APIAssembly::Version::get_from_loaded_assembly(GDMonoAssembly *p_api_assembly, APIAssembly::Type p_api_type) { + APIAssembly::Version api_assembly_version; + + const char *nativecalls_name = p_api_type == APIAssembly::API_CORE ? + BINDINGS_CLASS_NATIVECALLS : + BINDINGS_CLASS_NATIVECALLS_EDITOR; + + GDMonoClass *nativecalls_klass = p_api_assembly->get_class(BINDINGS_NAMESPACE, nativecalls_name); + + if (nativecalls_klass) { + GDMonoField *api_hash_field = nativecalls_klass->get_field("godot_api_hash"); + if (api_hash_field) + api_assembly_version.godot_api_hash = GDMonoMarshal::unbox<uint64_t>(api_hash_field->get_value(NULL)); + + GDMonoField *binds_ver_field = nativecalls_klass->get_field("bindings_version"); + if (binds_ver_field) + api_assembly_version.bindings_version = GDMonoMarshal::unbox<uint32_t>(binds_ver_field->get_value(NULL)); + + GDMonoField *cs_glue_ver_field = nativecalls_klass->get_field("cs_glue_version"); + if (cs_glue_ver_field) + api_assembly_version.cs_glue_version = GDMonoMarshal::unbox<uint32_t>(cs_glue_ver_field->get_value(NULL)); + } + + return api_assembly_version; +} + +String APIAssembly::to_string(APIAssembly::Type p_type) { + return p_type == APIAssembly::API_CORE ? "API_CORE" : "API_EDITOR"; +} + bool GDMono::_load_corlib_assembly() { if (corlib_assembly) return true; - bool success = _load_assembly("mscorlib", &corlib_assembly); + bool success = load_assembly("mscorlib", &corlib_assembly); if (success) GDMonoUtils::update_corlib_cache(); @@ -331,13 +431,25 @@ bool GDMono::_load_corlib_assembly() { bool GDMono::_load_core_api_assembly() { - if (api_assembly) + if (core_api_assembly) return true; - bool success = _load_assembly(API_ASSEMBLY_NAME, &api_assembly); +#ifdef TOOLS_ENABLED + if (metadata_is_api_assembly_invalidated(APIAssembly::API_CORE)) + return false; +#endif - if (success) + bool success = load_assembly(API_ASSEMBLY_NAME, &core_api_assembly); + + if (success) { +#ifndef MONO_GLUE_DISABLED + APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(core_api_assembly, APIAssembly::API_CORE); + core_api_assembly_out_of_sync = GodotSharpBindings::get_core_api_hash() != api_assembly_ver.godot_api_hash || + GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version || + GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version; +#endif GDMonoUtils::update_godot_api_cache(); + } return success; } @@ -348,7 +460,23 @@ bool GDMono::_load_editor_api_assembly() { if (editor_api_assembly) return true; - return _load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly); +#ifdef TOOLS_ENABLED + if (metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) + return false; +#endif + + bool success = load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly); + + if (success) { +#ifndef MONO_GLUE_DISABLED + APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(editor_api_assembly, APIAssembly::API_EDITOR); + editor_api_assembly_out_of_sync = GodotSharpBindings::get_editor_api_hash() != api_assembly_ver.godot_api_hash || + GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version || + GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version; +#endif + } + + return success; } #endif @@ -360,7 +488,7 @@ bool GDMono::_load_editor_tools_assembly() { _GDMONO_SCOPE_DOMAIN_(tools_domain) - return _load_assembly(EDITOR_TOOLS_ASSEMBLY_NAME, &editor_tools_assembly); + return load_assembly(EDITOR_TOOLS_ASSEMBLY_NAME, &editor_tools_assembly); } #endif @@ -374,17 +502,20 @@ bool GDMono::_load_project_assembly() { name = "UnnamedProject"; } - bool success = _load_assembly(name, &project_assembly); + bool success = load_assembly(name, &project_assembly); - if (success) + if (success) { mono_assembly_set_main(project_assembly->get_assembly()); + } else { + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->printerr("Mono: Failed to load project assembly\n"); + } return success; } -bool GDMono::_load_all_script_assemblies() { +bool GDMono::_load_api_assemblies() { -#ifndef MONO_GLUE_DISABLED if (!_load_core_api_assembly()) { if (OS::get_singleton()->is_stdout_verbose()) OS::get_singleton()->printerr("Mono: Failed to load Core API assembly\n"); @@ -399,20 +530,72 @@ bool GDMono::_load_all_script_assemblies() { #endif } - if (!_load_project_assembly()) { - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->printerr("Mono: Failed to load project assembly\n"); - return false; + return true; +} + +#ifdef TOOLS_ENABLED +String GDMono::_get_api_assembly_metadata_path() { + + return GodotSharpDirs::get_res_metadata_dir().plus_file("api_assemblies.cfg"); +} + +void GDMono::metadata_set_api_assembly_invalidated(APIAssembly::Type p_api_type, bool p_invalidated) { + + String section = APIAssembly::to_string(p_api_type); + String path = _get_api_assembly_metadata_path(); + + Ref<ConfigFile> metadata; + metadata.instance(); + metadata->load(path); + + metadata->set_value(section, "invalidated", p_invalidated); + + String assembly_path = GodotSharpDirs::get_res_assemblies_dir() + .plus_file(p_api_type == APIAssembly::API_CORE ? + API_ASSEMBLY_NAME ".dll" : + EDITOR_API_ASSEMBLY_NAME ".dll"); + + ERR_FAIL_COND(!FileAccess::exists(assembly_path)); + + uint64_t modified_time = FileAccess::get_modified_time(assembly_path); + + metadata->set_value(section, "invalidated_asm_modified_time", String::num_uint64(modified_time)); + + String dir = path.get_base_dir(); + if (!DirAccess::exists(dir)) { + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND(!da); + Error err = da->make_dir_recursive(ProjectSettings::get_singleton()->globalize_path(dir)); + ERR_FAIL_COND(err != OK); } - return true; -#else - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print("Mono: Glue disbled, ignoring script assemblies\n"); + Error save_err = metadata->save(path); + ERR_FAIL_COND(save_err != OK); +} - return true; -#endif +bool GDMono::metadata_is_api_assembly_invalidated(APIAssembly::Type p_api_type) { + + String section = APIAssembly::to_string(p_api_type); + + Ref<ConfigFile> metadata; + metadata.instance(); + metadata->load(_get_api_assembly_metadata_path()); + + String assembly_path = GodotSharpDirs::get_res_assemblies_dir() + .plus_file(p_api_type == APIAssembly::API_CORE ? + API_ASSEMBLY_NAME ".dll" : + EDITOR_API_ASSEMBLY_NAME ".dll"); + + if (!FileAccess::exists(assembly_path)) + return false; + + uint64_t modified_time = FileAccess::get_modified_time(assembly_path); + + uint64_t stored_modified_time = metadata->get_value(section, "invalidated_asm_modified_time", 0); + + return metadata->get_value(section, "invalidated", false) && modified_time <= stored_modified_time; } +#endif Error GDMono::_load_scripts_domain() { @@ -455,12 +638,15 @@ Error GDMono::_unload_scripts_domain() { _domain_assemblies_cleanup(mono_domain_get_id(scripts_domain)); - api_assembly = NULL; + core_api_assembly = NULL; project_assembly = NULL; #ifdef TOOLS_ENABLED editor_api_assembly = NULL; #endif + core_api_assembly_out_of_sync = false; + editor_api_assembly_out_of_sync = false; + MonoDomain *domain = scripts_domain; scripts_domain = NULL; @@ -515,16 +701,80 @@ Error GDMono::reload_scripts_domain() { return err; } - if (!_load_all_script_assemblies()) { - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->printerr("Mono: Failed to load script assemblies\n"); +#ifndef MONO_GLUE_DISABLED + if (!_load_api_assemblies()) { return ERR_CANT_OPEN; } + if (!core_api_assembly_out_of_sync && !editor_api_assembly_out_of_sync && GDMonoUtils::mono_cache.godot_api_cache_updated) { + // Everything is fine with the api assemblies, load the project assembly + _load_project_assembly(); + } else { + // The assembly was successfuly loaded, but the full api could not be cached. + // This is most likely an outdated assembly loaded because of an invalid version in the metadata, + // so we invalidate the version in the metadata and unload the script domain. + + if (core_api_assembly_out_of_sync) { + metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); + } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { + ERR_PRINT("Core API assembly is in sync, but the cache update failed"); + metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); + } + + if (editor_api_assembly_out_of_sync) { + metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true); + } + + Error err = _unload_scripts_domain(); + if (err != OK) { + WARN_PRINT("Mono: Failed to unload scripts domain"); + } + + return ERR_CANT_RESOLVE; + } + + if (!_load_project_assembly()) + return ERR_CANT_OPEN; +#else + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Mono: Glue disabled, ignoring script assemblies\n"); +#endif + return OK; } #endif +Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { + + CRASH_COND(p_domain == NULL); + + String domain_name = mono_domain_get_friendly_name(p_domain); + + if (OS::get_singleton()->is_stdout_verbose()) { + OS::get_singleton()->print(String("Mono: Unloading domain `" + domain_name + "`...\n").utf8()); + } + + if (mono_domain_get() != root_domain) + mono_domain_set(root_domain, true); + + mono_gc_collect(mono_gc_max_generation()); + mono_domain_finalize(p_domain, 2000); + mono_gc_collect(mono_gc_max_generation()); + + _domain_assemblies_cleanup(mono_domain_get_id(p_domain)); + + MonoObject *ex = NULL; + mono_domain_try_unload(p_domain, &ex); + + if (ex) { + ERR_PRINTS("Exception thrown when unloading domain `" + domain_name + "`:"); + mono_print_unhandled_exception(ex); + return FAILED; + } + + return OK; +} + GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { MonoImage *image = mono_class_get_image(p_raw_class); @@ -576,8 +826,11 @@ GDMono::GDMono() { tools_domain = NULL; #endif + core_api_assembly_out_of_sync = false; + editor_api_assembly_out_of_sync = false; + corlib_assembly = NULL; - api_assembly = NULL; + core_api_assembly = NULL; project_assembly = NULL; #ifdef TOOLS_ENABLED editor_api_assembly = NULL; diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index 67251778c6..5e01152870 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -31,6 +31,8 @@ #ifndef GD_MONO_H #define GD_MONO_H +#include "core/io/config_file.h" + #include "../godotsharp_defs.h" #include "gd_mono_assembly.h" #include "gd_mono_log.h" @@ -39,6 +41,43 @@ #include "../utils/mono_reg_utils.h" #endif +namespace APIAssembly { +enum Type { + API_CORE, + API_EDITOR +}; + +struct Version { + uint64_t godot_api_hash; + uint32_t bindings_version; + uint32_t cs_glue_version; + + bool operator==(const Version &p_other) const { + return godot_api_hash == p_other.godot_api_hash && + bindings_version == p_other.bindings_version && + cs_glue_version == p_other.cs_glue_version; + } + + Version() : + godot_api_hash(0), + bindings_version(0), + cs_glue_version(0) { + } + + Version(uint64_t p_godot_api_hash, + uint32_t p_bindings_version, + uint32_t p_cs_glue_version) : + godot_api_hash(p_godot_api_hash), + bindings_version(p_bindings_version), + cs_glue_version(p_cs_glue_version) { + } + + static Version get_from_loaded_assembly(GDMonoAssembly *p_api_assembly, Type p_api_type); +}; + +String to_string(Type p_type); +} // namespace APIAssembly + #define SCRIPTS_DOMAIN GDMono::get_singleton()->get_scripts_domain() #ifdef TOOLS_ENABLED #define TOOLS_DOMAIN GDMono::get_singleton()->get_tools_domain() @@ -55,8 +94,11 @@ class GDMono { MonoDomain *tools_domain; #endif + bool core_api_assembly_out_of_sync; + bool editor_api_assembly_out_of_sync; + GDMonoAssembly *corlib_assembly; - GDMonoAssembly *api_assembly; + GDMonoAssembly *core_api_assembly; GDMonoAssembly *project_assembly; #ifdef TOOLS_ENABLED GDMonoAssembly *editor_api_assembly; @@ -75,7 +117,11 @@ class GDMono { #endif bool _load_project_assembly(); - bool _load_all_script_assemblies(); + bool _load_api_assemblies(); + +#ifdef TOOLS_ENABLED + String _get_api_assembly_metadata_path(); +#endif void _register_internal_calls(); @@ -94,8 +140,6 @@ class GDMono { void _initialize_and_check_api_hashes(); #endif - bool _load_assembly(const String &p_name, GDMonoAssembly **r_assembly); - GDMonoLog *gdmono_log; #ifdef WINDOWS_ENABLED @@ -113,6 +157,11 @@ public: #endif #endif +#ifdef TOOLS_ENABLED + void metadata_set_api_assembly_invalidated(APIAssembly::Type p_api_type, bool p_invalidated); + bool metadata_is_api_assembly_invalidated(APIAssembly::Type p_api_type); +#endif + static GDMono *get_singleton() { return singleton; } // Do not use these, unless you know what you're doing @@ -128,7 +177,7 @@ public: #endif _FORCE_INLINE_ GDMonoAssembly *get_corlib_assembly() const { return corlib_assembly; } - _FORCE_INLINE_ GDMonoAssembly *get_api_assembly() const { return api_assembly; } + _FORCE_INLINE_ GDMonoAssembly *get_core_api_assembly() const { return core_api_assembly; } _FORCE_INLINE_ GDMonoAssembly *get_project_assembly() const { return project_assembly; } #ifdef TOOLS_ENABLED _FORCE_INLINE_ GDMonoAssembly *get_editor_api_assembly() const { return editor_api_assembly; } @@ -145,6 +194,10 @@ public: Error reload_scripts_domain(); #endif + bool load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly = false); + bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly = false); + Error finalize_and_unload_domain(MonoDomain *p_domain); + void initialize(); GDMono(); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index ef39b8549d..d062d56dcf 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -43,7 +43,23 @@ bool GDMonoAssembly::no_search = false; Vector<String> GDMonoAssembly::search_dirs; -MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data) { +MonoAssembly *GDMonoAssembly::assembly_search_hook(MonoAssemblyName *aname, void *user_data) { + return GDMonoAssembly::_search_hook(aname, user_data, false); +} + +MonoAssembly *GDMonoAssembly::assembly_refonly_search_hook(MonoAssemblyName *aname, void *user_data) { + return GDMonoAssembly::_search_hook(aname, user_data, true); +} + +MonoAssembly *GDMonoAssembly::assembly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) { + return GDMonoAssembly::_preload_hook(aname, assemblies_path, user_data, false); +} + +MonoAssembly *GDMonoAssembly::assembly_refonly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) { + return GDMonoAssembly::_preload_hook(aname, assemblies_path, user_data, true); +} + +MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly) { (void)user_data; // UNUSED @@ -60,7 +76,7 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d no_search = true; // Avoid the recursion madness String path; - MonoAssembly *res = NULL; + GDMonoAssembly *res = NULL; for (int i = 0; i < search_dirs.size(); i++) { const String &search_dir = search_dirs[i]; @@ -68,44 +84,49 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d if (has_extension) { path = search_dir.plus_file(name); if (FileAccess::exists(path)) { - res = _load_assembly_from(name.get_basename(), path); - break; + res = _load_assembly_from(name.get_basename(), path, refonly); + if (res != NULL) + break; } } else { path = search_dir.plus_file(name + ".dll"); if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path); - break; + res = _load_assembly_from(name, path, refonly); + if (res != NULL) + break; } path = search_dir.plus_file(name + ".exe"); if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path); - break; + res = _load_assembly_from(name, path, refonly); + if (res != NULL) + break; } } } no_search = false; - return res; + return res ? res->get_assembly() : NULL; } -MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) { +MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly) { (void)user_data; // UNUSED if (search_dirs.empty()) { -#ifdef TOOLS_DOMAIN search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir()); -#endif search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir()); search_dirs.push_back(OS::get_singleton()->get_resource_dir()); search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir()); +#ifdef GD_MONO_EDITOR_ASSEMBLIES_DIR + search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir().plus_file(_MKSTR(GD_MONO_EDITOR_ASSEMBLIES_DIR)).simplify_path()); +#endif const char *rootdir = mono_assembly_getrootdir(); if (rootdir) { search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5")); + search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5").plus_file("Facades")); } if (assemblies_path) { @@ -121,10 +142,11 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse if (has_extension ? name == "mscorlib.dll" : name == "mscorlib") { GDMonoAssembly **stored_assembly = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); - if (stored_assembly) return (*stored_assembly)->get_assembly(); + if (stored_assembly) + return (*stored_assembly)->get_assembly(); String path; - MonoAssembly *res = NULL; + GDMonoAssembly *res = NULL; for (int i = 0; i < search_dirs.size(); i++) { const String &search_dir = search_dirs[i]; @@ -132,53 +154,57 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse if (has_extension) { path = search_dir.plus_file(name); if (FileAccess::exists(path)) { - res = _load_assembly_from(name.get_basename(), path); - break; + res = _load_assembly_from(name.get_basename(), path, refonly); + if (res != NULL) + break; } } else { path = search_dir.plus_file(name + ".dll"); if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path); - break; + res = _load_assembly_from(name, path, refonly); + if (res != NULL) + break; } } } - if (res) return res; + return res ? res->get_assembly() : NULL; } return NULL; } -MonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path) { +GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly) { GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path)); - MonoDomain *domain = mono_domain_get(); - - Error err = assembly->load(domain); + Error err = assembly->load(p_refonly); if (err != OK) { memdelete(assembly); ERR_FAIL_V(NULL); } + MonoDomain *domain = mono_domain_get(); GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, assembly); - return assembly->get_assembly(); + return assembly; } void GDMonoAssembly::initialize() { - // TODO refonly as well? - mono_install_assembly_preload_hook(&GDMonoAssembly::_preload_hook, NULL); - mono_install_assembly_search_hook(&GDMonoAssembly::_search_hook, NULL); + mono_install_assembly_search_hook(&assembly_search_hook, NULL); + mono_install_assembly_refonly_search_hook(&assembly_refonly_search_hook, NULL); + mono_install_assembly_preload_hook(&assembly_preload_hook, NULL); + mono_install_assembly_refonly_preload_hook(&assembly_refonly_preload_hook, NULL); } -Error GDMonoAssembly::load(MonoDomain *p_domain) { +Error GDMonoAssembly::load(bool p_refonly) { ERR_FAIL_COND_V(loaded, ERR_FILE_ALREADY_IN_USE); + refonly = p_refonly; + uint64_t last_modified_time = FileAccess::get_modified_time(path); Vector<uint8_t> data = FileAccess::get_file_as_array(path); @@ -186,14 +212,15 @@ Error GDMonoAssembly::load(MonoDomain *p_domain) { String image_filename(path); - MonoImageOpenStatus status; + MonoImageOpenStatus status = MONO_IMAGE_OK; image = mono_image_open_from_data_with_name( (char *)&data[0], data.size(), - true, &status, false, + true, &status, refonly, image_filename.utf8().get_data()); - ERR_FAIL_COND_V(status != MONO_IMAGE_OK || image == NULL, ERR_FILE_CANT_OPEN); + ERR_FAIL_COND_V(status != MONO_IMAGE_OK, ERR_FILE_CANT_OPEN); + ERR_FAIL_NULL_V(image, ERR_FILE_CANT_OPEN); #ifdef DEBUG_ENABLED String pdb_path(path + ".pdb"); @@ -213,15 +240,10 @@ no_pdb: #endif - assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, false); + assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, refonly); ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN); - if (p_domain && mono_image_get_entry_point(image)) { - // TODO should this be removed? do we want to call main? what other effects does this have? - mono_jit_exec(p_domain, assembly, 0, NULL); - } - loaded = true; modified_time = last_modified_time; @@ -373,12 +395,26 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) return match; } +GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_path, bool p_refonly) { + + GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); + if (loaded_asm) + return *loaded_asm; + + no_search = true; + GDMonoAssembly *res = _load_assembly_from(p_name, p_path, p_refonly); + no_search = false; + + return res; +} + GDMonoAssembly::GDMonoAssembly(const String &p_name, const String &p_path) { loaded = false; gdobject_class_cache_updated = false; name = p_name; path = p_path; + refonly = false; modified_time = 0; assembly = NULL; image = NULL; diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 8a5fa19626..5cf744a5a2 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -71,6 +71,7 @@ class GDMonoAssembly { MonoAssembly *assembly; MonoImage *image; + bool refonly; bool loaded; String name; @@ -90,19 +91,25 @@ class GDMonoAssembly { static bool no_search; static Vector<String> search_dirs; - static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data); - static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data); + static MonoAssembly *assembly_search_hook(MonoAssemblyName *aname, void *user_data); + static MonoAssembly *assembly_refonly_search_hook(MonoAssemblyName *aname, void *user_data); + static MonoAssembly *assembly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data); + static MonoAssembly *assembly_refonly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data); - static MonoAssembly *_load_assembly_from(const String &p_name, const String &p_path); + static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly); + static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly); + + static GDMonoAssembly *_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly); friend class GDMono; static void initialize(); public: - Error load(MonoDomain *p_domain); + Error load(bool p_refonly); Error wrapper_for_image(MonoImage *p_image); void unload(); + _FORCE_INLINE_ bool is_refonly() const { return refonly; } _FORCE_INLINE_ bool is_loaded() const { return loaded; } _FORCE_INLINE_ MonoImage *get_image() const { return image; } _FORCE_INLINE_ MonoAssembly *get_assembly() const { return assembly; } @@ -115,6 +122,8 @@ public: GDMonoClass *get_object_derived_class(const StringName &p_class); + static GDMonoAssembly *load_from(const String &p_name, const String &p_path, bool p_refonly); + GDMonoAssembly(const String &p_name, const String &p_path = String()); ~GDMonoAssembly(); }; diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 6572408ab5..4e28622adb 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -195,13 +195,13 @@ Dictionary mono_object_to_Dictionary(MonoObject *p_dict); // Transform #define MARSHALLED_OUT_Transform(m_in, m_out) real_t m_out[12] = { \ - m_in.basis[0].x, m_in.basis[0].y, m_in.basis[0].z, \ - m_in.basis[1].x, m_in.basis[1].y, m_in.basis[1].z, \ - m_in.basis[2].x, m_in.basis[2].y, m_in.basis[2].z, \ + m_in.basis[0].x, m_in.basis[1].x, m_in.basis[2].x, \ + m_in.basis[0].y, m_in.basis[1].y, m_in.basis[2].y, \ + m_in.basis[0].z, m_in.basis[1].z, m_in.basis[2].z, \ m_in.origin.x, m_in.origin.y, m_in.origin.z \ }; #define MARSHALLED_IN_Transform(m_in, m_out) Transform m_out( \ - Basis(m_in[0], m_in[1], m_in[2], m_in[3], m_in[4], m_in[5], m_in[6], m_in[7], m_in[8]), \ + Basis(m_in[0], m_in[3], m_in[6], m_in[1], m_in[4], m_in[7], m_in[2], m_in[5], m_in[8]), \ Vector3(m_in[9], m_in[10], m_in[11])); // AABB diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp index df0985f6ac..ad52904945 100644 --- a/modules/mono/mono_gd/gd_mono_method.cpp +++ b/modules/mono/mono_gd/gd_mono_method.cpp @@ -230,10 +230,13 @@ String GDMonoMethod::get_signature_desc(bool p_namespaces) const { } void GDMonoMethod::get_parameter_names(Vector<StringName> &names) const { - const char *_names[params_count]; - mono_method_get_param_names(mono_method, _names); - for (int i = 0; i < params_count; ++i) { - names.push_back(StringName(_names[i])); + if (params_count > 0) { + const char **_names = memnew_arr(const char *, params_count); + mono_method_get_param_names(mono_method, _names); + for (int i = 0; i < params_count; ++i) { + names.push_back(StringName(_names[i])); + } + memdelete_arr(_names); } } diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 42e307cf08..db136a1313 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -143,7 +143,7 @@ void MonoCache::cleanup() { godot_api_cache_updated = false; } -#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class)) +#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class)) void update_corlib_cache() { @@ -245,7 +245,7 @@ void update_godot_api_cache() { mono_runtime_object_init(task_scheduler); mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler); - mono_cache.corlib_cache_updated = true; + mono_cache.godot_api_cache_updated = true; } void clear_cache() { @@ -305,7 +305,7 @@ GDMonoClass *type_get_proxy_class(const StringName &p_type) { if (class_name[0] == '_') class_name = class_name.substr(1, class_name.length()); - GDMonoClass *klass = GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); + GDMonoClass *klass = GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); #ifdef TOOLS_ENABLED if (!klass) { @@ -321,7 +321,7 @@ GDMonoClass *get_class_native_base(GDMonoClass *p_class) { do { const GDMonoAssembly *assembly = klass->get_assembly(); - if (assembly == GDMono::get_singleton()->get_api_assembly()) + if (assembly == GDMono::get_singleton()->get_core_api_assembly()) return klass; #ifdef TOOLS_ENABLED if (assembly == GDMono::get_singleton()->get_editor_api_assembly()) @@ -420,37 +420,56 @@ void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution) { if (!ScriptDebugger::get_singleton()) return; - GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); - MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); + ScriptLanguage::StackInfo separator; + separator.file = ""; + separator.func = "--- " + RTR("End of inner exception stack trace") + " ---"; + separator.line = 0; + + Vector<ScriptLanguage::StackInfo> si; + String exc_msg = ""; + + while (p_exc != NULL) { + GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); + MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); - MonoBoolean need_file_info = true; - void *ctor_args[2] = { p_exc, &need_file_info }; + MonoBoolean need_file_info = true; + void *ctor_args[2] = { p_exc, &need_file_info }; - MonoObject *unexpected_exc = NULL; - CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc); + MonoObject *unexpected_exc = NULL; + CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc); - if (unexpected_exc != NULL) { - mono_print_unhandled_exception(unexpected_exc); + if (unexpected_exc != NULL) { + mono_print_unhandled_exception(unexpected_exc); - if (p_recursion_caution) { - // Called from CSharpLanguage::get_current_stack_info, - // so printing an error here could result in endless recursion - OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed"); - return; - } else { - ERR_FAIL(); + if (p_recursion_caution) { + // Called from CSharpLanguage::get_current_stack_info, + // so printing an error here could result in endless recursion + OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed"); + return; + } else { + ERR_FAIL(); + } } - } - Vector<ScriptLanguage::StackInfo> si; - if (stack_trace != NULL && !p_recursion_caution) - si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); + Vector<ScriptLanguage::StackInfo> _si; + if (stack_trace != NULL && !p_recursion_caution) { + _si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); + for (int i = _si.size() - 1; i >= 0; i--) + si.insert(0, _si[i]); + } + + exc_msg += (exc_msg.length() > 0 ? " ---> " : "") + GDMonoUtils::get_exception_name_and_message(p_exc); + + GDMonoProperty *p_prop = GDMono::get_singleton()->get_class(mono_object_get_class(p_exc))->get_property("InnerException"); + p_exc = p_prop != NULL ? p_prop->get_value(p_exc) : NULL; + if (p_exc != NULL) + si.insert(0, separator); + } String file = si.size() ? si[0].file : __FILE__; String func = si.size() ? si[0].func : FUNCTION_STR; int line = si.size() ? si[0].line : __LINE__; String error_msg = "Unhandled exception"; - String exc_msg = GDMonoUtils::get_exception_name_and_message(p_exc); ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si); #endif diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml index 2cf80acd28..75e8903ff8 100644 --- a/modules/regex/doc_classes/RegEx.xml +++ b/modules/regex/doc_classes/RegEx.xml @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RegEx" inherits="Reference" category="Core" version="3.0-stable"> +<class name="RegEx" inherits="Reference" category="Core" version="3.1"> <brief_description> Class for searching text for patterns using regular expressions. </brief_description> <description> - Regular Expression (or regex) is a compact programming language that can be used to recognise strings that follow a specific pattern, such as URLs, email addresses, complete sentences, etc. For instance, a regex of [code]ab[0-9][/code] would find any string that is [code]ab[/code] followed by any number from [code]0[/code] to [code]9[/code]. For a more in-depth look, you can easily find various tutorials and detailed explainations on the Internet. + Regular Expression (or regex) is a compact programming language that can be used to recognise strings that follow a specific pattern, such as URLs, email addresses, complete sentences, etc. For instance, a regex of [code]ab[0-9][/code] would find any string that is [code]ab[/code] followed by any number from [code]0[/code] to [code]9[/code]. For a more in-depth look, you can easily find various tutorials and detailed explanations on the Internet. To begin, the RegEx object needs to be compiled with the search pattern using [method compile] before it can be used. [codeblock] var regex = RegEx.new() regex.compile("\\w-(\\d+)") [/codeblock] The search pattern must be escaped first for gdscript before it is escaped for the expression. For example, [code]compile("\\d+")[/code] would be read by RegEx as [code]\d+[/code]. Similarly, [code]compile("\"(?:\\\\.|[^\"])*\"")[/code] would be read as [code]"(?:\\.|[^"])*"[/code] - Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using fuctions such as [method RegExMatch.get_string] and [method RegExMatch.get_start]. + Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using functions such as [method RegExMatch.get_string] and [method RegExMatch.get_start]. [codeblock] var regex = RegEx.new() regex.compile("\\w-(\\d+)") diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml index 9eba0f738b..3d070d2786 100644 --- a/modules/regex/doc_classes/RegExMatch.xml +++ b/modules/regex/doc_classes/RegExMatch.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RegExMatch" inherits="Reference" category="Core" version="3.0-stable"> +<class name="RegExMatch" inherits="Reference" category="Core" version="3.1"> <brief_description> Contains the results of a regex search. </brief_description> diff --git a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml index 827e947a79..ac95a7197f 100644 --- a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml +++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.0-stable"> +<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.1"> <brief_description> OGG Vorbis audio stream driver. </brief_description> diff --git a/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml index 9a095c3ddd..018f4734ec 100644 --- a/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml +++ b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.0-stable"> +<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp index 16ebfa2832..c8acdb689a 100644 --- a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp @@ -100,6 +100,7 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin ogg_stream.instance(); ogg_stream->set_data(data); + ERR_FAIL_COND_V(!ogg_stream->get_data().size(), ERR_FILE_CORRUPT); ogg_stream->set_loop(loop); ogg_stream->set_loop_offset(loop_offset); diff --git a/modules/theora/doc_classes/ResourceImporterTheora.xml b/modules/theora/doc_classes/ResourceImporterTheora.xml index a280d767c3..5fc40a6eba 100644 --- a/modules/theora/doc_classes/ResourceImporterTheora.xml +++ b/modules/theora/doc_classes/ResourceImporterTheora.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceImporterTheora" inherits="ResourceImporter" category="Core" version="3.0-stable"> +<class name="ResourceImporterTheora" inherits="ResourceImporter" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/theora/doc_classes/VideoStreamTheora.xml b/modules/theora/doc_classes/VideoStreamTheora.xml index 9da3dc0d02..e7c4727332 100644 --- a/modules/theora/doc_classes/VideoStreamTheora.xml +++ b/modules/theora/doc_classes/VideoStreamTheora.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.0-stable"> +<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml index a6a43f31b8..dab186fb57 100644 --- a/modules/visual_script/doc_classes/VisualScript.xml +++ b/modules/visual_script/doc_classes/VisualScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="VisualScript" inherits="Script" category="Core" version="3.1"> <brief_description> A script implemented in the Visual Script programming environment. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml index d63a6ad524..793291eca2 100644 --- a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node representing a constant from the base types. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml index da4db29086..0929b227d0 100644 --- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml +++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node used to call built-in functions. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml index 189a6f6ad8..2e3a5b33c0 100644 --- a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Gets a constant from a given class. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptComment.xml b/modules/visual_script/doc_classes/VisualScriptComment.xml index 5462c379ad..a4a890ea8a 100644 --- a/modules/visual_script/doc_classes/VisualScriptComment.xml +++ b/modules/visual_script/doc_classes/VisualScriptComment.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node used to annotate the script. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptCondition.xml b/modules/visual_script/doc_classes/VisualScriptCondition.xml index bb70a17357..353898c93a 100644 --- a/modules/visual_script/doc_classes/VisualScriptCondition.xml +++ b/modules/visual_script/doc_classes/VisualScriptCondition.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node which branches the flow. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptConstant.xml b/modules/visual_script/doc_classes/VisualScriptConstant.xml index e2ccb50bfd..ed633c4135 100644 --- a/modules/visual_script/doc_classes/VisualScriptConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Gets a contant's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptConstructor.xml b/modules/visual_script/doc_classes/VisualScriptConstructor.xml index da6779b79d..14c44c6970 100644 --- a/modules/visual_script/doc_classes/VisualScriptConstructor.xml +++ b/modules/visual_script/doc_classes/VisualScriptConstructor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node which calls a base type constructor. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml index 33d2f1437a..b8e77a1b0f 100644 --- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A scripted Visual Script node. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml index 09fcba4314..d3158df357 100644 --- a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml +++ b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node which deconstructs a base type instance into its parts. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptEditor.xml b/modules/visual_script/doc_classes/VisualScriptEditor.xml index 8e26758a31..fc49cfc07b 100644 --- a/modules/visual_script/doc_classes/VisualScriptEditor.xml +++ b/modules/visual_script/doc_classes/VisualScriptEditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.0-stable"> +<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml index 30f96011d4..4bb05525bd 100644 --- a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml +++ b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Emits a specified signal. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml index 0dc0cdf5eb..93d7ce3516 100644 --- a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml +++ b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node returning a singleton from [@GlobalScope] </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptExpression.xml b/modules/visual_script/doc_classes/VisualScriptExpression.xml index 91f55edb2b..343e83cb55 100644 --- a/modules/visual_script/doc_classes/VisualScriptExpression.xml +++ b/modules/visual_script/doc_classes/VisualScriptExpression.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptFunction.xml b/modules/visual_script/doc_classes/VisualScriptFunction.xml index bd59d739ea..ec8e955cf7 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunction.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml index e2b732a250..f6116cf539 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml index 614176498a..c75dd0cdbc 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.0-stable"> +<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml index a36f7809c2..9d43204f02 100644 --- a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml index b2d0a194e0..73c1f47e1a 100644 --- a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml index 7ad200afa4..652c29a9ac 100644 --- a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptInputAction.xml b/modules/visual_script/doc_classes/VisualScriptInputAction.xml index 45c493887b..ab4c23012b 100644 --- a/modules/visual_script/doc_classes/VisualScriptInputAction.xml +++ b/modules/visual_script/doc_classes/VisualScriptInputAction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptIterator.xml b/modules/visual_script/doc_classes/VisualScriptIterator.xml index 28e8a66182..7090621bd7 100644 --- a/modules/visual_script/doc_classes/VisualScriptIterator.xml +++ b/modules/visual_script/doc_classes/VisualScriptIterator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Steps through items in a given input. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml index 66faf448cb..5c8ee6453c 100644 --- a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml +++ b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Gets a local variable's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml index 8a816e5dd7..f2e6c48907 100644 --- a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Changes a local variable's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml index 45fa471c41..df439f8794 100644 --- a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Commonly used mathematical constants. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptNode.xml b/modules/visual_script/doc_classes/VisualScriptNode.xml index e9d1cd949f..941a0cd91a 100644 --- a/modules/visual_script/doc_classes/VisualScriptNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.0-stable"> +<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.1"> <brief_description> A node which is part of a [VisualScript]. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptOperator.xml b/modules/visual_script/doc_classes/VisualScriptOperator.xml index 4538bd3c78..e60d50c977 100644 --- a/modules/visual_script/doc_classes/VisualScriptOperator.xml +++ b/modules/visual_script/doc_classes/VisualScriptOperator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptPreload.xml b/modules/visual_script/doc_classes/VisualScriptPreload.xml index 3dae0e4b81..5a2886ccac 100644 --- a/modules/visual_script/doc_classes/VisualScriptPreload.xml +++ b/modules/visual_script/doc_classes/VisualScriptPreload.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Creates a new [Resource] or loads one from the filesystem. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml index 7555c83960..60cc8fdd4f 100644 --- a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml index dc6a9efd83..8f29e9d152 100644 --- a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml +++ b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml index 3789626ed0..f6300e03f0 100644 --- a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml +++ b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptReturn.xml b/modules/visual_script/doc_classes/VisualScriptReturn.xml index 1172b7555b..6095520eff 100644 --- a/modules/visual_script/doc_classes/VisualScriptReturn.xml +++ b/modules/visual_script/doc_classes/VisualScriptReturn.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Exits a function and returns an optional value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml index 4c6181e040..7704eaba04 100644 --- a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Node reference. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml index 68cc0d0b55..2c2af9262d 100644 --- a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml +++ b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptSelect.xml b/modules/visual_script/doc_classes/VisualScriptSelect.xml index 017efdb07a..0731fc77e1 100644 --- a/modules/visual_script/doc_classes/VisualScriptSelect.xml +++ b/modules/visual_script/doc_classes/VisualScriptSelect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Chooses between two input values. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSelf.xml b/modules/visual_script/doc_classes/VisualScriptSelf.xml index e9b480bbae..61a73e104c 100644 --- a/modules/visual_script/doc_classes/VisualScriptSelf.xml +++ b/modules/visual_script/doc_classes/VisualScriptSelf.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Outputs a reference to the current instance. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSequence.xml b/modules/visual_script/doc_classes/VisualScriptSequence.xml index be793ae36e..c71e068045 100644 --- a/modules/visual_script/doc_classes/VisualScriptSequence.xml +++ b/modules/visual_script/doc_classes/VisualScriptSequence.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Executes a series of Sequence ports. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSubCall.xml b/modules/visual_script/doc_classes/VisualScriptSubCall.xml index 85db63b78a..46aeebab9c 100644 --- a/modules/visual_script/doc_classes/VisualScriptSubCall.xml +++ b/modules/visual_script/doc_classes/VisualScriptSubCall.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptSwitch.xml b/modules/visual_script/doc_classes/VisualScriptSwitch.xml index ec7565b31a..a00811a29b 100644 --- a/modules/visual_script/doc_classes/VisualScriptSwitch.xml +++ b/modules/visual_script/doc_classes/VisualScriptSwitch.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Branches program flow based on a given input's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml index d414a95657..0bdc4ce89d 100644 --- a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml +++ b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml index ccd2918ec8..06178a399d 100644 --- a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Gets a variable's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml index e1fc1ba762..5969f25060 100644 --- a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Changes a variable's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptWhile.xml b/modules/visual_script/doc_classes/VisualScriptWhile.xml index de1ff45746..b9e7f6a553 100644 --- a/modules/visual_script/doc_classes/VisualScriptWhile.xml +++ b/modules/visual_script/doc_classes/VisualScriptWhile.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Conditional loop. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptYield.xml b/modules/visual_script/doc_classes/VisualScriptYield.xml index f21b53861a..c4698f746a 100644 --- a/modules/visual_script/doc_classes/VisualScriptYield.xml +++ b/modules/visual_script/doc_classes/VisualScriptYield.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml index 5075fb6ded..b67e4ab1b8 100644 --- a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml +++ b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 5987fdf5da..ef680547ca 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -2182,7 +2182,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o Ref<VisualScriptNode> node = F->get().node; VisualScriptNodeInstance *instance = instances[F->key()]; - // conect to default values + // connect to default values for (int i = 0; i < instance->input_port_count; i++) { if (instance->input_ports[i] == -1) { @@ -2192,7 +2192,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o } } - // conect to trash + // connect to trash for (int i = 0; i < instance->output_port_count; i++) { if (instance->output_ports[i] == -1) { instance->output_ports[i] = function.trash_pos; //trash is same for all diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index e0b4fde237..c5654a5a20 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -425,7 +425,7 @@ PropertyInfo VisualScriptOperator::get_input_value_port_info(int p_idx) const { } PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { static const Variant::Type port_types[Variant::OP_MAX] = { - //comparation + //comparison Variant::BOOL, //OP_EQUAL, Variant::BOOL, //OP_NOT_EQUAL, Variant::BOOL, //OP_LESS, @@ -466,7 +466,7 @@ PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { } static const char *op_names[] = { - //comparation + //comparison "Equal", //OP_EQUAL, "NotEqual", //OP_NOT_EQUAL, "Less", //OP_LESS, @@ -506,7 +506,7 @@ String VisualScriptOperator::get_caption() const { String VisualScriptOperator::get_text() const { static const wchar_t *op_names[] = { - //comparation + //comparison L"A = B", //OP_EQUAL, L"A \u2260 B", //OP_NOT_EQUAL, L"A < B", //OP_LESS, diff --git a/modules/webm/SCsub b/modules/webm/SCsub index 2f1a28a54c..33561da098 100644 --- a/modules/webm/SCsub +++ b/modules/webm/SCsub @@ -18,6 +18,10 @@ thirdparty_libsimplewebm_sources = [thirdparty_libsimplewebm_dir + file for file env_webm.add_source_files(env.modules_sources, thirdparty_libsimplewebm_sources) env_webm.Append(CPPPATH=[thirdparty_libsimplewebm_dir, thirdparty_libsimplewebm_dir + "libwebm/"]) +# upstream uses c++11 +if (not env_webm.msvc): + env_webm.Append(CCFLAGS="-std=c++11") + # also requires libogg, libvorbis and libopus if env['builtin_libogg']: env_webm.Append(CPPPATH=["#thirdparty/libogg"]) diff --git a/modules/webm/doc_classes/ResourceImporterWebm.xml b/modules/webm/doc_classes/ResourceImporterWebm.xml index 20e0e48187..0cfab1baf0 100644 --- a/modules/webm/doc_classes/ResourceImporterWebm.xml +++ b/modules/webm/doc_classes/ResourceImporterWebm.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceImporterWebm" inherits="ResourceImporter" category="Core" version="3.0-stable"> +<class name="ResourceImporterWebm" inherits="ResourceImporter" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/webm/doc_classes/VideoStreamWebm.xml b/modules/webm/doc_classes/VideoStreamWebm.xml index 94aea5c8d2..c02a7a8016 100644 --- a/modules/webm/doc_classes/VideoStreamWebm.xml +++ b/modules/webm/doc_classes/VideoStreamWebm.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.0-stable"> +<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub index aa282338cb..0ebafa022d 100644 --- a/modules/webm/libvpx/SCsub +++ b/modules/webm/libvpx/SCsub @@ -254,7 +254,6 @@ env_libvpx = env.Clone() env_libvpx.Append(CPPPATH=[libvpx_dir]) cpu_bits = env["bits"] -osx_fat = (env["platform"] == 'osx' and cpu_bits == 'fat') webm_cpu_x86 = False webm_cpu_arm = False if env["platform"] == 'uwp': @@ -269,11 +268,8 @@ else: is_android_x86 = (env["platform"] == 'android' and env["android_arch"] == 'x86') if is_android_x86: cpu_bits = '32' - if osx_fat: - webm_cpu_x86 = True - else: - webm_cpu_x86 = not is_x11_or_server_arm and (cpu_bits == '32' or cpu_bits == '64') and (env["platform"] == 'windows' or env["platform"] == 'x11' or env["platform"] == 'osx' or env["platform"] == 'haiku' or is_android_x86 or is_ios_x86) - webm_cpu_arm = is_x11_or_server_arm or (not is_ios_x86 and env["platform"] == 'iphone') or (not is_android_x86 and env["platform"] == 'android') + webm_cpu_x86 = not is_x11_or_server_arm and (cpu_bits == '32' or cpu_bits == '64') and (env["platform"] == 'windows' or env["platform"] == 'x11' or env["platform"] == 'osx' or env["platform"] == 'haiku' or is_android_x86 or is_ios_x86) + webm_cpu_arm = is_x11_or_server_arm or (not is_ios_x86 and env["platform"] == 'iphone') or (not is_android_x86 and env["platform"] == 'android') if webm_cpu_x86: import subprocess @@ -303,28 +299,22 @@ if webm_cpu_x86: webm_simd_optimizations = False if webm_cpu_x86: - if osx_fat: - #'osx' platform only: run python script which will compile using 'yasm' command and then merge 32-bit and 64-bit using 'lipo' command - env_libvpx["AS"] = 'python modules/webm/libvpx/yasm_osx_fat.py' - env_libvpx["ASFLAGS"] = '-I' + libvpx_dir[1:] - env_libvpx["ASCOM"] = '$AS $ASFLAGS $TARGET $SOURCES' + if env["platform"] == 'windows' or env["platform"] == 'uwp': + env_libvpx["ASFORMAT"] = 'win' + elif env["platform"] == 'osx' or env["platform"] == "iphone": + env_libvpx["ASFORMAT"] = 'macho' else: - if env["platform"] == 'windows' or env["platform"] == 'uwp': - env_libvpx["ASFORMAT"] = 'win' - elif env["platform"] == 'osx' or env["platform"] == "iphone": - env_libvpx["ASFORMAT"] = 'macho' - else: - env_libvpx["ASFORMAT"] = 'elf' - env_libvpx["ASFORMAT"] += cpu_bits - - env_libvpx["AS"] = 'yasm' - env_libvpx["ASFLAGS"] = '-I' + libvpx_dir[1:] + ' -f $ASFORMAT -D $ASCPU' - env_libvpx["ASCOM"] = '$AS $ASFLAGS -o $TARGET $SOURCES' + env_libvpx["ASFORMAT"] = 'elf' + env_libvpx["ASFORMAT"] += cpu_bits + + env_libvpx["AS"] = 'yasm' + env_libvpx["ASFLAGS"] = '-I' + libvpx_dir[1:] + ' -f $ASFORMAT -D $ASCPU' + env_libvpx["ASCOM"] = '$AS $ASFLAGS -o $TARGET $SOURCES' - if cpu_bits == '32': - env_libvpx["ASCPU"] = 'X86_32' - elif cpu_bits == '64': - env_libvpx["ASCPU"] = 'X86_64' + if cpu_bits == '32': + env_libvpx["ASCPU"] = 'X86_32' + elif cpu_bits == '64': + env_libvpx["ASCPU"] = 'X86_64' env_libvpx.Append(CCFLAGS=['-DWEBM_X86ASM']) @@ -375,7 +365,7 @@ if webm_cpu_x86: env_libvpx.add_source_files(env.modules_sources, libvpx_sources_intrin_x86) env_libvpx.add_source_files(env.modules_sources, libvpx_sources_x86asm) - if cpu_bits == '64' or osx_fat: + if cpu_bits == '64': env_libvpx.add_source_files(env.modules_sources, libvpx_sources_x86_64asm) elif webm_cpu_arm: env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm) diff --git a/modules/webm/libvpx/yasm_osx_fat.py b/modules/webm/libvpx/yasm_osx_fat.py deleted file mode 100644 index 0065e2766c..0000000000 --- a/modules/webm/libvpx/yasm_osx_fat.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -import sys -import os - -includes = sys.argv[1] -output_file = sys.argv[2] -input_file = sys.argv[3] - -can_remove = {} - -lipo_command = '' - -exit_code = 1 - -for arch in ['32', '64']: - if arch == '32' and input_file.endswith('x86_64.asm'): - can_remove[arch] = False - else: - command = 'yasm ' + includes + ' -f macho' + arch + ' -D X86_' + arch + ' -o ' + output_file + '.' + arch + ' ' + input_file - print(command) - if os.system(command) == 0: - lipo_command += output_file + '.' + arch + ' ' - can_remove[arch] = True - else: - can_remove[arch] = False - -if lipo_command != '': - lipo_command = 'lipo -create ' + lipo_command + '-output ' + output_file - print(lipo_command) - if os.system(lipo_command) == 0: - exit_code = 0 - -for arch in ['32', '64']: - if can_remove[arch]: - os.remove(output_file + '.' + arch) - -sys.exit(exit_code) diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub index 3b0f920bbf..b36f1beacd 100644 --- a/modules/websocket/SCsub +++ b/modules/websocket/SCsub @@ -35,7 +35,6 @@ thirdparty_sources = [ "handshake.c", "header.c", "libwebsockets.c", - "minilex.c", "output.c", "pollfd.c", "service.c", @@ -54,7 +53,7 @@ thirdparty_sources = [ if env_lws["platform"] == "android": # Builtin getifaddrs thirdparty_sources += ["misc/getifaddrs.c"] -if env_lws["platform"] == "windows": # Winsock +if env_lws["platform"] == "windows" or env_lws["platform"] == "uwp": # Winsock thirdparty_sources += ["plat/lws-plat-win.c", helper_dir + "getopt.c", helper_dir + "getopt_long.c", helper_dir + "gettimeofday.c"] else: # Unix socket thirdparty_sources += ["plat/lws-plat-unix.c"] @@ -69,13 +68,16 @@ else: env_lws.Append(CPPPATH=[thirdparty_dir]) wrapper_includes = ["#thirdparty/lws/mbedtls_wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]] - env_lws.Append(CPPPATH=wrapper_includes) + env_lws.Prepend(CPPPATH=wrapper_includes) if env['builtin_mbedtls']: mbedtls_includes = "#thirdparty/mbedtls/include" - env_lws.Append(CPPPATH=[mbedtls_includes]) + env_lws.Prepend(CPPPATH=[mbedtls_includes]) - if env_lws["platform"] == "windows": + if env_lws["platform"] == "windows" or env_lws["platform"] == "uwp": env_lws.Append(CPPPATH=[thirdparty_dir + helper_dir]) + if env_lws["platform"] == "uwp": + env_lws.Append(CCFLAGS=["/DLWS_MINGW_SUPPORT"]) + env_lws.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index 38fe520fc1..1405fa98b0 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/emws_client.h b/modules/websocket/emws_client.h index 8801f37007..6c2fa23b53 100644 --- a/modules/websocket/emws_client.h +++ b/modules/websocket/emws_client.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp index 93665e6428..d3330d683c 100644 --- a/modules/websocket/emws_peer.cpp +++ b/modules/websocket/emws_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/emws_peer.h b/modules/websocket/emws_peer.h index a50d1874ba..e06f725265 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/emws_server.cpp b/modules/websocket/emws_server.cpp index 60e9133225..c9ddae0c8c 100644 --- a/modules/websocket/emws_server.cpp +++ b/modules/websocket/emws_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/emws_server.h b/modules/websocket/emws_server.h index 59f1d76346..aa089ea40d 100644 --- a/modules/websocket/emws_server.h +++ b/modules/websocket/emws_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp index 604b1886ad..bebf342f8c 100644 --- a/modules/websocket/lws_client.cpp +++ b/modules/websocket/lws_client.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/lws_client.h b/modules/websocket/lws_client.h index 2e082175df..8850683cb5 100644 --- a/modules/websocket/lws_client.h +++ b/modules/websocket/lws_client.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/lws_helper.h b/modules/websocket/lws_helper.h index ac0c340aa9..a850a545d3 100644 --- a/modules/websocket/lws_helper.h +++ b/modules/websocket/lws_helper.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -108,7 +108,7 @@ static bool _lws_poll(struct lws_context *context, _LWSRef *ref) { static void _lws_make_protocols(void *p_obj, lws_callback_function *p_callback, PoolVector<String> p_names, _LWSRef **r_lws_ref) { /* the input strings might go away after this call, * we need to copy them. Will clear them when - * detroying the context */ + * destroying the context */ int i; int len = p_names.size(); size_t data_size = sizeof(struct LWSPeer::PeerData); diff --git a/modules/websocket/lws_peer.cpp b/modules/websocket/lws_peer.cpp index fdaa79f9d4..ba45d7688f 100644 --- a/modules/websocket/lws_peer.cpp +++ b/modules/websocket/lws_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/lws_peer.h b/modules/websocket/lws_peer.h index 0a62b65d24..e96b38b168 100644 --- a/modules/websocket/lws_peer.h +++ b/modules/websocket/lws_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/lws_server.cpp b/modules/websocket/lws_server.cpp index 8a47ba557d..94fe4231ae 100644 --- a/modules/websocket/lws_server.cpp +++ b/modules/websocket/lws_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/lws_server.h b/modules/websocket/lws_server.h index 5f7ac4850a..de8f59e5ae 100644 --- a/modules/websocket/lws_server.h +++ b/modules/websocket/lws_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/register_types.cpp b/modules/websocket/register_types.cpp index 39d03ff1f0..721f3cc330 100644 --- a/modules/websocket/register_types.cpp +++ b/modules/websocket/register_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/register_types.h b/modules/websocket/register_types.h index 010d88789b..89ce93e286 100644 --- a/modules/websocket/register_types.h +++ b/modules/websocket/register_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp index f92a386988..591d9510ce 100644 --- a/modules/websocket/websocket_client.cpp +++ b/modules/websocket/websocket_client.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_client.h b/modules/websocket/websocket_client.h index 0e87825222..5c863559bc 100644 --- a/modules/websocket/websocket_client.h +++ b/modules/websocket/websocket_client.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_macros.h b/modules/websocket/websocket_macros.h index b5c2159806..d27fb4d778 100644 --- a/modules/websocket/websocket_macros.h +++ b/modules/websocket/websocket_macros.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_multiplayer.cpp b/modules/websocket/websocket_multiplayer.cpp index 8cd4dff38b..b948c439df 100644 --- a/modules/websocket/websocket_multiplayer.cpp +++ b/modules/websocket/websocket_multiplayer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_multiplayer.h b/modules/websocket/websocket_multiplayer.h index e8e795e97f..8edfc5296e 100644 --- a/modules/websocket/websocket_multiplayer.h +++ b/modules/websocket/websocket_multiplayer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_peer.cpp b/modules/websocket/websocket_peer.cpp index a6fbb4481b..6324047846 100644 --- a/modules/websocket/websocket_peer.cpp +++ b/modules/websocket/websocket_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index f4d8ce3e38..ad451e9cc7 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp index ba77019f55..5746f61e10 100644 --- a/modules/websocket/websocket_server.cpp +++ b/modules/websocket/websocket_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/websocket/websocket_server.h b/modules/websocket/websocket_server.h index db188811fd..360ff9e6d4 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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/platform/SCsub b/platform/SCsub index e624f8e90f..2019a30be7 100644 --- a/platform/SCsub +++ b/platform/SCsub @@ -18,11 +18,10 @@ for platform in env.platform_apis: reg_apis_inc += '\n' reg_apis += '}\n\n' unreg_apis += '}\n' -f = open_utf8('register_platform_apis.gen.cpp', 'w') -f.write(reg_apis_inc) -f.write(reg_apis) -f.write(unreg_apis) -f.close() +with open_utf8('register_platform_apis.gen.cpp', 'w') as f: + f.write(reg_apis_inc) + f.write(reg_apis) + f.write(unreg_apis) platform_sources.append('register_platform_apis.gen.cpp') lib = env.add_library('platform', platform_sources) diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template index 9d8eb951c4..3e42b7a3cd 100644 --- a/platform/android/AndroidManifest.xml.template +++ b/platform/android/AndroidManifest.xml.template @@ -16,7 +16,8 @@ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:launchMode="singleTask" android:screenOrientation="landscape" - android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize"> + android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize" + android:resizeableActivity="false"> <intent-filter> <action android:name="android.intent.action.MAIN" /> @@ -31,7 +32,7 @@ $$ADD_APPLICATION_CHUNKS$$ </application> - <uses-feature android:glEsVersion="0x00030000"/> + <uses-feature android:glEsVersion="0x00030000" android:required="true" /> $$ADD_PERMISSION_CHUNKS$$ <uses-permission android:name="godot.ACCESS_CHECKIN_PROPERTIES"/> diff --git a/platform/android/SCsub b/platform/android/SCsub index d2285a82dd..8c08289932 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -41,10 +41,8 @@ prog = None abspath = env.Dir(".").abspath -gradle_basein = open_utf8(abspath + "/build.gradle.template", "r") -gradle_baseout = open_utf8(abspath + "/java/build.gradle", "w") - -gradle_text = gradle_basein.read() +with open_utf8(abspath + "/build.gradle.template", "r") as gradle_basein: + gradle_text = gradle_basein.read() gradle_maven_flat_text = "" if len(env.android_flat_dirs) > 0: @@ -131,17 +129,19 @@ gradle_text = gradle_text.replace("$$GRADLE_DEFAULT_CONFIG$$", gradle_default_co gradle_text = gradle_text.replace("$$GRADLE_PLUGINS$$", gradle_plugins) gradle_text = gradle_text.replace("$$GRADLE_CLASSPATH$$", gradle_classpath) -gradle_baseout.write(gradle_text) -gradle_baseout.close() +with open_utf8(abspath + "/java/build.gradle", "w") as gradle_baseout: + gradle_baseout.write(gradle_text) + +with open_utf8(abspath + "/AndroidManifest.xml.template", "r") as pp_basein: + manifest = pp_basein.read() -pp_basein = open_utf8(abspath + "/AndroidManifest.xml.template", "r") -pp_baseout = open_utf8(abspath + "/java/AndroidManifest.xml", "w") -manifest = pp_basein.read() manifest = manifest.replace("$$ADD_APPLICATION_CHUNKS$$", env.android_manifest_chunk) manifest = manifest.replace("$$ADD_PERMISSION_CHUNKS$$", env.android_permission_chunk) manifest = manifest.replace("$$ADD_APPATTRIBUTE_CHUNKS$$", env.android_appattributes_chunk) -pp_baseout.write(manifest) + +with open_utf8(abspath + "/java/AndroidManifest.xml", "w") as pp_baseout: + pp_baseout.write(manifest) lib = env_android.add_shared_library("#bin/libgodot", [android_objects], SHLIBSUFFIX=env["SHLIBSUFFIX"]) diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp index 7545ee88d0..3d80e76707 100644 --- a/platform/android/audio_driver_jandroid.cpp +++ b/platform/android/audio_driver_jandroid.cpp @@ -86,7 +86,6 @@ Error AudioDriverAndroid::init() { print_line("audio buffer size: " + itos(buffer_size)); } - __android_log_print(ANDROID_LOG_INFO, "godot", "Initializing audio! params: %i,%i ", mix_rate, buffer_size); audioBuffer = env->CallObjectMethod(io, _init_audio, mix_rate, buffer_size); ERR_FAIL_COND_V(audioBuffer == NULL, ERR_INVALID_PARAMETER); @@ -113,29 +112,10 @@ void AudioDriverAndroid::setup(jobject p_io) { jclass c = env->GetObjectClass(io); cls = (jclass)env->NewGlobalRef(c); - __android_log_print(ANDROID_LOG_INFO, "godot", "starting to attempt get methods"); - _init_audio = env->GetMethodID(cls, "audioInit", "(II)Ljava/lang/Object;"); - if (_init_audio != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _init_audio ok!!"); - } else { - __android_log_print(ANDROID_LOG_INFO, "godot", "audioinit ok!"); - } - _write_buffer = env->GetMethodID(cls, "audioWriteShortBuffer", "([S)V"); - if (_write_buffer != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _write_buffer ok!!"); - } - _quit = env->GetMethodID(cls, "audioQuit", "()V"); - if (_quit != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _quit ok!!"); - } - _pause = env->GetMethodID(cls, "audioPause", "(Z)V"); - if (_quit != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _pause ok!!"); - } } void AudioDriverAndroid::thread_func(JNIEnv *env) { @@ -144,7 +124,6 @@ void AudioDriverAndroid::thread_func(JNIEnv *env) { if (cls) { cls = (jclass)env->NewGlobalRef(cls); - __android_log_print(ANDROID_LOG_INFO, "godot", "*******CLASS FOUND!!!"); } jfieldID fid = env->GetStaticFieldID(cls, "io", "Lorg/godotengine/godot/GodotIO;"); jobject ob = env->GetStaticObjectField(cls, fid); @@ -152,9 +131,6 @@ void AudioDriverAndroid::thread_func(JNIEnv *env) { jclass c = env->GetObjectClass(gob); jclass lcls = (jclass)env->NewGlobalRef(c); _write_buffer = env->GetMethodID(lcls, "audioWriteShortBuffer", "([S)V"); - if (_write_buffer != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _write_buffer ok!!"); - } while (!quit) { diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp index 87a7d04e01..e6bd3ff253 100644 --- a/platform/android/audio_driver_opensl.cpp +++ b/platform/android/audio_driver_opensl.cpp @@ -117,8 +117,6 @@ Error AudioDriverOpenSL::init() { ERR_FAIL_V(ERR_INVALID_PARAMETER); } - print_line("OpenSL Init OK!"); - return OK; } @@ -273,4 +271,5 @@ AudioDriverOpenSL::AudioDriverOpenSL() { s_ad = this; mutex = Mutex::create(); //NULL; pause = false; + active = false; } diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index 5601dcc763..3e40b59de9 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -130,7 +130,6 @@ Error DirAccessJAndroid::change_dir(String p_dir) { else new_dir = current_dir.plus_file(p_dir); - //print_line("new dir is: "+new_dir); //test if newdir exists new_dir = new_dir.simplify_path(); @@ -226,28 +225,14 @@ void DirAccessJAndroid::setup(jobject p_io) { JNIEnv *env = ThreadAndroid::get_env(); io = p_io; - __android_log_print(ANDROID_LOG_INFO, "godot", "STEP7"); jclass c = env->GetObjectClass(io); cls = (jclass)env->NewGlobalRef(c); - __android_log_print(ANDROID_LOG_INFO, "godot", "STEP8"); _dir_open = env->GetMethodID(cls, "dir_open", "(Ljava/lang/String;)I"); - if (_dir_open != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _dir_open ok!!"); - } _dir_next = env->GetMethodID(cls, "dir_next", "(I)Ljava/lang/String;"); - if (_dir_next != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _dir_next ok!!"); - } _dir_close = env->GetMethodID(cls, "dir_close", "(I)V"); - if (_dir_close != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _dir_close ok!!"); - } _dir_is_dir = env->GetMethodID(cls, "dir_is_dir", "(I)Z"); - if (_dir_is_dir != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _dir_is_dir ok!!"); - } //(*env)->CallVoidMethod(env,obj,aMethodID, myvar); } diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 2a61f8d873..6d9f0a7e9a 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -257,7 +257,7 @@ class EditorExportAndroid : public EditorExportPlatform { if (dpos == -1) continue; d = d.substr(0, dpos).strip_edges(); - //print_line("found devuce: "+d); + //print_line("found device: "+d); ldevices.push_back(d); } @@ -301,8 +301,7 @@ class EditorExportAndroid : public EditorExportPlatform { args.push_back("-s"); args.push_back(d.id); args.push_back("shell"); - args.push_back("cat"); - args.push_back("/system/build.prop"); + args.push_back("getprop"); int ec; String dp; @@ -315,7 +314,14 @@ class EditorExportAndroid : public EditorExportPlatform { d.api_level = 0; for (int j = 0; j < props.size(); j++) { + // got information by `shell cat /system/build.prop` before and its format is "property=value" + // it's now changed to use `shell getporp` because of permission issue with Android 8.0 and above + // its format is "[property]: [value]" so changed it as like build.prop String p = props[j]; + p = p.replace("]: ", "="); + p = p.replace("[", ""); + p = p.replace("]", ""); + if (p.begins_with("ro.product.model=")) { device = p.get_slice("=", 1).strip_edges(); } else if (p.begins_with("ro.product.brand=")) { @@ -996,7 +1002,7 @@ public: public: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { - // Reenable when a GLES 2.0 backend is readded + // Re-enable when a GLES 2.0 backend is read /*int api = p_preset->get("graphics/api"); if (api == 0) r_features->push_back("etc"); diff --git a/platform/android/file_access_jandroid.cpp b/platform/android/file_access_jandroid.cpp index 1a9d3af4ea..214e273d9b 100644 --- a/platform/android/file_access_jandroid.cpp +++ b/platform/android/file_access_jandroid.cpp @@ -190,43 +190,16 @@ void FileAccessJAndroid::setup(jobject p_io) { io = p_io; JNIEnv *env = ThreadAndroid::get_env(); - __android_log_print(ANDROID_LOG_INFO, "godot", "STEP5"); - jclass c = env->GetObjectClass(io); - __android_log_print(ANDROID_LOG_INFO, "godot", "STEP6"); cls = (jclass)env->NewGlobalRef(c); _file_open = env->GetMethodID(cls, "file_open", "(Ljava/lang/String;Z)I"); - if (_file_open != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _file_open ok!!"); - } _file_get_size = env->GetMethodID(cls, "file_get_size", "(I)I"); - if (_file_get_size != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _file_get_size ok!!"); - } _file_tell = env->GetMethodID(cls, "file_tell", "(I)I"); - if (_file_tell != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _file_tell ok!!"); - } _file_eof = env->GetMethodID(cls, "file_eof", "(I)Z"); - - if (_file_eof != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _file_eof ok!!"); - } _file_seek = env->GetMethodID(cls, "file_seek", "(II)V"); - if (_file_seek != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _file_seek ok!!"); - } _file_read = env->GetMethodID(cls, "file_read", "(II)[B"); - if (_file_read != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _file_read ok!!"); - } _file_close = env->GetMethodID(cls, "file_close", "(I)V"); - if (_file_close != 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*******GOT METHOD _file_close ok!!"); - } - - //(*env)->CallVoidMethod(env,obj,aMethodID, myvar); } FileAccessJAndroid::FileAccessJAndroid() { diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp index 64715b3683..0e5f4fb93a 100644 --- a/platform/android/godot_android.cpp +++ b/platform/android/godot_android.cpp @@ -76,14 +76,11 @@ public: virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - print_line("attempt to call " + String(p_method)); - r_error.error = Variant::CallError::CALL_OK; Map<StringName, MethodData>::Element *E = method_map.find(p_method); if (!E) { - print_line("no exists"); r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); } @@ -91,7 +88,6 @@ public: int ac = E->get().argtypes.size(); if (ac < p_argcount) { - print_line("fewargs"); r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = ac; return Variant(); @@ -99,7 +95,6 @@ public: if (ac > p_argcount) { - print_line("manyargs"); r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument = ac; return Variant(); @@ -181,26 +176,21 @@ public: } } - print_line("calling method!!"); - Variant ret; switch (E->get().ret_type) { case Variant::NIL: { - print_line("call void"); env->CallVoidMethodA(instance, E->get().method, v); } break; case Variant::BOOL: { ret = env->CallBooleanMethodA(instance, E->get().method, v); - print_line("call bool"); } break; case Variant::INT: { ret = env->CallIntMethodA(instance, E->get().method, v); - print_line("call int"); } break; case Variant::REAL: { @@ -255,13 +245,10 @@ public: } break; default: { - print_line("failure.."); ERR_FAIL_V(Variant()); } break; } - print_line("success"); - return ret; } @@ -389,7 +376,6 @@ static int engine_init_display(struct engine *engine, bool p_gl2) { eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); - print_line("INIT VIDEO MODE: " + itos(w) + "," + itos(h)); //engine->os->set_egl_extensions(eglQueryString(display,EGL_EXTENSIONS)); engine->os->init_video_mode(w, h); @@ -942,7 +928,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerMethod(JNIEnv *e jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data()); if (!mid) { - print_line("FAILED GETTING METHOID " + mname); + print_line("FAILED GETTING METHOD ID " + mname); } s->add_method(mname, mid, types, get_jni_type(retval)); diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index 0d14211bd0..90848e6a90 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -150,21 +150,16 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { boolean found = false; - Log.d("XXX", "METHOD: %s\n" + method.getName()); for (String s : p_methods) { - Log.d("XXX", "METHOD CMP WITH: %s\n" + s); if (s.equals(method.getName())) { found = true; - Log.d("XXX", "METHOD CMP VALID"); break; } } if (!found) continue; - Log.d("XXX", "METHOD FOUND: %s\n" + method.getName()); - List<String> ptr = new ArrayList<String>(); Class[] paramTypes = method.getParameterTypes(); @@ -281,7 +276,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC godot.mView.getWindowVisibleDisplayFrame(gameSize); final int keyboardHeight = fullSize.y - gameSize.bottom; - Log.d("GODOT", "setVirtualKeyboardHeight: " + keyboardHeight); GodotLib.setVirtualKeyboardHeight(keyboardHeight); } }); @@ -351,8 +345,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC byte[] len = new byte[4]; int r = is.read(len); if (r < 4) { - Log.d("XXX", "**ERROR** Wrong cmdline length.\n"); - Log.d("GODOT", "**ERROR** Wrong cmdline length.\n"); return new String[0]; } int argc = ((int)(len[3] & 0xFF) << 24) | ((int)(len[2] & 0xFF) << 16) | ((int)(len[1] & 0xFF) << 8) | ((int)(len[0] & 0xFF)); @@ -362,12 +354,10 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC r = is.read(len); if (r < 4) { - Log.d("GODOT", "**ERROR** Wrong cmdline param length.\n"); return new String[0]; } int strlen = ((int)(len[3] & 0xFF) << 24) | ((int)(len[2] & 0xFF) << 16) | ((int)(len[1] & 0xFF) << 8) | ((int)(len[0] & 0xFF)); if (strlen > 65535) { - Log.d("GODOT", "**ERROR** Wrong command len\n"); return new String[0]; } byte[] arg = new byte[strlen]; @@ -379,7 +369,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC return cmdline; } catch (Exception e) { e.printStackTrace(); - Log.d("GODOT", "**ERROR** Exception " + e.getClass().getName() + ":" + e.getMessage()); return new String[0]; } } @@ -393,14 +382,12 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC String[] new_cmdline; int cll = 0; if (command_line != null) { - Log.d("GODOT", "initializeGodot: command_line: is not null"); new_cmdline = new String[command_line.length + 2]; cll = command_line.length; for (int i = 0; i < command_line.length; i++) { new_cmdline[i] = command_line[i]; } } else { - Log.d("GODOT", "initializeGodot: command_line: is null"); new_cmdline = new String[2]; } @@ -412,13 +399,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC io = new GodotIO(this); io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); GodotLib.io = io; - Log.d("GODOT", "command_line is null? " + ((command_line == null) ? "yes" : "no")); - /*if(command_line != null){ - Log.d("GODOT", "Command Line:"); - for(int w=0;w <command_line.length;w++){ - Log.d("GODOT"," " + command_line[w]); - } - }*/ mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); @@ -447,8 +427,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC @Override protected void onCreate(Bundle icicle) { - Log.d("GODOT", "** GODOT ACTIVITY CREATED HERE ***\n"); - super.onCreate(icicle); _self = this; Window window = getWindow(); @@ -509,7 +487,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) { //check that environment is ok! if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - Log.d("GODOT", "**ERROR! No media mounted!"); //show popup and die } @@ -524,25 +501,20 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC File f = new File(expansion_pack_path); boolean pack_valid = true; - Log.d("GODOT", "**PACK** - Path " + expansion_pack_path); if (!f.exists()) { pack_valid = false; - Log.d("GODOT", "**PACK** - File does not exist"); } else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) { - Log.d("GODOT", "**PACK** - Expansion pack (obb) is corrupted"); pack_valid = false; try { f.delete(); } catch (Exception e) { - Log.d("GODOT", "**PACK** - Error deleting corrupted expansion pack (obb)"); } } if (!pack_valid) { - Log.d("GODOT", "Pack Invalid, try re-downloading."); Intent notifierIntent = new Intent(this, this.getClass()); notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | @@ -553,15 +525,12 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC int startResult; try { - Log.d("GODOT", "INITIALIZING DOWNLOAD"); startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( getApplicationContext(), pendingIntent, GodotDownloaderService.class); - Log.d("GODOT", "DOWNLOAD SERVICE FINISHED:" + startResult); if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { - Log.d("GODOT", "DOWNLOAD REQUIRED"); // This is where you do set up to display the download // progress (next step) mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this, @@ -581,11 +550,9 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC return; } else { - Log.d("GODOT", "NO DOWNLOAD REQUIRED"); } } catch (NameNotFoundException e) { // TODO Auto-generated catch block - Log.d("GODOT", "Error downloading expansion package:" + e.getMessage()); } } } @@ -763,7 +730,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC } } - System.out.printf("** BACK REQUEST!\n"); if (shouldQuit && mView != null) { mView.queueEvent(new Runnable() { @Override @@ -812,15 +778,12 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC } String md5str = hexString.toString(); - //Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5); if (!md5str.equals(main_pack_md5)) { - Log.d("GODOT", "**PACK MD5 MISMATCH???** - MD5 Found: " + md5str + " " + Integer.toString(md5str.length()) + " - MD5 Expected: " + main_pack_md5 + " " + Integer.toString(main_pack_md5.length())); return true; } return false; } catch (Exception e) { e.printStackTrace(); - Log.d("GODOT", "**PACK FAIL**"); return true; } } @@ -936,7 +899,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC */ @Override public void onDownloadStateChanged(int newState) { - Log.d("GODOT", "onDownloadStateChanged:" + newState); setState(newState); boolean showDashboard = true; boolean showCellMessage = false; @@ -944,7 +906,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC boolean indeterminate; switch (newState) { case IDownloaderClient.STATE_IDLE: - Log.d("GODOT", "DOWNLOAD STATE IDLE"); // STATE_IDLE means the service is listening, so it's // safe to start making calls via mRemoteService. paused = false; @@ -952,13 +913,11 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC break; case IDownloaderClient.STATE_CONNECTING: case IDownloaderClient.STATE_FETCHING_URL: - Log.d("GODOT", "DOWNLOAD STATE CONNECTION / FETCHING URL"); showDashboard = true; paused = false; indeterminate = true; break; case IDownloaderClient.STATE_DOWNLOADING: - Log.d("GODOT", "DOWNLOAD STATE DOWNLOADING"); paused = false; showDashboard = true; indeterminate = false; @@ -968,14 +927,12 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC case IDownloaderClient.STATE_FAILED: case IDownloaderClient.STATE_FAILED_FETCHING_URL: case IDownloaderClient.STATE_FAILED_UNLICENSED: - Log.d("GODOT", "DOWNLOAD STATE: FAILED, CANCELLED, UNLICENSED OR FAILED TO FETCH URL"); paused = true; showDashboard = false; indeterminate = false; break; case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION: case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION: - Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY MISSING CELLULAR PERMISSION"); showDashboard = false; paused = true; indeterminate = false; @@ -983,26 +940,21 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC break; case IDownloaderClient.STATE_PAUSED_BY_REQUEST: - Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY USER"); paused = true; indeterminate = false; break; case IDownloaderClient.STATE_PAUSED_ROAMING: case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE: - Log.d("GODOT", "DOWNLOAD STATE: PAUSED BY ROAMING OR SDCARD UNAVAILABLE"); paused = true; indeterminate = false; break; case IDownloaderClient.STATE_COMPLETED: - Log.d("GODOT", "DOWNLOAD STATE: COMPLETED"); showDashboard = false; paused = false; indeterminate = false; - // validateXAPKZipFiles(); initializeGodot(); return; default: - Log.d("GODOT", "DOWNLOAD STATE: DEFAULT"); paused = true; indeterminate = true; showDashboard = true; diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index 80a32452a5..446a5911e5 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -1117,7 +1117,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { } if (!valid) { - print_line("Method Can't be bound (unsupported arguments): " + p_class + "::" + str_method); + print_line("Method can't be bound (unsupported arguments): " + p_class + "::" + str_method); env->DeleteLocalRef(obj); env->DeleteLocalRef(param_types); continue; @@ -1130,7 +1130,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { String strsig; uint32_t sig = 0; if (!_get_type_sig(env, return_type, sig, strsig)) { - print_line("Method Can't be bound (unsupported return type): " + p_class + "::" + str_method); + print_line("Method can't be bound (unsupported return type): " + p_class + "::" + str_method); env->DeleteLocalRef(obj); env->DeleteLocalRef(param_types); env->DeleteLocalRef(return_type); @@ -1140,8 +1140,6 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { signature += strsig; mi.return_type = sig; - print_line("METHOD: " + str_method + " SIG: " + signature + " static: " + itos(mi._static)); - bool discard = false; for (List<JavaClass::MethodInfo>::Element *E = java_class->methods[str_method].front(); E; E = E->next()) { @@ -1173,11 +1171,9 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { if (new_likeliness > existing_likeliness) { java_class->methods[str_method].erase(E); - print_line("replace old"); break; } else { discard = true; - print_line("old is better"); } } diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index 2d81d79bf1..9baf58c3eb 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -240,7 +240,6 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) { jclass c = env->GetObjectClass(obj); bool array; String name = _get_class_name(env, c, &array); - //print_line("name is " + name + ", array "+Variant(array)); if (name == "java.lang.String") { @@ -251,7 +250,6 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) { jobjectArray arr = (jobjectArray)obj; int stringCount = env->GetArrayLength(arr); - //print_line("String array! " + String::num(stringCount)); PoolVector<String> sarr; for (int i = 0; i < stringCount; i++) { @@ -380,7 +378,6 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) { Array vals = _jobject_to_variant(env, arr); env->DeleteLocalRef(arr); - //print_line("adding " + String::num(keys.size()) + " to Dictionary!"); for (int i = 0; i < keys.size(); i++) { ret[keys[i]] = vals[i]; @@ -411,7 +408,6 @@ class JNISingleton : public Object { public: virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { - //print_line("attempt to call "+String(p_method)); ERR_FAIL_COND_V(!instance, Variant()); r_error.error = Variant::CallError::CALL_OK; @@ -419,7 +415,6 @@ public: Map<StringName, MethodData>::Element *E = method_map.find(p_method); if (!E) { - print_line("no exists"); r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); } @@ -427,7 +422,6 @@ public: int ac = E->get().argtypes.size(); if (ac < p_argcount) { - print_line("fewargs"); r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = ac; return Variant(); @@ -435,7 +429,6 @@ public: if (ac > p_argcount) { - print_line("manyargs"); r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument = ac; return Variant(); @@ -464,7 +457,6 @@ public: ERR_FAIL_COND_V(res != 0, Variant()); - //print_line("argcount "+String::num(p_argcount)); List<jobject> to_erase; for (int i = 0; i < p_argcount; i++) { @@ -474,26 +466,21 @@ public: to_erase.push_back(vr.obj); } - //print_line("calling method!!"); - Variant ret; switch (E->get().ret_type) { case Variant::NIL: { - //print_line("call void"); env->CallVoidMethodA(instance, E->get().method, v); } break; case Variant::BOOL: { ret = env->CallBooleanMethodA(instance, E->get().method, v) == JNI_TRUE; - //print_line("call bool"); } break; case Variant::INT: { ret = env->CallIntMethodA(instance, E->get().method, v); - //print_line("call int"); } break; case Variant::REAL: { @@ -544,7 +531,6 @@ public: case Variant::DICTIONARY: { - //print_line("call dictionary"); jobject obj = env->CallObjectMethodA(instance, E->get().method, v); ret = _jobject_to_variant(env, obj); env->DeleteLocalRef(obj); @@ -552,7 +538,6 @@ public: } break; default: { - print_line("failure.."); env->PopLocalFrame(NULL); ERR_FAIL_V(Variant()); } break; @@ -564,7 +549,6 @@ public: } env->PopLocalFrame(NULL); - //print_line("success"); return ret; } @@ -757,8 +741,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobject p_asset_manager, jboolean p_use_apk_expansion) { - __android_log_print(ANDROID_LOG_INFO, "godot", "**INIT EVENT! - %p\n", env); - initialized = true; JavaVM *jvm; @@ -767,8 +749,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en _godot_instance = env->NewGlobalRef(activity); //_godot_instance=activity; - __android_log_print(ANDROID_LOG_INFO, "godot", "***************** HELLO FROM JNI!!!!!!!!"); - { //setup IO Object @@ -776,17 +756,12 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en if (cls) { cls = (jclass)env->NewGlobalRef(cls); - __android_log_print(ANDROID_LOG_INFO, "godot", "*******CLASS FOUND!!!"); } - __android_log_print(ANDROID_LOG_INFO, "godot", "STEP2, %p", cls); jfieldID fid = env->GetStaticFieldID(cls, "io", "Lorg/godotengine/godot/GodotIO;"); - __android_log_print(ANDROID_LOG_INFO, "godot", "STEP3 %i", fid); jobject ob = env->GetStaticObjectField(cls, fid); - __android_log_print(ANDROID_LOG_INFO, "godot", "STEP4, %p", ob); jobject gob = env->NewGlobalRef(ob); - __android_log_print(ANDROID_LOG_INFO, "godot", "STEP4.5, %p", gob); godot_io = gob; _on_video_init = env->GetMethodID(cls, "onVideoInit", "(Z)V"); @@ -831,9 +806,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en char wd[500]; getcwd(wd, 500); - __android_log_print(ANDROID_LOG_INFO, "godot", "test construction %i\n", tst.a); - __android_log_print(ANDROID_LOG_INFO, "godot", "running from dir %s\n", wd); - //video driver is determined here, because once initialized, it can't be changed // String vd = ProjectSettings::get_singleton()->get("display/driver"); @@ -843,7 +815,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en static void _initialize_java_modules() { if (!ProjectSettings::get_singleton()->has_setting("android/modules")) { - print_line("ANDROID MODULES: Nothing to load, aborting"); + print_line("Android modules: Nothing to load, aborting"); return; } @@ -853,8 +825,6 @@ static void _initialize_java_modules() { return; } Vector<String> mods = modules.split(",", false); - print_line("ANDROID MODULES : " + modules); - __android_log_print(ANDROID_LOG_INFO, "godot", "mod count: %i", mods.size()); if (mods.size()) { @@ -877,7 +847,7 @@ static void _initialize_java_modules() { String m = mods[i]; //jclass singletonClass = env->FindClass(m.utf8().get_data()); - print_line("LOADING MODULE: " + m); + print_line("Loading module: " + m); jstring strClassName = env->NewStringUTF(m.utf8().get_data()); jclass singletonClass = (jclass)env->CallObjectMethod(cls, findClass, strClassName); @@ -888,7 +858,6 @@ static void _initialize_java_modules() { } //singletonClass=(jclass)env->NewGlobalRef(singletonClass); - __android_log_print(ANDROID_LOG_INFO, "godot", "****^*^*?^*^*class data %x", singletonClass); jmethodID initialize = env->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lorg/godotengine/godot/Godot$SingletonBase;"); if (!initialize) { @@ -897,7 +866,6 @@ static void _initialize_java_modules() { ERR_CONTINUE(!initialize); } jobject obj = env->CallStaticObjectMethod(singletonClass, initialize, _godot_instance); - __android_log_print(ANDROID_LOG_INFO, "godot", "****^*^*?^*^*class instance %x", obj); jobject gob = env->NewGlobalRef(obj); } } @@ -906,8 +874,6 @@ static void _initialize_java_modules() { JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jobject obj, jobjectArray p_cmdline) { ThreadAndroid::setup_thread(); - __android_log_print(ANDROID_LOG_INFO, "godot", "**SETUP"); - const char **cmdline = NULL; int cmdlen = 0; bool use_apk_expansion = false; @@ -921,20 +887,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo jstring string = (jstring)env->GetObjectArrayElement(p_cmdline, i); const char *rawString = env->GetStringUTFChars(string, 0); - if (!rawString) { - __android_log_print(ANDROID_LOG_INFO, "godot", "cmdline arg %i is null\n", i); - } else { - //__android_log_print(ANDROID_LOG_INFO,"godot","cmdline arg %i is: %s\n",i,rawString); - - if (strcmp(rawString, "--main-pack") == 0) - use_apk_expansion = true; + if (rawString && strcmp(rawString, "--main-pack") == 0) { + use_apk_expansion = true; } cmdline[i] = rawString; } } } - __android_log_print(ANDROID_LOG_INFO, "godot", "CMDLINE LEN %i - APK EXPANSION %i\n", cmdlen, int(use_apk_expansion)); Error err = Main::setup("apk", cmdlen, (char **)cmdline, false); if (cmdline) { @@ -942,10 +902,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo } if (err != OK) { - __android_log_print(ANDROID_LOG_INFO, "godot", "*****UNABLE TO SETUP"); return; //should exit instead and print the error } - __android_log_print(ANDROID_LOG_INFO, "godot", "*****SETUP OK"); java_class_wrapper = memnew(JavaClassWrapper(_godot_instance)); Engine::get_singleton()->add_singleton(Engine::Singleton("JavaClassWrapper", java_class_wrapper)); @@ -954,7 +912,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height, jboolean reload) { - __android_log_print(ANDROID_LOG_INFO, "godot", "^_^_^_^_^ resize %lld, %i, %i\n", Thread::get_caller_id(), width, height); if (os_android) os_android->set_display_size(Size2(width, height)); @@ -968,8 +925,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, j JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits) { - __android_log_print(ANDROID_LOG_INFO, "godot", "^_^_^_^_^ newcontext %lld\n", Thread::get_caller_id()); - if (os_android) { os_android->set_context_is_16_bits(!p_32_bits); } @@ -986,7 +941,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, job JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj) { if (step == 0) { - __android_log_print(ANDROID_LOG_INFO, "godot", "**FIRST_STEP"); // Since Godot is initialized on the UI thread, _main_thread_id was set to that thread's id, // but for Godot purposes, the main thread is the one running the game loop @@ -1004,8 +958,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job ++step; } - //__android_log_print(ANDROID_LOG_INFO,"godot","**STEP EVENT! - %p-%i\n",env,Thread::get_caller_id()); - os_android->process_accelerometer(accelerometer); os_android->process_gravity(gravity); @@ -1019,14 +971,11 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job jclass cls = env->FindClass("org/godotengine/godot/Godot"); jmethodID _finish = env->GetMethodID(cls, "forceQuit", "()V"); env->CallVoidMethod(_godot_instance, _finish); - __android_log_print(ANDROID_LOG_INFO, "godot", "**FINISH REQUEST!!! - %p-%i\n", env, Thread::get_caller_id()); } } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions) { - //__android_log_print(ANDROID_LOG_INFO,"godot","**TOUCH EVENT! - %p-%i\n",env,Thread::get_caller_id()); - Vector<OS_Android::TouchPos> points; for (int i = 0; i < count; i++) { @@ -1292,7 +1241,6 @@ static unsigned int android_get_keysym(unsigned int p_code) { for (int i = 0; _ak_to_keycode[i].keysym != KEY_UNKNOWN; i++) { if (_ak_to_keycode[i].keycode == p_code) { - //print_line("outcode: " + _ak_to_keycode[i].keysym); return _ak_to_keycode[i].keysym; } @@ -1362,8 +1310,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobj ievent->set_unicode(val); ievent->set_pressed(p_pressed); - print_line("Scancode: " + String::num(p_scancode) + ":" + String::num(ievent->get_scancode()) + " Unicode: " + String::num(val)); - if (val == '\n') { ievent->set_scancode(KEY_ENTER); } else if (val == 61448) { @@ -1527,7 +1473,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv *env, j jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data()); if (!mid) { - print_line("FAILED GETTING METHOID " + mname); + print_line("Failed getting method ID " + mname); } s->add_method(mname, mid, types, get_jni_type(retval)); @@ -1578,16 +1524,12 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * int count = env->GetArrayLength(params); Variant args[VARIANT_ARG_MAX]; - //print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count)); - for (int i = 0; i < MIN(count, VARIANT_ARG_MAX); i++) { jobject obj = env->GetObjectArrayElement(params, i); if (obj) args[i] = _jobject_to_variant(env, obj); env->DeleteLocalRef(obj); - - //print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type())); }; obj->call_deferred(str_method, args[0], args[1], args[2], args[3], args[4]); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 67ce796279..5557c1de44 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -130,8 +130,6 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int if (gfx_init_func) gfx_init_func(gfx_init_ud, use_gl2); - AudioDriverManager::add_driver(&audio_driver_android); - RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); @@ -775,6 +773,8 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI Vector<Logger *> loggers; loggers.push_back(memnew(AndroidLogger)); _set_logger(memnew(CompositeLogger(loggers))); + + AudioDriverManager::add_driver(&audio_driver_android); } OS_Android::~OS_Android() { diff --git a/platform/iphone/icloud.mm b/platform/iphone/icloud.mm index 7508a480ce..a9748bf562 100644 --- a/platform/iphone/icloud.mm +++ b/platform/iphone/icloud.mm @@ -131,6 +131,8 @@ Variant nsobject_to_variant(NSObject *object) { return Variant([num floatValue]); } else if (strcmp([num objCType], @encode(double)) == 0) { return Variant((float)[num doubleValue]); + } else { + return Variant(); } } else if ([object isKindOfClass:[NSDate class]]) { //this is a type that icloud supports...but how did you submit it in the first place? diff --git a/platform/iphone/in_app_store.h b/platform/iphone/in_app_store.h index 7d53eaae20..353438676d 100644 --- a/platform/iphone/in_app_store.h +++ b/platform/iphone/in_app_store.h @@ -46,6 +46,7 @@ class InAppStore : public Object { public: Error request_product_info(Variant p_params); + Error restore_purchases(); Error purchase(Variant p_params); int get_pending_event_count(); diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm index 9bb3d7d3fa..6fa189e917 100644 --- a/platform/iphone/in_app_store.mm +++ b/platform/iphone/in_app_store.mm @@ -63,6 +63,7 @@ InAppStore *InAppStore::instance = NULL; void InAppStore::_bind_methods() { ClassDB::bind_method(D_METHOD("request_product_info"), &InAppStore::request_product_info); + ClassDB::bind_method(D_METHOD("restore_purchases"), &InAppStore::restore_purchases); ClassDB::bind_method(D_METHOD("purchase"), &InAppStore::purchase); ClassDB::bind_method(D_METHOD("get_pending_event_count"), &InAppStore::get_pending_event_count); @@ -153,6 +154,14 @@ Error InAppStore::request_product_info(Variant p_params) { return OK; }; +Error InAppStore::restore_purchases() { + + printf("restoring purchases!\n"); + [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; + + return OK; +}; + @interface TransObserver : NSObject <SKPaymentTransactionObserver> { }; @end @@ -236,6 +245,11 @@ Error InAppStore::request_product_info(Variant p_params) { printf("status transaction restored!\n"); String pid = String::utf8([transaction.originalTransaction.payment.productIdentifier UTF8String]); InAppStore::get_singleton()->_record_purchase(pid); + Dictionary ret; + ret["type"] = "restore"; + ret["result"] = "ok"; + ret["product_id"] = pid; + InAppStore::get_singleton()->_post_event(ret); [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; } break; default: { diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index c284ab6905..c4c59431f2 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -123,7 +123,6 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p // reset this to what it should be, it will have been set to 0 after visual_server->init() is called RasterizerStorageGLES3::system_fbo = gl_view_base_fb; - AudioDriverManager::add_driver(&audio_driver); AudioDriverManager::initialize(p_audio_driver); input = memnew(InputDefault); @@ -632,6 +631,8 @@ OSIPhone::OSIPhone(int width, int height, String p_data_dir) { loggers.push_back(memnew(StdLogger)); #endif _set_logger(memnew(CompositeLogger(loggers))); + + AudioDriverManager::add_driver(&audio_driver); }; OSIPhone::~OSIPhone() { diff --git a/platform/iphone/platform_config.h b/platform/iphone/platform_config.h index d205c7da83..d9fd61fb6e 100644 --- a/platform/iphone/platform_config.h +++ b/platform/iphone/platform_config.h @@ -30,6 +30,7 @@ #include <alloca.h> +#define GLES2_INCLUDE_H <ES2/gl.h> #define GLES3_INCLUDE_H <ES3/gl.h> #define PLATFORM_REFCOUNT diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 7e6a1518ed..ad6b710382 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -65,13 +65,14 @@ def configure(env): elif (env["target"] == "release_debug"): env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED']) - env.Append(LINKFLAGS=['-O2', '-s', 'ASSERTIONS=1']) + env.Append(LINKFLAGS=['-O2']) # retain function names at the cost of file size, for backtraces and profiling env.Append(LINKFLAGS=['--profiling-funcs']) elif (env["target"] == "debug"): env.Append(CCFLAGS=['-O1', '-D_DEBUG', '-g', '-DDEBUG_ENABLED']) env.Append(LINKFLAGS=['-O1', '-g']) + env.Append(LINKFLAGS=['-s', 'ASSERTIONS=1']) ## Compiler configuration @@ -102,7 +103,7 @@ def configure(env): ## Compile flags env.Append(CPPPATH=['#platform/javascript']) - env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DPTHREAD_NO_RENAME', '-DTYPED_METHOD_BIND', '-DNO_THREADS']) + env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DTYPED_METHOD_BIND', '-DNO_THREADS']) env.Append(CPPFLAGS=['-DGLES3_ENABLED']) # These flags help keep the file size down diff --git a/platform/javascript/engine.js b/platform/javascript/engine.js index bca1851f40..e6fb48d0d2 100644 --- a/platform/javascript/engine.js +++ b/platform/javascript/engine.js @@ -138,18 +138,6 @@ } var actualCanvas = this.rtenv.canvas; - var testContext = false; - var testCanvas; - try { - testCanvas = document.createElement('canvas'); - testContext = testCanvas.getContext('webgl2') || testCanvas.getContext('experimental-webgl2'); - } catch (e) {} - if (!testContext) { - throw new Error("WebGL 2 not available"); - } - testCanvas = null; - testContext = null; - // canvas can grab focus on click if (actualCanvas.tabIndex < 0) { actualCanvas.tabIndex = 0; @@ -273,6 +261,20 @@ Engine.RuntimeEnvironment = engine.RuntimeEnvironment; + Engine.isWebGLAvailable = function(majorVersion = 1) { + + var testContext = false; + try { + var testCanvas = document.createElement('canvas'); + if (majorVersion === 1) { + testContext = testCanvas.getContext('webgl') || testCanvas.getContext('experimental-webgl'); + } else if (majorVersion === 2) { + testContext = testCanvas.getContext('webgl2') || testCanvas.getContext('experimental-webgl2'); + } + } catch (e) {} + return !!testContext; + }; + Engine.load = function(newBasePath) { if (newBasePath !== undefined) basePath = getBasePath(newBasePath); diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index e226ab6332..cbfe99ba2d 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -33,6 +33,7 @@ #include "core/engine.h" #include "core/io/file_access_buffered_fa.h" #include "dom_keys.h" +#include "drivers/gles2/rasterizer_gles2.h" #include "drivers/gles3/rasterizer_gles3.h" #include "drivers/unix/dir_access_unix.h" #include "drivers/unix/file_access_unix.h" @@ -57,12 +58,19 @@ static void dom2godot_mod(T emscripten_event_ptr, Ref<InputEventWithModifiers> g int OS_JavaScript::get_video_driver_count() const { - return 1; + return VIDEO_DRIVER_MAX; } const char *OS_JavaScript::get_video_driver_name(int p_driver) const { - return "GLES3"; + switch (p_driver) { + case VIDEO_DRIVER_GLES3: + return "GLES3"; + case VIDEO_DRIVER_GLES2: + return "GLES2"; + } + ERR_EXPLAIN("Invalid video driver index " + itos(p_driver)); + ERR_FAIL_V(NULL); } int OS_JavaScript::get_audio_driver_count() const { @@ -422,8 +430,21 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, emscripten_webgl_init_context_attributes(&attributes); attributes.alpha = false; attributes.antialias = false; - attributes.majorVersion = 2; + ERR_FAIL_INDEX_V(p_video_driver, VIDEO_DRIVER_MAX, ERR_INVALID_PARAMETER); + switch (p_video_driver) { + case VIDEO_DRIVER_GLES3: + attributes.majorVersion = 2; + RasterizerGLES3::register_config(); + RasterizerGLES3::make_current(); + break; + case VIDEO_DRIVER_GLES2: + attributes.majorVersion = 1; + RasterizerGLES2::register_config(); + RasterizerGLES2::make_current(); + break; + } EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(NULL, &attributes); + ERR_EXPLAIN("WebGL " + itos(attributes.majorVersion) + ".0 not available"); ERR_FAIL_COND_V(emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS, ERR_UNAVAILABLE); video_mode = p_desired; @@ -447,12 +468,8 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, print_line("Init Audio"); - AudioDriverManager::add_driver(&audio_driver_javascript); AudioDriverManager::initialize(p_audio_driver); - RasterizerGLES3::register_config(); - RasterizerGLES3::make_current(); - print_line("Init VS"); visual_server = memnew(VisualServerRaster()); @@ -1012,6 +1029,8 @@ OS_JavaScript::OS_JavaScript(const char *p_execpath, GetUserDataDirFunc p_get_us Vector<Logger *> loggers; loggers.push_back(memnew(StdLogger)); _set_logger(memnew(CompositeLogger(loggers))); + + AudioDriverManager::add_driver(&audio_driver_javascript); } OS_JavaScript::~OS_JavaScript() { diff --git a/platform/osx/SCsub b/platform/osx/SCsub index 5efe2d0b22..4dfa46528a 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -7,10 +7,10 @@ def make_debug(target, source, env): if (env["macports_clang"] != 'no'): mpprefix = os.environ.get("MACPORTS_PREFIX", "/opt/local") mpclangver = env["macports_clang"] - os.system(mpprefix + '/libexec/llvm-' + mpclangver + '/bin/llvm-dsymutil %s -o %s.dSYM' % (target[0], target[0])) + os.system(mpprefix + '/libexec/llvm-' + mpclangver + '/bin/llvm-dsymutil {0} -o {0}.dSYM'.format(target[0])) else: - os.system('dsymutil %s -o %s.dSYM' % (target[0], target[0])) - os.system('strip -u -r %s' % (target[0])) + os.system('dsymutil {0} -o {0}.dSYM'.format(target[0])) + os.system('strip -u -r {0}'.format(target[0])) files = [ 'crash_handler_osx.mm', diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm index d757674a9b..99ce25adfb 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/osx/crash_handler_osx.mm @@ -35,8 +35,7 @@ #include <string.h> #include <unistd.h> -// Note: Dump backtrace in 32bit mode is getting a bus error on the fgets by the ->execute, so enable only on 64bit -#if defined(DEBUG_ENABLED) && defined(__x86_64__) +#if defined(DEBUG_ENABLED) #define CRASH_HANDLER_ENABLED 1 #endif @@ -50,13 +49,8 @@ #include <mach-o/dyld.h> #include <mach-o/getsect.h> -#ifdef __x86_64__ static uint64_t load_address() { const struct segment_command_64 *cmd = getsegbyname("__TEXT"); -#else -static uint32_t load_address() { - const struct segment_command *cmd = getsegbyname("__TEXT"); -#endif char full_path[1024]; uint32_t size = sizeof(full_path); @@ -120,11 +114,7 @@ static void handle_crash(int sig) { args.push_back("-o"); args.push_back(_execpath); args.push_back("-arch"); -#ifdef __x86_64__ args.push_back("x86_64"); -#else - args.push_back("i386"); -#endif args.push_back("-l"); snprintf(str, 1024, "%p", load_addr); args.push_back(str); diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 5f33100e42..e51a8082f7 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -57,22 +57,15 @@ def configure(env): ## Architecture - is64 = sys.maxsize > 2**32 - if (env["bits"] == "default"): - env["bits"] = "64" if is64 else "32" + # Mac OS X no longer runs on 32-bit since 10.7 which is unsupported since 2014 + # As such, we only support 64-bit + env["bits"] = "64" ## Compiler configuration if "OSXCROSS_ROOT" not in os.environ: # regular native build - if (env["bits"] == "fat"): - env.Append(CCFLAGS=['-arch', 'i386', '-arch', 'x86_64']) - env.Append(LINKFLAGS=['-arch', 'i386', '-arch', 'x86_64']) - elif (env["bits"] == "32"): - env.Append(CCFLAGS=['-arch', 'i386']) - env.Append(LINKFLAGS=['-arch', 'i386']) - else: # 64-bit, default - env.Append(CCFLAGS=['-arch', 'x86_64']) - env.Append(LINKFLAGS=['-arch', 'x86_64']) + env.Append(CCFLAGS=['-arch', 'x86_64']) + env.Append(LINKFLAGS=['-arch', 'x86_64']) if (env["macports_clang"] != 'no'): mpprefix = os.environ.get("MACPORTS_PREFIX", "/opt/local") mpclangver = env["macports_clang"] @@ -86,14 +79,7 @@ def configure(env): else: # osxcross build root = os.environ.get("OSXCROSS_ROOT", 0) - if env["bits"] == "fat": - basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-" - env.Append(CCFLAGS=['-arch', 'i386', '-arch', 'x86_64']) - env.Append(LINKFLAGS=['-arch', 'i386', '-arch', 'x86_64']) - elif env["bits"] == "32": - basecmd = root + "/target/bin/i386-apple-" + env["osxcross_sdk"] + "-" - else: # 64-bit, default - basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-" + basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-" ccache_path = os.environ.get("CCACHE") if ccache_path == None: diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index c4efa1f0ff..db265812fa 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -101,15 +101,7 @@ void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset> r_features->push_back("etc2"); } - int bits = p_preset->get("application/bits_mode"); - - if (bits == 0 || bits == 1) { - r_features->push_back("64"); - } - - if (bits == 0 || bits == 2) { - r_features->push_back("32"); - } + r_features->push_back("64"); } void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) { @@ -125,7 +117,6 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/bits_mode", PROPERTY_HINT_ENUM, "Fat (32 & 64 bits),64 bits,32 bits"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false)); #ifdef OSX_ENABLED @@ -323,11 +314,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN); int ret = unzGoToFirstFile(src_pkg_zip); - String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + "."; - int bits_mode = p_preset->get("application/bits_mode"); - binary_to_use += String(bits_mode == 0 ? "fat" : bits_mode == 1 ? "64" : "32"); + String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64"; - print_line("binary: " + binary_to_use); String pkg_name; if (p_preset->get("application/name") != "") pkg_name = p_preset->get("application/name"); // app_name @@ -508,7 +496,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p if (use_dmg()) { String pack_path = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck"; Vector<SharedObject> shared_objects; - Error err = save_pack(p_preset, pack_path, &shared_objects); + err = save_pack(p_preset, pack_path, &shared_objects); // see if we can code sign our new package String identity = p_preset->get("codesign/identity"); @@ -516,7 +504,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p if (err == OK) { DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < shared_objects.size(); i++) { - da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file()); + err = da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file()); if (err == OK && identity != "") { err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file()); } @@ -561,7 +549,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p String pack_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".pck"); Vector<SharedObject> shared_objects; - Error err = save_pack(p_preset, pack_path, &shared_objects); + err = save_pack(p_preset, pack_path, &shared_objects); if (err == OK) { zipOpenNewFileInZip(dst_pkg_zip, @@ -593,7 +581,9 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p } else { err = ERR_CANT_OPEN; } + } + if (err == OK) { //add shared objects for (int i = 0; i < shared_objects.size(); i++) { Vector<uint8_t> file = FileAccess::get_file_as_array(shared_objects[i].path); @@ -621,26 +611,32 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p zipClose(dst_pkg_zip, NULL); } - return OK; + return err; } bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { - bool valid = true; + bool valid = false; String err; - if (!exists_export_template("osx.zip", &err)) { - valid = false; + if (exists_export_template("osx.zip", &err)) { + valid = true; } - if (p_preset->get("custom_package/debug") != "" && !FileAccess::exists(p_preset->get("custom_package/debug"))) { - valid = false; - err += "Custom debug package not found.\n"; + if (p_preset->get("custom_package/debug") != "") { + if (FileAccess::exists(p_preset->get("custom_package/debug"))) { + valid = true; + } else { + err += "Custom debug package not found.\n"; + } } - if (p_preset->get("custom_package/release") != "" && !FileAccess::exists(p_preset->get("custom_package/release"))) { - valid = false; - err += "Custom release package not found.\n"; + if (p_preset->get("custom_package/release") != "") { + if (FileAccess::exists(p_preset->get("custom_package/release"))) { + valid = true; + } else { + err += "Custom release package not found.\n"; + } } if (!err.empty()) diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index aa8db8f300..72ca8969d0 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -100,7 +100,7 @@ public: id context; CursorShape cursor_shape; - NSCursor *cursors[CURSOR_MAX] = { NULL }; + NSCursor *cursors[CURSOR_MAX]; MouseMode mouse_mode; String title; @@ -134,9 +134,6 @@ public: void _update_window(); protected: - virtual int get_video_driver_count() const; - virtual const char *get_video_driver_name(int p_driver) const; - virtual void initialize_core(); virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void finalize(); @@ -198,6 +195,7 @@ public: virtual VideoMode get_video_mode(int p_screen = 0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const; + virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool p_read_stderr); virtual String get_executable_path() const; virtual LatinKeyboardVariant get_latin_keyboard_variant() const; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 4c459772aa..0e7c0f1a4e 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -31,6 +31,7 @@ #include "os_osx.h" #include "dir_access_osx.h" +#include "drivers/gles2/rasterizer_gles2.h" #include "drivers/gles3/rasterizer_gles3.h" #include "main/main.h" #include "os/keyboard.h" @@ -149,10 +150,44 @@ static Vector2 get_mouse_pos(NSEvent *event) { @end @interface GodotApplicationDelegate : NSObject +- (void)forceUnbundledWindowActivationHackStep1; +- (void)forceUnbundledWindowActivationHackStep2; +- (void)forceUnbundledWindowActivationHackStep3; @end @implementation GodotApplicationDelegate +- (void)forceUnbundledWindowActivationHackStep1 { + // Step1: Switch focus to macOS Dock. + // Required to perform step 2, TransformProcessType will fail if app is already the in focus. + for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) { + [app activateWithOptions:NSApplicationActivateIgnoringOtherApps]; + break; + } + [self performSelector:@selector(forceUnbundledWindowActivationHackStep2) withObject:nil afterDelay:0.02]; +} + +- (void)forceUnbundledWindowActivationHackStep2 { + // Step 2: Register app as foreground process. + ProcessSerialNumber psn = { 0, kCurrentProcess }; + (void)TransformProcessType(&psn, kProcessTransformToForegroundApplication); + + [self performSelector:@selector(forceUnbundledWindowActivationHackStep3) withObject:nil afterDelay:0.02]; +} + +- (void)forceUnbundledWindowActivationHackStep3 { + // Step 3: Switch focus back to app window. + [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps]; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)notice { + NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; + if (nsappname == nil) { + // If executable is not a bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored). + [self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02]; + } +} + - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { // Note: called before main loop init! char *utfs = strdup([filename UTF8String]); @@ -228,6 +263,7 @@ static Vector2 get_mouse_pos(NSEvent *event) { NSWindow *window = (NSWindow *)[notification object]; CGFloat newBackingScaleFactor = [window backingScaleFactor]; CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; + [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; if (newBackingScaleFactor != oldBackingScaleFactor) { //Set new display scale and window size @@ -991,15 +1027,6 @@ void OS_OSX::set_ime_position(const Point2 &p_pos) { im_position = p_pos; } -int OS_OSX::get_video_driver_count() const { - return 1; -} - -const char *OS_OSX::get_video_driver_name(int p_driver) const { - - return "GLES3"; -} - void OS_OSX::initialize_core() { crash_handler.initialize(); @@ -1092,7 +1119,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a unsigned int attributeCount = 0; - // OS X needs non-zero color size, so set resonable values + // OS X needs non-zero color size, so set reasonable values int colorBits = 32; // Fail if a robustness strategy was requested @@ -1111,8 +1138,12 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a ADD_ATTR(NSOpenGLPFADoubleBuffer); ADD_ATTR(NSOpenGLPFAClosestPolicy); - //we now need OpenGL 3 or better, maybe even change this to 3_3Core ? - ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); + if (p_video_driver == VIDEO_DRIVER_GLES2) { + ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy); + } else { + //we now need OpenGL 3 or better, maybe even change this to 3_3Core ? + ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); + } ADD_ATTR2(NSOpenGLPFAColorSize, colorBits); @@ -1138,7 +1169,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a */ // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB - // frambuffer, so there's no need (and no way) to request it + // framebuffer, so there's no need (and no way) to request it ADD_ATTR(0); @@ -1169,13 +1200,14 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a /*** END OSX INITIALIZATION ***/ - bool use_gl2 = p_video_driver != 1; - - AudioDriverManager::add_driver(&audio_driver); - // only opengl support here... - RasterizerGLES3::register_config(); - RasterizerGLES3::make_current(); + if (p_video_driver == VIDEO_DRIVER_GLES2) { + RasterizerGLES2::register_config(); + RasterizerGLES2::make_current(); + } else { + RasterizerGLES3::register_config(); + RasterizerGLES3::make_current(); + } visual_server = memnew(VisualServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { @@ -2014,6 +2046,55 @@ bool OS_OSX::get_borderless_window() { return [window_object styleMask] == NSWindowStyleMaskBorderless; } +Error OS_OSX::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool p_read_stderr) { + + NSTask *task = [[NSTask alloc] init]; + NSPipe *stdout_pipe = nil; + [task setLaunchPath:[NSString stringWithUTF8String:p_path.utf8().get_data()]]; + + NSMutableArray *arguments = [[NSMutableArray alloc] initWithCapacity:p_arguments.size()]; + for (int i = 0; i < p_arguments.size(); i++) { + [arguments addObject:[NSString stringWithUTF8String:p_arguments[i].utf8().get_data()]]; + } + [task setArguments:arguments]; + + if (p_blocking && r_pipe) { + stdout_pipe = [NSPipe pipe]; + [task setStandardOutput:stdout_pipe]; + if (p_read_stderr) [task setStandardError:[task standardOutput]]; + } + + @try { + [task launch]; + if (r_child_id) + *r_child_id = [task processIdentifier]; + + if (p_blocking) { + if (r_pipe) { + NSFileHandle *read_handle = [stdout_pipe fileHandleForReading]; + NSData *data = nil; + while ((data = [read_handle availableData]) && [data length]) { + NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + (*r_pipe) += [string UTF8String]; + [string release]; + } + } else { + [task waitUntilExit]; + } + } + + [arguments release]; + [task release]; + return OK; + } @catch (NSException *exception) { + ERR_PRINTS("NSException: " + String([exception reason].UTF8String) + "; Path: " + p_path); + + [arguments release]; + [task release]; + return ERR_CANT_OPEN; + } +} + String OS_OSX::get_executable_path() const { int ret; @@ -2289,6 +2370,7 @@ OS_OSX *OS_OSX::singleton = NULL; OS_OSX::OS_OSX() { + memset(cursors, 0, sizeof(cursors)); key_event_pos = 0; mouse_mode = OS::MOUSE_MODE_VISIBLE; main_loop = NULL; @@ -2325,7 +2407,7 @@ OS_OSX::OS_OSX() { NSMenuItem *menu_item; NSString *title; - NSString *nsappname = [[[NSBundle mainBundle] performSelector:@selector(localizedInfoDictionary)] objectForKey:@"CFBundleName"]; + NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; if (nsappname == nil) nsappname = [[NSProcessInfo processInfo] processName]; @@ -2396,6 +2478,8 @@ OS_OSX::OS_OSX() { [NSApp sendEvent:event]; } + + AudioDriverManager::add_driver(&audio_driver); } bool OS_OSX::_check_internal_feature_support(const String &p_feature) { diff --git a/platform/osx/platform_config.h b/platform/osx/platform_config.h index 1b497cebef..3f72831d77 100644 --- a/platform/osx/platform_config.h +++ b/platform/osx/platform_config.h @@ -31,4 +31,5 @@ #include <alloca.h> #define GLES3_INCLUDE_H "glad/glad.h" +#define GLES2_INCLUDE_H "glad/glad.h" #define PTHREAD_RENAME_SELF diff --git a/platform/server/detect.py b/platform/server/detect.py index fd4b6eae1c..7bf445b43f 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -1,4 +1,5 @@ import os +import platform import sys @@ -22,6 +23,7 @@ def get_opts(): from SCons.Variables import BoolVariable return [ BoolVariable('use_llvm', 'Use the LLVM compiler', False), + BoolVariable('use_static_cpp', 'Link libgcc and libstdc++ statically for better portability', False), ] @@ -122,6 +124,11 @@ def configure(env): if not env['builtin_libogg']: env.ParseConfig('pkg-config ogg --cflags --libs') + # On Linux wchar_t should be 32-bits + # 16-bit library shouldn't be required due to compiler optimisations + if not env['builtin_pcre2']: + env.ParseConfig('pkg-config libpcre2-32 --cflags --libs') + ## Flags # Linkflags below this line should typically stay the last ones @@ -131,4 +138,13 @@ def configure(env): env.Append(CPPPATH=['#platform/server']) env.Append(CPPFLAGS=['-DSERVER_ENABLED', '-DUNIX_ENABLED']) env.Append(LIBS=['pthread']) - env.Append(LIBS=['dl']) + + if (platform.system() == "Linux"): + env.Append(LIBS=['dl']) + + if (platform.system().find("BSD") >= 0): + env.Append(LIBS=['execinfo']) + + # Link those statically for portability + if env['use_static_cpp']: + env.Append(LINKFLAGS=['-static-libgcc', '-static-libstdc++']) diff --git a/platform/server/platform_config.h b/platform/server/platform_config.h index af4cf07393..2fa8eda337 100644 --- a/platform/server/platform_config.h +++ b/platform/server/platform_config.h @@ -28,4 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifdef __linux__ #include <alloca.h> +#endif +#if defined(__FreeBSD__) || defined(__OpenBSD__) +#include <stdlib.h> +#define PTHREAD_BSD_SET_NAME +#endif diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index 7cc8afff06..3ee195e4f9 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -25,8 +25,11 @@ def can_build(): def get_opts(): + from SCons.Variables import BoolVariable return [ + ('msvc_version', 'MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.', None), + BoolVariable('use_mingw', 'Use the Mingw compiler, even if MSVC is installed. Only used on Windows.', False), ] @@ -160,6 +163,7 @@ def configure(env): 'libANGLE', 'libEGL', 'libGLESv2', + 'bcrypt', ] env.Append(LINKFLAGS=[p + ".lib" for p in LIBS]) diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index 620f6c0f24..7d7bee9227 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -1082,7 +1082,7 @@ public: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "zip"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "zip"), "")); - // Capabilites + // Capabilities const char **basic = uwp_capabilities; while (*basic) { r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/" + String(*basic).camelcase_to_underscore(false)), false)); diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 8965b80fb7..ed3827353d 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -9,9 +9,9 @@ def make_debug_mingw(target, source, env): mingw_prefix = env["mingw_prefix_32"] else: mingw_prefix = env["mingw_prefix_64"] - os.system(mingw_prefix + 'objcopy --only-keep-debug %s %s.debugsymbols' % (target[0], target[0])) - os.system(mingw_prefix + 'strip --strip-debug --strip-unneeded %s' % (target[0])) - os.system(mingw_prefix + 'objcopy --add-gnu-debuglink=%s.debugsymbols %s' % (target[0], target[0])) + os.system(mingw_prefix + 'objcopy --only-keep-debug {0} {0}.debugsymbols'.format(target[0])) + os.system(mingw_prefix + 'strip --strip-debug --strip-unneeded {0}'.format(target[0])) + os.system(mingw_prefix + 'objcopy --add-gnu-debuglink={0}.debugsymbols {0}'.format(target[0])) common_win = [ "context_gl_win.cpp", diff --git a/platform/windows/context_gl_win.cpp b/platform/windows/context_gl_win.cpp index 8b57fdd9ce..d312fbcb12 100644 --- a/platform/windows/context_gl_win.cpp +++ b/platform/windows/context_gl_win.cpp @@ -38,6 +38,8 @@ #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_FLAGS_ARB 0x2094 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *); @@ -153,6 +155,7 @@ Error ContextGL_Win::initialize() { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, //we want a 3.3 context WGL_CONTEXT_MINOR_VERSION_ARB, 3, //and it shall be forward compatible so that we can only use up to date functionality + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB /*| _WGL_CONTEXT_DEBUG_BIT_ARB*/, 0 }; //zero indicates the end of the array diff --git a/platform/windows/detect.py b/platform/windows/detect.py index b8a9ed482c..2ce55d98be 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -12,23 +12,17 @@ def get_name(): def can_build(): - if (os.name == "nt"): # Building natively on Windows - if (os.getenv("VCINSTALLDIR")): # MSVC + # If VCINSTALLDIR is set in the OS environ, use traditional Godot logic to set up MSVC + if (os.getenv("VCINSTALLDIR")): # MSVC, manual setup return True - print("MSVC not detected (no VCINSTALLDIR environment variable), attempting MinGW.") - mingw32 = "" - mingw64 = "" - if (os.getenv("MINGW32_PREFIX")): - mingw32 = os.getenv("MINGW32_PREFIX") - if (os.getenv("MINGW64_PREFIX")): - mingw64 = os.getenv("MINGW64_PREFIX") - - test = "gcc --version > NUL 2>&1" - if (os.system(test) == 0 or os.system(mingw32 + test) == 0 or os.system(mingw64 + test) == 0): - return True + # Otherwise, let SCons find MSVC if installed, or else Mingw. + # Since we're just returning True here, if there's no compiler + # installed, we'll get errors when it tries to build with the + # null compiler. + return True if (os.name == "posix"): # Cross-compiling with MinGW-w64 (old MinGW32 is not supported) @@ -70,6 +64,8 @@ def get_opts(): ('target_win_version', 'Targeted Windows version, >= 0x0601 (Windows 7)', '0x0601'), EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')), BoolVariable('separate_debug_symbols', 'Create a separate file with the debug symbols', False), + ('msvc_version', 'MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.', None), + BoolVariable('use_mingw', 'Use the Mingw compiler, even if MSVC is installed. Only used on Windows.', False), ] @@ -98,192 +94,253 @@ def build_res_file(target, source, env): return 0 -def configure(env): - - env.Append(CPPPATH=['#platform/windows']) - - if (os.name == "nt" and os.getenv("VCINSTALLDIR")): # MSVC +def setup_msvc_manual(env): + """Set up env to use MSVC manually, using VCINSTALLDIR""" + if (env["bits"] != "default"): + print(""" + Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console + (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits + argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you. + """) + raise SCons.Errors.UserError("Bits argument should not be used when using VCINSTALLDIR") + + # Force bits arg + # (Actually msys2 mingw can support 64-bit, we could detect that) + env["bits"] = "32" + env["x86_libtheora_opt_vc"] = True + + # find compiler manually + compiler_version_str = methods.detect_visual_c_compiler_version(env['ENV']) + print("Found MSVC compiler: " + compiler_version_str) + + # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writing)... vc compiler for 64bit can not compile _asm + if(compiler_version_str == "amd64" or compiler_version_str == "x86_amd64"): + env["bits"] = "64" + env["x86_libtheora_opt_vc"] = False + print("Compiled program architecture will be a 64 bit executable (forcing bits=64).") + elif (compiler_version_str == "x86" or compiler_version_str == "amd64_x86"): + print("Compiled program architecture will be a 32 bit executable. (forcing bits=32).") + else: + print("Failed to manually detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup, or avoid setting VCINSTALLDIR.") + +def setup_msvc_auto(env): + """Set up MSVC using SCons's auto-detection logic""" + + # If MSVC_VERSION is set by SCons, we know MSVC is installed. + # But we may want a different version or target arch. + + # The env may have already been set up with default MSVC tools, so + # reset a few things so we can set it up with the tools we want. + # (Ideally we'd decide on the tool config before configuring any + # environment, and just set the env up once, but this function runs + # on an existing env so this is the simplest way.) + env['MSVC_SETUP_RUN'] = False # Need to set this to re-run the tool + env['MSVS_VERSION'] = None + env['MSVC_VERSION'] = None + env['TARGET_ARCH'] = None + if env['bits'] != 'default': + env['TARGET_ARCH'] = {'32': 'x86', '64': 'x86_64'}[env['bits']] + if env.has_key('msvc_version'): + env['MSVC_VERSION'] = env['msvc_version'] + env.Tool('msvc') + env.Tool('mssdk') # we want the MS SDK + # Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015 + # Get actual target arch into bits (it may be "default" at this point): + if env['TARGET_ARCH'] in ('amd64', 'x86_64'): + env['bits'] = 64 + else: + env['bits'] = 32 + print(" Found MSVC version %s, arch %s, bits=%s" % (env['MSVC_VERSION'], env['TARGET_ARCH'], env['bits'])) + if env['TARGET_ARCH'] in ('amd64', 'x86_64'): + env["x86_libtheora_opt_vc"] = False + +def setup_mingw(env): + """Set up env for use with mingw""" + # Nothing to do here + print("Using Mingw") + pass + +def configure_msvc(env, manual_msvc_config): + """Configure env to work with MSVC""" + + # Build type + + if (env["target"] == "release"): + env.Append(CCFLAGS=['/O2']) + env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) + env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup']) + + elif (env["target"] == "release_debug"): + env.Append(CCFLAGS=['/O2']) + env.AppendUnique(CPPDEFINES = ['DEBUG_ENABLED']) + env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + + elif (env["target"] == "debug_release"): + env.Append(CCFLAGS=['/Z7', '/Od']) + env.Append(LINKFLAGS=['/DEBUG']) + env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) + env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup']) + + elif (env["target"] == "debug"): + env.AppendUnique(CCFLAGS=['/Z7', '/Od', '/EHsc']) + env.AppendUnique(CPPDEFINES = ['DEBUG_ENABLED', 'DEBUG_MEMORY_ENABLED', + 'D3D_DEBUG_INFO']) + env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + env.Append(LINKFLAGS=['/DEBUG']) + + ## Compile/link flags + + env.AppendUnique(CCFLAGS=['/MT', '/Gd', '/GR', '/nologo']) + env.AppendUnique(CXXFLAGS=['/TP']) # assume all sources are C++ + if manual_msvc_config: # should be automatic if SCons found it + env.Append(CPPPATH=[os.getenv("WindowsSdkDir") + "/Include"]) + + env.AppendUnique(CPPDEFINES = ['WINDOWS_ENABLED', 'OPENGL_ENABLED', + 'RTAUDIO_ENABLED', 'WASAPI_ENABLED', + 'TYPED_METHOD_BIND', 'WIN32', 'MSVC', + {'WINVER' : '$target_win_version', + '_WIN32_WINNT': '$target_win_version'}]) + if env["bits"] == "64": + env.AppendUnique(CPPDEFINES=['_WIN64']) + + ## Libs + + LIBS = ['winmm', 'opengl32', 'dsound', 'kernel32', 'ole32', 'oleaut32', + 'user32', 'gdi32', 'IPHLPAPI', 'Shlwapi', 'wsock32', 'Ws2_32', + 'shell32', 'advapi32', 'dinput8', 'dxguid', 'imm32', 'bcrypt'] + env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS]) + + if manual_msvc_config: + env.Append(LIBPATH=[os.getenv("WindowsSdkDir") + "/Lib"]) - env['ENV']['TMP'] = os.environ['TMP'] + ## LTO - ## Build type - - if (env["target"] == "release"): - env.Append(CCFLAGS=['/O2']) - env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) - env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup']) - - elif (env["target"] == "release_debug"): - env.Append(CCFLAGS=['/O2', '/DDEBUG_ENABLED']) - env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) - - elif (env["target"] == "debug_release"): - env.Append(CCFLAGS=['/Z7', '/Od']) - env.Append(LINKFLAGS=['/DEBUG']) - env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) - env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup']) - - elif (env["target"] == "debug"): - env.Append(CCFLAGS=['/Z7', '/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED', '/DD3D_DEBUG_INFO', '/Od', '/EHsc']) - env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) - env.Append(LINKFLAGS=['/DEBUG']) - - ## Architecture - - # Note: this detection/override code from here onward should be here instead of in SConstruct because it's platform and compiler specific (MSVC/Windows) - if (env["bits"] != "default"): - print("Error: bits argument is disabled for MSVC") - print(""" - Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console - (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits - argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you. - """) - sys.exit() - - # Forcing bits argument because MSVC does not have a flag to set this through SCons... it's different compilers (cl.exe's) called from the proper command prompt - # that decide the architecture that is build for. Scons can only detect the os.getenviron (because vsvarsall.bat sets a lot of stuff for cl.exe to work with) - env["bits"] = "32" - env["x86_libtheora_opt_vc"] = True - - ## Compiler configuration - - env['ENV'] = os.environ - # This detection function needs the tools env (that is env['ENV'], not SCons's env), and that is why it's this far bellow in the code - compiler_version_str = methods.detect_visual_c_compiler_version(env['ENV']) - - print("Detected MSVC compiler: " + compiler_version_str) - # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writting)... vc compiler for 64bit can not compile _asm - if(compiler_version_str == "amd64" or compiler_version_str == "x86_amd64"): - env["bits"] = "64" - env["x86_libtheora_opt_vc"] = False - print("Compiled program architecture will be a 64 bit executable (forcing bits=64).") - elif (compiler_version_str == "x86" or compiler_version_str == "amd64_x86"): - print("Compiled program architecture will be a 32 bit executable. (forcing bits=32).") + if (env["use_lto"]): + env.AppendUnique(CCFLAGS=['/GL']) + env.AppendUnique(ARFLAGS=['/LTCG']) + if env["progress"]: + env.AppendUnique(LINKFLAGS=['/LTCG:STATUS']) else: - print("Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup.") + env.AppendUnique(LINKFLAGS=['/LTCG']) - ## Compile flags + if manual_msvc_config: + env.Append(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")]) + env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")]) - env.Append(CCFLAGS=['/MT', '/Gd', '/GR', '/nologo']) - env.Append(CXXFLAGS=['/TP']) - env.Append(CPPFLAGS=['/DMSVC', '/GR', ]) - env.Append(CCFLAGS=['/I' + os.getenv("WindowsSdkDir") + "/Include"]) + # Incremental linking fix + env['BUILDERS']['ProgramOriginal'] = env['BUILDERS']['Program'] + env['BUILDERS']['Program'] = methods.precious_program - env.Append(CCFLAGS=['/DWINDOWS_ENABLED']) - env.Append(CCFLAGS=['/DOPENGL_ENABLED']) - env.Append(CCFLAGS=['/DRTAUDIO_ENABLED']) - env.Append(CCFLAGS=['/DWASAPI_ENABLED']) - env.Append(CCFLAGS=['/DTYPED_METHOD_BIND']) - env.Append(CCFLAGS=['/DWIN32']) - env.Append(CCFLAGS=['/DWINVER=%s' % env['target_win_version'], '/D_WIN32_WINNT=%s' % env['target_win_version']]) - if env["bits"] == "64": - env.Append(CCFLAGS=['/D_WIN64']) +def configure_mingw(env): + # Workaround for MinGW. See: + # http://www.scons.org/wiki/LongCmdLinesOnWin32 + env.use_windows_spawn_fix() - LIBS = ['winmm', 'opengl32', 'dsound', 'kernel32', 'ole32', 'oleaut32', 'user32', 'gdi32', 'IPHLPAPI', 'Shlwapi', 'wsock32', 'Ws2_32', 'shell32', 'advapi32', 'dinput8', 'dxguid', 'imm32'] - env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS]) + ## Build type - env.Append(LIBPATH=[os.getenv("WindowsSdkDir") + "/Lib"]) + if (env["target"] == "release"): + env.Append(CCFLAGS=['-msse2']) - if (os.getenv("VCINSTALLDIR")): - VC_PATH = os.getenv("VCINSTALLDIR") + if (env["bits"] == "64"): + env.Append(CCFLAGS=['-O3']) else: - VC_PATH = "" + env.Append(CCFLAGS=['-O2']) - if (env["use_lto"]): - env.Append(CCFLAGS=['/GL']) - env.Append(ARFLAGS=['/LTCG']) - if env["progress"]: - env.Append(LINKFLAGS=['/LTCG:STATUS']) - else: - env.Append(LINKFLAGS=['/LTCG']) + env.Append(LINKFLAGS=['-Wl,--subsystem,windows']) - env.Append(CCFLAGS=["/I" + p for p in os.getenv("INCLUDE").split(";")]) - env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")]) + if (env["debug_symbols"] == "yes"): + env.Prepend(CCFLAGS=['-g1']) + if (env["debug_symbols"] == "full"): + env.Prepend(CCFLAGS=['-g2']) - # Incremental linking fix - env['BUILDERS']['ProgramOriginal'] = env['BUILDERS']['Program'] - env['BUILDERS']['Program'] = methods.precious_program + elif (env["target"] == "release_debug"): + env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED']) + if (env["debug_symbols"] == "yes"): + env.Prepend(CCFLAGS=['-g1']) + if (env["debug_symbols"] == "full"): + env.Prepend(CCFLAGS=['-g2']) - else: # MinGW - - # Workaround for MinGW. See: - # http://www.scons.org/wiki/LongCmdLinesOnWin32 - env.use_windows_spawn_fix() - - ## Build type + elif (env["target"] == "debug"): + env.Append(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) - if (env["target"] == "release"): - env.Append(CCFLAGS=['-msse2']) + ## Compiler configuration - if (env["bits"] == "64"): - env.Append(CCFLAGS=['-O3']) - else: - env.Append(CCFLAGS=['-O2']) + if (os.name == "nt"): + env['ENV']['TMP'] = os.environ['TMP'] # way to go scons, you can be so stupid sometimes + else: + env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation - env.Append(LINKFLAGS=['-Wl,--subsystem,windows']) + if (env["bits"] == "default"): + if (os.name == "nt"): + env["bits"] = "64" if "PROGRAMFILES(X86)" in os.environ else "32" + else: # default to 64-bit on Linux + env["bits"] = "64" - if (env["debug_symbols"] == "yes"): - env.Prepend(CCFLAGS=['-g1']) - if (env["debug_symbols"] == "full"): - env.Prepend(CCFLAGS=['-g2']) + mingw_prefix = "" - elif (env["target"] == "release_debug"): - env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED']) - if (env["debug_symbols"] == "yes"): - env.Prepend(CCFLAGS=['-g1']) - if (env["debug_symbols"] == "full"): - env.Prepend(CCFLAGS=['-g2']) + if (env["bits"] == "32"): + env.Append(LINKFLAGS=['-static']) + env.Append(LINKFLAGS=['-static-libgcc']) + env.Append(LINKFLAGS=['-static-libstdc++']) + mingw_prefix = env["mingw_prefix_32"] + else: + env.Append(LINKFLAGS=['-static']) + mingw_prefix = env["mingw_prefix_64"] - elif (env["target"] == "debug"): - env.Append(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) + env["CC"] = mingw_prefix + "gcc" + env['AS'] = mingw_prefix + "as" + env['CXX'] = mingw_prefix + "g++" + env['AR'] = mingw_prefix + "gcc-ar" + env['RANLIB'] = mingw_prefix + "gcc-ranlib" + env['LINK'] = mingw_prefix + "g++" + env["x86_libtheora_opt_gcc"] = True - ## Compiler configuration + if env['use_lto']: + env.Append(CCFLAGS=['-flto']) + env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))]) - if (os.name == "nt"): - env['ENV']['TMP'] = os.environ['TMP'] # way to go scons, you can be so stupid sometimes - else: - env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation - if (env["bits"] == "default"): - if (os.name == "nt"): - env["bits"] = "64" if "PROGRAMFILES(X86)" in os.environ else "32" - else: # default to 64-bit on Linux - env["bits"] = "64" + ## Compile flags - mingw_prefix = "" + env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows']) + env.Append(CCFLAGS=['-DOPENGL_ENABLED']) + env.Append(CCFLAGS=['-DRTAUDIO_ENABLED']) + env.Append(CCFLAGS=['-DWASAPI_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']) - if (env["bits"] == "32"): - env.Append(LINKFLAGS=['-static']) - env.Append(LINKFLAGS=['-static-libgcc']) - env.Append(LINKFLAGS=['-static-libstdc++']) - mingw_prefix = env["mingw_prefix_32"] - else: - env.Append(LINKFLAGS=['-static']) - mingw_prefix = env["mingw_prefix_64"] + env.Append(CPPFLAGS=['-DMINGW_ENABLED']) - env["CC"] = mingw_prefix + "gcc" - env['AS'] = mingw_prefix + "as" - env['CXX'] = mingw_prefix + "g++" - env['AR'] = mingw_prefix + "gcc-ar" - env['RANLIB'] = mingw_prefix + "gcc-ranlib" - env['LINK'] = mingw_prefix + "g++" - env["x86_libtheora_opt_gcc"] = True + # resrc + env.Append(BUILDERS={'RES': env.Builder(action=build_res_file, suffix='.o', src_suffix='.rc')}) - if env['use_lto']: - env.Append(CCFLAGS=['-flto']) - env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))]) +def configure(env): + # At this point the env has been set up with basic tools/compilers. + env.Append(CPPPATH=['#platform/windows']) + print("Configuring for Windows: target=%s, bits=%s" % (env['target'], env['bits'])) - ## Compile flags + if (os.name == "nt"): + env['ENV'] = os.environ # this makes build less repeatable, but simplifies some things + env['ENV']['TMP'] = os.environ['TMP'] - env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows']) - env.Append(CCFLAGS=['-DOPENGL_ENABLED']) - env.Append(CCFLAGS=['-DRTAUDIO_ENABLED']) - env.Append(CCFLAGS=['-DWASAPI_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']) + # First figure out which compiler, version, and target arch we're using + if os.getenv("VCINSTALLDIR"): + # Manual setup of MSVC + setup_msvc_manual(env) + env.msvc = True + manual_msvc_config = True + elif env.get('MSVC_VERSION', ''): + setup_msvc_auto(env) + env.msvc = True + manual_msvc_config = False + else: + setup_mingw(env) + env.msvc = False - env.Append(CPPFLAGS=['-DMINGW_ENABLED']) + # Now set compiler/linker flags + if env.msvc: + configure_msvc(env, manual_msvc_config) - # resrc - env.Append(BUILDERS={'RES': env.Builder(action=build_res_file, suffix='.o', src_suffix='.rc')}) + else: # MinGW + configure_mingw(env) diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc index c535a749c0..f2dca10d55 100644 --- a/platform/windows/godot_res.rc +++ b/platform/windows/godot_res.rc @@ -3,11 +3,9 @@ #define _STR(m_x) #m_x #define _MKSTR(m_x) _STR(m_x) #endif + #ifndef VERSION_PATCH #define VERSION_PATCH 0 -#define PATCH_STRING -#else -#define PATCH_STRING "." _MKSTR(VERSION_PATCH) #endif GODOT_ICON ICON platform/windows/godot.ico @@ -24,12 +22,12 @@ BEGIN BEGIN VALUE "CompanyName", "Godot Engine" VALUE "FileDescription", VERSION_NAME " Editor" - VALUE "FileVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) + VALUE "FileVersion", VERSION_NUMBER VALUE "ProductName", VERSION_NAME VALUE "Licence", "MIT" - VALUE "LegalCopyright", "Copyright (c) 2007-" _MKSTR(VERSION_YEAR) " Juan Linietsky, Ariel Manzur" + VALUE "LegalCopyright", "Copyright (c) 2007-" _MKSTR(VERSION_YEAR) " Juan Linietsky, Ariel Manzur and contributors" VALUE "Info", "https://godotengine.org" - VALUE "ProductVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) PATCH_STRING "." VERSION_BUILD + VALUE "ProductVersion", VERSION_FULL_BUILD END END BLOCK "VarFileInfo" diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 20129299a1..13fe781ff3 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -30,6 +30,7 @@ #include "os_windows.h" +#include "drivers/gles2/rasterizer_gles2.h" #include "drivers/gles3/rasterizer_gles3.h" #include "drivers/windows/dir_access_windows.h" #include "drivers/windows/file_access_windows.h" @@ -151,26 +152,6 @@ void RedirectIOToConsole() { // point to console as well } -int OS_Windows::get_video_driver_count() const { - - return 1; -} -const char *OS_Windows::get_video_driver_name(int p_driver) const { - - return "GLES3"; -} - -int OS_Windows::get_audio_driver_count() const { - - return AudioDriverManager::get_driver_count(); -} -const char *OS_Windows::get_audio_driver_name(int p_driver) const { - - AudioDriver *driver = AudioDriverManager::get_driver(p_driver); - ERR_FAIL_COND_V(!driver, ""); - return AudioDriverManager::get_driver(p_driver)->get_name(); -} - void OS_Windows::initialize_core() { crash_handler.initialize(); @@ -632,7 +613,16 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) video_mode.width = window_w; video_mode.height = window_h; } - //return 0; // Jump Back + if (wParam == SIZE_MAXIMIZED) { + maximized = true; + minimized = false; + } else if (wParam == SIZE_MINIMIZED) { + maximized = false; + minimized = true; + } else if (wParam == SIZE_RESTORED) { + maximized = false; + minimized = false; + } } break; case WM_ENTERSIZEMOVE: { @@ -1080,12 +1070,19 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int } #if defined(OPENGL_ENABLED) - gl_context = memnew(ContextGL_Win(hWnd, true)); - gl_context->initialize(); + if (p_video_driver == VIDEO_DRIVER_GLES2) { + gl_context = memnew(ContextGL_Win(hWnd, false)); + gl_context->initialize(); - RasterizerGLES3::register_config(); + RasterizerGLES2::register_config(); + RasterizerGLES2::make_current(); + } else { + gl_context = memnew(ContextGL_Win(hWnd, true)); + gl_context->initialize(); - RasterizerGLES3::make_current(); + RasterizerGLES3::register_config(); + RasterizerGLES3::make_current(); + } gl_context->set_use_vsync(video_mode.use_vsync); #endif diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 4c4fbcf8f0..3d13627bfa 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -142,12 +142,6 @@ class OS_Windows : public OS { // functions used by main to initialize/deintialize the OS protected: - virtual int get_video_driver_count() const; - virtual const char *get_video_driver_name(int p_driver) const; - - virtual int get_audio_driver_count() const; - virtual const char *get_audio_driver_name(int p_driver) const; - virtual void initialize_core(); virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h index 10ec9110d1..d100385e80 100644 --- a/platform/windows/platform_config.h +++ b/platform/windows/platform_config.h @@ -33,3 +33,4 @@ //#include <alloca.h> //#endif #define GLES3_INCLUDE_H "glad/glad.h" +#define GLES2_INCLUDE_H "glad/glad.h" diff --git a/platform/x11/SCsub b/platform/x11/SCsub index b18757337a..d0f77892ef 100644 --- a/platform/x11/SCsub +++ b/platform/x11/SCsub @@ -4,9 +4,9 @@ import os Import('env') def make_debug(target, source, env): - os.system('objcopy --only-keep-debug %s %s.debugsymbols' % (target[0], target[0])) - os.system('strip --strip-debug --strip-unneeded %s' % (target[0])) - os.system('objcopy --add-gnu-debuglink=%s.debugsymbols %s' % (target[0], target[0])) + os.system('objcopy --only-keep-debug {0} {0}.debugsymbols'.format(target[0])) + os.system('strip --strip-debug --strip-unneeded {0}'.format(target[0])) + os.system('objcopy --add-gnu-debuglink={0}.debugsymbols {0}'.format(target[0])) common_x11 = [ "context_gl_x11.cpp", diff --git a/platform/x11/context_gl_x11.cpp b/platform/x11/context_gl_x11.cpp index 20f2212861..1a7cbc0d6d 100644 --- a/platform/x11/context_gl_x11.cpp +++ b/platform/x11/context_gl_x11.cpp @@ -146,20 +146,39 @@ Error ContextGL_X11::initialize() { int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&ctxErrorHandler); - if (!opengl_3_context) { - //oldstyle context: - p->glx_context = glXCreateContext(x11_display, vi, 0, GL_TRUE); - } else { - static int context_attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 3, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB /*|GLX_CONTEXT_DEBUG_BIT_ARB*/, - None - }; - - p->glx_context = glXCreateContextAttribsARB(x11_display, fbc[0], NULL, true, context_attribs); - ERR_EXPLAIN("Could not obtain an OpenGL 3.3 context!"); - ERR_FAIL_COND_V(ctxErrorOccurred || !p->glx_context, ERR_UNCONFIGURED); + switch (context_type) { + case GLES_2_0_COMPATIBLE: + case OLDSTYLE: { + p->glx_context = glXCreateContext(x11_display, vi, 0, GL_TRUE); + } break; + /* + case ContextType::GLES_2_0_COMPATIBLE: { + + static int context_attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + None + }; + + p->glx_context = glXCreateContextAttribsARB(x11_display, fbc[0], NULL, true, context_attribs); + ERR_EXPLAIN("Could not obtain an OpenGL 3.0 context!"); + ERR_FAIL_COND_V(!p->glx_context, ERR_UNCONFIGURED); + } break; + */ + case GLES_3_0_COMPATIBLE: { + + static int context_attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB /*|GLX_CONTEXT_DEBUG_BIT_ARB*/, + None + }; + + p->glx_context = glXCreateContextAttribsARB(x11_display, fbc[0], NULL, true, context_attribs); + ERR_EXPLAIN("Could not obtain an OpenGL 3.3 context!"); + ERR_FAIL_COND_V(ctxErrorOccurred || !p->glx_context, ERR_UNCONFIGURED); + } break; } XSync(x11_display, False); @@ -229,13 +248,13 @@ bool ContextGL_X11::is_using_vsync() const { return use_vsync; } -ContextGL_X11::ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, bool p_opengl_3_context) : +ContextGL_X11::ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, ContextType p_context_type) : x11_window(p_x11_window) { default_video_mode = p_default_video_mode; x11_display = p_x11_display; - opengl_3_context = p_opengl_3_context; + context_type = p_context_type; double_buffer = false; direct_render = false; diff --git a/platform/x11/context_gl_x11.h b/platform/x11/context_gl_x11.h index c969f0044d..b54cc84fac 100644 --- a/platform/x11/context_gl_x11.h +++ b/platform/x11/context_gl_x11.h @@ -46,6 +46,14 @@ struct ContextGL_X11_Private; class ContextGL_X11 : public ContextGL { +public: + enum ContextType { + OLDSTYLE, + GLES_2_0_COMPATIBLE, + GLES_3_0_COMPATIBLE + }; + +private: ContextGL_X11_Private *p; OS::VideoMode default_video_mode; //::Colormap x11_colormap; @@ -54,8 +62,8 @@ class ContextGL_X11 : public ContextGL { bool double_buffer; bool direct_render; int glx_minor, glx_major; - bool opengl_3_context; bool use_vsync; + ContextType context_type; public: virtual void release_current(); @@ -69,7 +77,7 @@ public: virtual void set_use_vsync(bool p_use); virtual bool is_using_vsync() const; - ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, bool p_opengl_3_context); + ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, ContextType p_context_type); ~ContextGL_X11(); }; diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp index 43b9051ea7..d39fc33f81 100644 --- a/platform/x11/crash_handler_x11.cpp +++ b/platform/x11/crash_handler_x11.cpp @@ -32,8 +32,9 @@ #define CRASH_HANDLER_ENABLED 1 #endif +#include "crash_handler_x11.h" #include "main/main.h" -#include "os_x11.h" +#include "os/os.h" #include "project_settings.h" #ifdef CRASH_HANDLER_ENABLED diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 2d8e32137f..c06c7516d0 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -29,9 +29,11 @@ /*************************************************************************/ #include "os_x11.h" +#include "drivers/gles2/rasterizer_gles2.h" #include "drivers/gles3/rasterizer_gles3.h" #include "errno.h" #include "key_mapping_x11.h" +#include "os/dir_access.h" #include "print_string.h" #include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_wrap_mt.h" @@ -75,25 +77,6 @@ #include <X11/XKBlib.h> -int OS_X11::get_video_driver_count() const { - return 1; -} - -const char *OS_X11::get_video_driver_name(int p_driver) const { - return "GLES3"; -} - -int OS_X11::get_audio_driver_count() const { - return AudioDriverManager::get_driver_count(); -} - -const char *OS_X11::get_audio_driver_name(int p_driver) const { - - AudioDriver *driver = AudioDriverManager::get_driver(p_driver); - ERR_FAIL_COND_V(!driver, ""); - return AudioDriverManager::get_driver(p_driver)->get_name(); -} - void OS_X11::initialize_core() { crash_handler.initialize(); @@ -282,12 +265,25 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a //print_line("def videomode "+itos(current_videomode.width)+","+itos(current_videomode.height)); #if defined(OPENGL_ENABLED) - context_gl = memnew(ContextGL_X11(x11_display, x11_window, current_videomode, true)); - context_gl->initialize(); + ContextGL_X11::ContextType opengl_api_type = ContextGL_X11::GLES_3_0_COMPATIBLE; - RasterizerGLES3::register_config(); + if (p_video_driver == VIDEO_DRIVER_GLES2) { + opengl_api_type = ContextGL_X11::GLES_2_0_COMPATIBLE; + } - RasterizerGLES3::make_current(); + context_gl = memnew(ContextGL_X11(x11_display, x11_window, current_videomode, opengl_api_type)); + context_gl->initialize(); + + switch (opengl_api_type) { + case ContextGL_X11::GLES_2_0_COMPATIBLE: { + RasterizerGLES2::register_config(); + RasterizerGLES2::make_current(); + } break; + case ContextGL_X11::GLES_3_0_COMPATIBLE: { + RasterizerGLES3::register_config(); + RasterizerGLES3::make_current(); + } break; + } context_gl->set_use_vsync(current_videomode.use_vsync); @@ -730,6 +726,16 @@ void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) con } void OS_X11::set_wm_fullscreen(bool p_enabled) { + if (p_enabled && !get_borderless_window()) { + // remove decorations if the window is not already borderless + Hints hints; + Atom property; + hints.flags = 2; + hints.decorations = 0; + property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + } + if (p_enabled && !is_window_resizable()) { // Set the window as resizable to prevent window managers to ignore the fullscreen state flag. XSizeHints *xsh; @@ -740,7 +746,7 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) { XFree(xsh); } - // Using EWMH -- Extened Window Manager Hints + // Using EWMH -- Extended Window Manager Hints XEvent xev; Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False); @@ -1182,6 +1188,7 @@ bool OS_X11::is_window_maximized() const { unsigned long len; unsigned long remaining; unsigned char *data = NULL; + bool retval = false; int result = XGetWindowProperty( x11_display, @@ -1210,13 +1217,15 @@ bool OS_X11::is_window_maximized() const { if (atoms[i] == wm_max_vert) found_wm_max_vert = true; - if (found_wm_max_horz && found_wm_max_vert) - return true; + if (found_wm_max_horz && found_wm_max_vert) { + retval = true; + break; + } } - XFree(atoms); } - return false; + XFree(data); + return retval; } void OS_X11::set_window_always_on_top(bool p_enabled) { @@ -2585,48 +2594,66 @@ static String get_mountpoint(const String &p_path) { } Error OS_X11::move_to_trash(const String &p_path) { - String trashcan = ""; + String trash_can = ""; String mnt = get_mountpoint(p_path); + // If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can. if (mnt != "") { String path(mnt + "/.Trash-" + itos(getuid()) + "/files"); struct stat s; if (!stat(path.utf8().get_data(), &s)) { - trashcan = path; + trash_can = path; } } - if (trashcan == "") { + // Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can. + if (trash_can == "") { char *dhome = getenv("XDG_DATA_HOME"); if (dhome) { - trashcan = String(dhome) + "/Trash/files"; + trash_can = String(dhome) + "/Trash/files"; } } - if (trashcan == "") { + // Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can. + if (trash_can == "") { char *home = getenv("HOME"); if (home) { - trashcan = String(home) + "/.local/share/Trash/files"; + trash_can = String(home) + "/.local/share/Trash/files"; } } - if (trashcan == "") { - ERR_PRINTS("move_to_trash: Could not determine trashcan location"); + // Issue an error if none of the previous locations is appropriate for the trash can. + if (trash_can == "") { + ERR_PRINTS("move_to_trash: Could not determine the trash can location"); return FAILED; } - List<String> args; - args.push_back("-p"); - args.push_back(trashcan); - Error err = execute("mkdir", args, true); - if (err == OK) { - List<String> args2; - args2.push_back(p_path); - args2.push_back(trashcan); - err = execute("mv", args2, true); + // Create needed directories for decided trash can location. + DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + Error err = dir_access->make_dir_recursive(trash_can); + memdelete(dir_access); + + // Issue an error if trash can is not created proprely. + if (err != OK) { + ERR_PRINTS("move_to_trash: Could not create the trash can \"" + trash_can + "\""); + return err; } - return err; + // The trash can is successfully created, now move the given resource to it. + // Do not use DirAccess:rename() because it can't move files across multiple mountpoints. + List<String> mv_args; + mv_args.push_back(p_path); + mv_args.push_back(trash_can); + int retval; + err = execute("mv", mv_args, true, NULL, NULL, &retval); + + // Issue an error if "mv" failed to move the given resource to the trash can. + if (err != OK || retval != 0) { + ERR_PRINTS("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\""); + return FAILED; + } + + return OK; } OS::LatinKeyboardVariant OS_X11::get_latin_keyboard_variant() const { diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 494845bc56..610dba0716 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -188,12 +188,6 @@ class OS_X11 : public OS_Unix { Bool xrandr_ext_ok; protected: - virtual int get_video_driver_count() const; - virtual const char *get_video_driver_name(int p_driver) const; - - virtual int get_audio_driver_count() const; - virtual const char *get_audio_driver_name(int p_driver) const; - virtual void initialize_core(); virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void finalize(); diff --git a/platform/x11/platform_config.h b/platform/x11/platform_config.h index 58d6b210ee..b757be49c3 100644 --- a/platform/x11/platform_config.h +++ b/platform/x11/platform_config.h @@ -37,3 +37,4 @@ #endif #define GLES3_INCLUDE_H "glad/glad.h" +#define GLES2_INCLUDE_H "glad/glad.h" diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index f290a181ec..824f50495b 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -34,7 +34,51 @@ #define NORMAL_SUFFIX "_normal" -//////////////////////////// +Dictionary AnimatedSprite::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = offset; + return state; +} + +void AnimatedSprite::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_offset(p_state["offset"]); +} + +void AnimatedSprite::_edit_set_pivot(const Point2 &p_pivot) { + set_offset(get_offset() - p_pivot); + set_position(get_transform().xform(p_pivot)); +} + +Point2 AnimatedSprite::_edit_get_pivot() const { + return Vector2(); +} + +bool AnimatedSprite::_edit_use_pivot() const { + return true; +} + +Rect2 AnimatedSprite::_edit_get_rect() const { + if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + return Node2D::_edit_get_rect(); + } + + Ref<Texture> t; + if (animation) + t = frames->get_frame(animation, frame); + if (t.is_null()) + return Node2D::_edit_get_rect(); + Size2 s = t->get_size(); + + Point2 ofs = offset; + if (centered) + ofs -= s / 2; + + if (s == Size2(0, 0)) + s = Size2(1, 1); + + return Rect2(ofs, s); +} void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture> &p_frame, int p_at_pos) { @@ -248,20 +292,6 @@ SpriteFrames::SpriteFrames() { add_animation(SceneStringNames::get_singleton()->_default); } -void AnimatedSprite::_edit_set_pivot(const Point2 &p_pivot) { - - set_offset(p_pivot); -} - -Point2 AnimatedSprite::_edit_get_pivot() const { - - return get_offset(); -} -bool AnimatedSprite::_edit_use_pivot() const { - - return true; -} - void AnimatedSprite::_validate_property(PropertyInfo &property) const { if (!frames.is_valid()) @@ -491,29 +521,6 @@ bool AnimatedSprite::is_flipped_v() const { return vflip; } -Rect2 AnimatedSprite::_edit_get_rect() const { - - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { - return Node2D::_edit_get_rect(); - } - - Ref<Texture> t; - if (animation) - t = frames->get_frame(animation, frame); - if (t.is_null()) - return Node2D::_edit_get_rect(); - Size2i s = t->get_size(); - - Point2 ofs = offset; - if (centered) - ofs -= s / 2; - - if (s == Size2(0, 0)) - s = Size2(1, 1); - - return Rect2(ofs, s); -} - void AnimatedSprite::_res_changed() { set_frame(frame); diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index 2c356d619f..a38adf792c 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -150,9 +150,13 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + virtual void _edit_set_pivot(const Point2 &p_pivot); virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; + virtual Rect2 _edit_get_rect() const; void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; @@ -182,8 +186,6 @@ public: void set_modulate(const Color &p_color); Color get_modulate() const; - virtual Rect2 _edit_get_rect() const; - virtual String get_configuration_warning() const; AnimatedSprite(); }; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index fc67d28a29..f998f23d3b 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -226,14 +226,14 @@ void AudioStreamPlayer2D::_notification(int p_what) { setseek = setplay; active = true; setplay = -1; - //do not update, this makes it easier to animate (will shut off otherise) + //do not update, this makes it easier to animate (will shut off otherwise) //_change_notify("playing"); //update property in editor } //stop playing if no longer active if (!active) { set_physics_process_internal(false); - //do not update, this makes it easier to animate (will shut off otherise) + //do not update, this makes it easier to animate (will shut off otherwise) //_change_notify("playing"); //update property in editor emit_signal("finished"); } diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 87bcdae527..5cca5705a0 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -684,7 +684,7 @@ void CanvasItem::draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw(canvas_item, p_pos, p_modulate); + p_texture->draw(canvas_item, p_pos, p_modulate, false, p_normal_map); } void CanvasItem::draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) { @@ -779,6 +779,22 @@ void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Colo VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, colors, p_uvs, rid, rid_normal, p_antialiased); } +void CanvasItem::draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map) { + + ERR_FAIL_COND(p_mesh.is_null()); + RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); + RID normal_map_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + + VisualServer::get_singleton()->canvas_item_add_mesh(canvas_item, p_mesh->get_rid(), texture_rid, normal_map_rid); +} +void CanvasItem::draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map) { + + ERR_FAIL_COND(p_multimesh.is_null()); + RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); + RID normal_map_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); + VisualServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid, normal_map_rid); +} + void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate, int p_clip_w) { if (!drawing) { @@ -1016,6 +1032,8 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture", "normal_map", "antialiased"), &CanvasItem::draw_colored_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_string", "font", "position", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("draw_char", "font", "position", "char", "next", "modulate"), &CanvasItem::draw_char, DEFVAL(Color(1, 1, 1))); + ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture>())); + ClassDB::bind_method(D_METHOD("draw_multimesh", "mesh", "texture", "normal_map"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture>())); ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform); ClassDB::bind_method(D_METHOD("draw_set_transform_matrix", "xform"), &CanvasItem::draw_set_transform_matrix); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 7e5bea0511..980fcb4109 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -34,6 +34,7 @@ #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "scene/resources/material.h" +#include "scene/resources/multimesh.h" #include "scene/resources/shader.h" #include "scene/resources/texture.h" @@ -230,7 +231,7 @@ public: // Used to resize/move/select the node virtual void _edit_set_rect(const Rect2 &p_rect){}; virtual Rect2 _edit_get_rect() const { return Rect2(-32, -32, 64, 64); }; - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return true; } + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return _edit_get_rect().has_point(p_point); } Rect2 _edit_get_item_and_children_rect() const; virtual bool _edit_use_rect() const { return false; }; @@ -282,6 +283,9 @@ public: void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_antialiased = false); void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_antialiased = false); + void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map); + void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map); + void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate = Color(1, 1, 1), int p_clip_w = -1); float draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", const Color &p_modulate = Color(1, 1, 1)); diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 8350e7c48a..d05c818ae1 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -336,7 +336,7 @@ String CollisionObject2D::get_configuration_warning() const { if (warning == String()) { warning += "\n"; } - warning += TTR("This node has no children shapes, so it can't interact with the space.\nConsider adding CollisionShape2D or CollisionPolygon2D children nodes to define its shape."); + warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape2D or CollisionPolygon2D as a child to define its shape."); } return warning; diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 978fb379ac..7e2026d225 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -175,7 +175,8 @@ void CollisionPolygon2D::_notification(int p_what) { Vector2 p = polygon[i]; Vector2 n = polygon[(i + 1) % polygon.size()]; - draw_line(p, n, Color(0.9, 0.2, 0.0, 0.8), 3); + // draw line with width <= 1, so it does not scale with zoom and break pixel exact editing + draw_line(p, n, Color(0.9, 0.2, 0.0, 0.8), 1); } #define DEBUG_DECOMPOSE #if defined(TOOLS_ENABLED) && defined(DEBUG_DECOMPOSE) diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 999d8a2630..1220ff299c 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -33,35 +33,36 @@ #include "engine.h" #include "servers/visual_server.h" -void Light2D::_edit_set_pivot(const Point2 &p_pivot) { +Dictionary Light2D::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = get_texture_offset(); + return state; +} - set_texture_offset(p_pivot); +void Light2D::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_texture_offset(p_state["offset"]); } -Point2 Light2D::_edit_get_pivot() const { +void Light2D::_edit_set_pivot(const Point2 &p_pivot) { + set_position(get_transform().xform(p_pivot)); + set_texture_offset(get_texture_offset() - p_pivot); +} - return get_texture_offset(); +Point2 Light2D::_edit_get_pivot() const { + return Vector2(); } -bool Light2D::_edit_use_pivot() const { +bool Light2D::_edit_use_pivot() const { return true; } Rect2 Light2D::_edit_get_rect() const { - if (texture.is_null()) - return Rect2(0, 0, 1, 1); - - Size2i s; - - s = texture->get_size() * _scale; - Point2i ofs = texture_offset; - ofs -= s / 2; - - if (s == Size2(0, 0)) - s = Size2(1, 1); + return Node2D::_edit_get_rect(); - return Rect2(ofs, s); + Size2 s = texture->get_size() * _scale; + return Rect2(texture_offset - s / 2.0, s); } void Light2D::_update_light_visibility() { @@ -131,6 +132,7 @@ void Light2D::set_texture_offset(const Vector2 &p_offset) { texture_offset = p_offset; VS::get_singleton()->canvas_light_set_texture_offset(canvas_light, texture_offset); item_rect_changed(); + _change_notify("offset"); } Vector2 Light2D::get_texture_offset() const { diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index b216ad5e95..16d8c485d4 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -85,6 +85,9 @@ protected: static void _bind_methods(); public: + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + virtual void _edit_set_pivot(const Point2 &p_pivot); virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index f0ab9652b4..ba4a5c5571 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -252,12 +252,15 @@ void Line2D::_draw() { lb.sharp_limit = _sharp_limit; lb.width = _width; - lb.build(); - RID texture_rid; - if (_texture.is_valid()) + if (_texture.is_valid()) { texture_rid = (**_texture).get_rid(); + lb.tile_aspect = _texture->get_size().aspect(); + } + + lb.build(); + VS::get_singleton()->canvas_item_add_triangle_array( get_canvas_item(), lb.indices, diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp index b1a072729f..845788bada 100644 --- a/scene/2d/line_builder.cpp +++ b/scene/2d/line_builder.cpp @@ -101,6 +101,7 @@ LineBuilder::LineBuilder() { round_precision = 8; begin_cap_mode = Line2D::LINE_CAP_NONE; end_cap_mode = Line2D::LINE_CAP_NONE; + tile_aspect = 1.f; _interpolate_color = false; _last_index[0] = 0; @@ -111,6 +112,7 @@ void LineBuilder::clear_output() { vertices.clear(); colors.clear(); indices.clear(); + uvs.clear(); } void LineBuilder::build() { @@ -121,6 +123,8 @@ void LineBuilder::build() { return; } + ERR_FAIL_COND(tile_aspect <= 0.f); + const float hw = width / 2.f; const float hw_sq = hw * hw; const float sharp_limit_sq = sharp_limit * sharp_limit; @@ -164,7 +168,7 @@ void LineBuilder::build() { current_distance1 = current_distance0; } else if (begin_cap_mode == Line2D::LINE_CAP_ROUND) { if (texture_mode == Line2D::LINE_TEXTURE_TILE) { - uvx0 = 0.5f; + uvx0 = 0.5f / tile_aspect; } new_arc(pos0, pos_up0 - pos0, -Math_PI, color0, Rect2(0.f, 0.f, 1.f, 1.f)); total_distance += width; @@ -286,8 +290,8 @@ void LineBuilder::build() { color1 = gradient->get_color_at_offset(current_distance1 / total_distance); } if (texture_mode == Line2D::LINE_TEXTURE_TILE) { - uvx0 = current_distance0 / width; - uvx1 = current_distance1 / width; + uvx0 = current_distance0 / (width * tile_aspect); + uvx1 = current_distance1 / (width * tile_aspect); } strip_add_quad(pos_up1, pos_down1, color1, uvx1); @@ -373,7 +377,7 @@ void LineBuilder::build() { color1 = gradient->get_color(gradient->get_points_count() - 1); } if (texture_mode == Line2D::LINE_TEXTURE_TILE) { - uvx1 = current_distance1 / width; + uvx1 = current_distance1 / (width * tile_aspect); } strip_add_quad(pos_up1, pos_down1, color1, uvx1); diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h index daa2ed7c24..b1c62f84e2 100644 --- a/scene/2d/line_builder.h +++ b/scene/2d/line_builder.h @@ -50,6 +50,7 @@ public: Line2D::LineTextureMode texture_mode; float sharp_limit; int round_precision; + float tile_aspect; // w/h // TODO offset_joints option (offers alternative implementation of round joints) // TODO Move in a struct and reference it diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp new file mode 100644 index 0000000000..adbb227d0c --- /dev/null +++ b/scene/2d/mesh_instance_2d.cpp @@ -0,0 +1,76 @@ +#include "mesh_instance_2d.h" + +void MeshInstance2D::_notification(int p_what) { + + if (p_what == NOTIFICATION_DRAW) { + if (mesh.is_valid()) { + draw_mesh(mesh, texture, normal_map); + } + } +} + +void MeshInstance2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MeshInstance2D::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &MeshInstance2D::get_mesh); + + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &MeshInstance2D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &MeshInstance2D::get_texture); + + ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &MeshInstance2D::set_normal_map); + ClassDB::bind_method(D_METHOD("get_normal_map"), &MeshInstance2D::get_normal_map); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map"); +} + +void MeshInstance2D::set_mesh(const Ref<Mesh> &p_mesh) { + + mesh = p_mesh; + update(); +} + +Ref<Mesh> MeshInstance2D::get_mesh() const { + + return mesh; +} + +void MeshInstance2D::set_texture(const Ref<Texture> &p_texture) { + + if (p_texture == texture) + return; + texture = p_texture; + update(); + emit_signal("texture_changed"); + _change_notify("texture"); +} + +void MeshInstance2D::set_normal_map(const Ref<Texture> &p_texture) { + + normal_map = p_texture; + update(); +} + +Ref<Texture> MeshInstance2D::get_normal_map() const { + + return normal_map; +} + +Ref<Texture> MeshInstance2D::get_texture() const { + + return texture; +} + +Rect2 MeshInstance2D::_edit_get_rect() const { + + if (mesh.is_valid()) { + AABB aabb = mesh->get_aabb(); + return Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + } + + return Node2D::_edit_get_rect(); +} + +MeshInstance2D::MeshInstance2D() { +} diff --git a/scene/2d/mesh_instance_2d.h b/scene/2d/mesh_instance_2d.h new file mode 100644 index 0000000000..d1d1ade0ae --- /dev/null +++ b/scene/2d/mesh_instance_2d.h @@ -0,0 +1,33 @@ +#ifndef MESH_INSTANCE_2D_H +#define MESH_INSTANCE_2D_H + +#include "scene/2d/node_2d.h" + +class MeshInstance2D : public Node2D { + GDCLASS(MeshInstance2D, Node2D) + + Ref<Mesh> mesh; + + Ref<Texture> texture; + Ref<Texture> normal_map; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_mesh(const Ref<Mesh> &p_mesh); + Ref<Mesh> get_mesh() const; + + void set_texture(const Ref<Texture> &p_texture); + Ref<Texture> get_texture() const; + + void set_normal_map(const Ref<Texture> &p_texture); + Ref<Texture> get_normal_map() const; + + virtual Rect2 _edit_get_rect() const; + + MeshInstance2D(); +}; + +#endif // MESH_INSTANCE_2D_H diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 95a1cbfce3..95e24505be 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -46,10 +46,9 @@ Dictionary Node2D::_edit_get_state() const { } void Node2D::_edit_set_state(const Dictionary &p_state) { - Dictionary state = p_state; - pos = state["position"]; - angle = state["rotation"]; - _scale = state["scale"]; + pos = p_state["position"]; + angle = p_state["rotation"]; + _scale = p_state["scale"]; _update_transform(); _change_notify("rotation"); @@ -60,6 +59,8 @@ void Node2D::_edit_set_state(const Dictionary &p_state) { void Node2D::_edit_set_position(const Point2 &p_position) { pos = p_position; + _update_transform(); + _change_notify("position"); } Point2 Node2D::_edit_get_position() const { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 9908907ee9..feb11089d0 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -30,6 +30,7 @@ #include "physics_body_2d.h" +#include "core/method_bind_ext.gen.inc" #include "engine.h" #include "scene/scene_string_names.h" @@ -362,12 +363,12 @@ struct _RigidBody2DInOut { int local_shape; }; -bool RigidBody2D::_test_motion(const Vector2 &p_motion, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) { +bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) { Physics2DServer::MotionResult *r = NULL; if (p_result.is_valid()) r = p_result->get_result_ptr(); - return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_margin, r); + return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r); } void RigidBody2D::_direct_state_changed(Object *p_state) { @@ -886,7 +887,7 @@ void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep); ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep); - ClassDB::bind_method(D_METHOD("test_motion", "motion", "margin", "result"), &RigidBody2D::_test_motion, DEFVAL(0.08), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("test_motion", "motion", "infinite_inertia", "margin", "result"), &RigidBody2D::_test_motion, DEFVAL(true), DEFVAL(0.08), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("_direct_state_changed"), &RigidBody2D::_direct_state_changed); ClassDB::bind_method(D_METHOD("_body_enter_tree"), &RigidBody2D::_body_enter_tree); @@ -970,11 +971,11 @@ RigidBody2D::~RigidBody2D() { ////////////////////////// -Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion) { +Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia) { Collision col; - if (move_and_collide(p_motion, col)) { + if (move_and_collide(p_motion, p_infinite_inertia, col)) { if (motion_cache.is_null()) { motion_cache.instance(); motion_cache->owner = this; @@ -988,11 +989,11 @@ Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion) { return Ref<KinematicCollision2D>(); } -bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, Collision &r_collision) { +bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision) { Transform2D gt = get_global_transform(); Physics2DServer::MotionResult result; - bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result); + bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result); if (colliding) { r_collision.collider_metadata = result.collider_metadata; @@ -1012,7 +1013,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, Collision &r_col return colliding; } -Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) { +Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) { Vector2 motion = (floor_velocity + p_linear_velocity) * get_physics_process_delta_time(); Vector2 lv = p_linear_velocity; @@ -1027,7 +1028,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Collision collision; - bool collided = move_and_collide(motion, collision); + bool collided = move_and_collide(motion, p_infinite_inertia, collision); if (collided) { @@ -1094,11 +1095,11 @@ Vector2 KinematicBody2D::get_floor_velocity() const { return floor_velocity; } -bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion) { +bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia) { ERR_FAIL_COND_V(!is_inside_tree(), false); - return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, margin); + return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin); } void KinematicBody2D::set_safe_margin(float p_margin) { @@ -1139,10 +1140,10 @@ Ref<KinematicCollision2D> KinematicBody2D::_get_slide_collision(int p_bounce) { void KinematicBody2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec"), &KinematicBody2D::_move); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); + ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia"), &KinematicBody2D::_move, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); - ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody2D::test_move); + ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move); ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index c755f30f2b..0fda3c5c05 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -185,7 +185,7 @@ private: void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape); void _direct_state_changed(Object *p_state); - bool _test_motion(const Vector2 &p_motion, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>()); + bool _test_motion(const Vector2 &p_motion, bool p_infinite_inertia = true, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>()); protected: void _notification(int p_what); @@ -296,20 +296,20 @@ private: _FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const; - Ref<KinematicCollision2D> _move(const Vector2 &p_motion); + Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_infinite_inertia = true); Ref<KinematicCollision2D> _get_slide_collision(int p_bounce); protected: static void _bind_methods(); public: - bool move_and_collide(const Vector2 &p_motion, Collision &r_collision); - bool test_move(const Transform2D &p_from, const Vector2 &p_motion); + bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision); + bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia); void set_safe_margin(float p_margin); float get_safe_margin() const; - Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), float p_slope_stop_min_velocity = 5, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45)); + Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_infinite_inertia = true, float p_slope_stop_min_velocity = 5, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45)); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index f6cb796b10..2cb1e86f51 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -31,8 +31,31 @@ #include "polygon_2d.h" #include "core/math/geometry.h" -Rect2 Polygon2D::_edit_get_rect() const { +Dictionary Polygon2D::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = offset; + return state; +} + +void Polygon2D::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_offset(p_state["offset"]); +} + +void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) { + set_position(get_transform().xform(p_pivot)); + set_offset(get_offset() - p_pivot); +} + +Point2 Polygon2D::_edit_get_pivot() const { + return Vector2(); +} +bool Polygon2D::_edit_use_pivot() const { + return true; +} + +Rect2 Polygon2D::_edit_get_rect() const { if (rect_cache_dirty) { int l = polygon.size(); PoolVector<Vector2>::Read r = polygon.read(); @@ -52,21 +75,7 @@ Rect2 Polygon2D::_edit_get_rect() const { bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - return Geometry::is_point_in_polygon(p_point, Variant(polygon)); -} - -void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) { - - set_offset(p_pivot); -} - -Point2 Polygon2D::_edit_get_pivot() const { - - return get_offset(); -} -bool Polygon2D::_edit_use_pivot() const { - - return true; + return Geometry::is_point_in_polygon(p_point - get_offset(), Variant(polygon)); } void Polygon2D::_notification(int p_what) { @@ -183,7 +192,80 @@ void Polygon2D::_notification(int p_what) { // Vector<int> indices = Geometry::triangulate_polygon(points); // VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID()); - VS::get_singleton()->canvas_item_add_polygon(get_canvas_item(), points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID(), RID(), antialiased); + if (invert || splits.size() == 0) { + VS::get_singleton()->canvas_item_add_polygon(get_canvas_item(), points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID(), RID(), antialiased); + } else { + //use splits + Vector<int> loop; + int sc = splits.size(); + PoolVector<int>::Read r = splits.read(); + int last = points.size(); + + Vector<Vector<int> > loops; + + for (int i = 0; i < last; i++) { + + int split; + int min_end = -1; + + do { + + loop.push_back(i); + + split = -1; + int end = -1; + + for (int j = 0; j < sc; j += 2) { + if (r[j + 1] >= last) + continue; //no longer valid + if (min_end != -1 && r[j + 1] >= min_end) + continue; + if (r[j] == i) { + if (split == -1 || r[j + 1] > end) { + split = r[j]; + end = r[j + 1]; + } + } + } + + if (split != -1) { + for (int j = end; j < last; j++) { + loop.push_back(j); + } + loops.push_back(loop); + last = end + 1; + loop.clear(); + min_end = end; //avoid this split from repeating + } + + } while (split != -1); + } + + if (loop.size()) { + loops.push_back(loop); + } + + Vector<int> indices; + + for (int i = 0; i < loops.size(); i++) { + Vector<int> loop = loops[i]; + Vector<Vector2> vertices; + vertices.resize(loop.size()); + for (int j = 0; j < vertices.size(); j++) { + vertices[j] = points[loop[j]]; + } + Vector<int> sub_indices = Geometry::triangulate_polygon(vertices); + int from = indices.size(); + indices.resize(from + sub_indices.size()); + for (int j = 0; j < sub_indices.size(); j++) { + indices[from + j] = loop[sub_indices[j]]; + } + } + + //print_line("loops: " + itos(loops.size()) + " indices: " + itos(indices.size())); + + VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID()); + } } break; } @@ -211,6 +293,18 @@ PoolVector<Vector2> Polygon2D::get_uv() const { return uv; } +void Polygon2D::set_splits(const PoolVector<int> &p_splits) { + + ERR_FAIL_COND(p_splits.size() & 1); //splits should be multiple of 2 + splits = p_splits; + update(); +} + +PoolVector<int> Polygon2D::get_splits() const { + + return splits; +} + void Polygon2D::set_color(const Color &p_color) { color = p_color; @@ -324,6 +418,7 @@ void Polygon2D::set_offset(const Vector2 &p_offset) { offset = p_offset; rect_cache_dirty = true; update(); + _change_notify("offset"); } Vector2 Polygon2D::get_offset() const { @@ -342,6 +437,9 @@ void Polygon2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_color", "color"), &Polygon2D::set_color); ClassDB::bind_method(D_METHOD("get_color"), &Polygon2D::get_color); + ClassDB::bind_method(D_METHOD("set_splits", "splits"), &Polygon2D::set_splits); + ClassDB::bind_method(D_METHOD("get_splits"), &Polygon2D::get_splits); + ClassDB::bind_method(D_METHOD("set_vertex_colors", "vertex_colors"), &Polygon2D::set_vertex_colors); ClassDB::bind_method(D_METHOD("get_vertex_colors"), &Polygon2D::get_vertex_colors); @@ -374,6 +472,7 @@ void Polygon2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "splits"), "set_splits", "get_splits"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "vertex_colors"), "set_vertex_colors", "get_vertex_colors"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index f62c78c55b..3a24177548 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -40,6 +40,8 @@ class Polygon2D : public Node2D { PoolVector<Vector2> polygon; PoolVector<Vector2> uv; PoolVector<Color> vertex_colors; + PoolVector<int> splits; + Color color; Ref<Texture> texture; Size2 tex_scale; @@ -59,12 +61,25 @@ protected: static void _bind_methods(); public: + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; + virtual Rect2 _edit_get_rect() const; + + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_polygon(const PoolVector<Vector2> &p_polygon); PoolVector<Vector2> get_polygon() const; void set_uv(const PoolVector<Vector2> &p_uv); PoolVector<Vector2> get_uv() const; + void set_splits(const PoolVector<int> &p_uv); + PoolVector<int> get_splits() const; + void set_color(const Color &p_color); Color get_color() const; @@ -98,15 +113,6 @@ public: void set_offset(const Vector2 &p_offset); Vector2 get_offset() const; - //editor stuff - - virtual void _edit_set_pivot(const Point2 &p_pivot); - virtual Point2 _edit_get_pivot() const; - virtual bool _edit_use_pivot() const; - - virtual Rect2 _edit_get_rect() const; - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; - Polygon2D(); }; diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp new file mode 100644 index 0000000000..705e82bcbb --- /dev/null +++ b/scene/2d/skeleton_2d.cpp @@ -0,0 +1,210 @@ +#include "skeleton_2d.h" + +void Bone2D::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + Node *parent = get_parent(); + parent_bone = Object::cast_to<Bone2D>(parent); + skeleton = NULL; + while (parent) { + skeleton = Object::cast_to<Skeleton2D>(parent); + if (skeleton) + break; + if (!Object::cast_to<Bone2D>(parent)) + break; //skeletons must be chained to Bone2Ds. + } + + if (skeleton) { + Skeleton2D::Bone bone; + bone.bone = this; + skeleton->bones.push_back(bone); + skeleton->_make_bone_setup_dirty(); + } + } + if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { + if (skeleton) { + skeleton->_make_transform_dirty(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + if (skeleton) { + for (int i = 0; i < skeleton->bones.size(); i++) { + if (skeleton->bones[i].bone == this) { + skeleton->bones.remove(i); + break; + } + } + skeleton->_make_bone_setup_dirty(); + skeleton = NULL; + } + parent_bone = NULL; + } +} +void Bone2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_rest", "rest"), &Bone2D::set_rest); + ClassDB::bind_method(D_METHOD("get_rest"), &Bone2D::get_rest); + ClassDB::bind_method(D_METHOD("apply_rest"), &Bone2D::apply_rest); +} + +void Bone2D::set_rest(const Transform2D &p_rest) { + rest = p_rest; + if (skeleton) + skeleton->_make_bone_setup_dirty(); +} + +Transform2D Bone2D::get_rest() const { + return rest; +} + +Transform2D Bone2D::get_skeleton_rest() const { + + if (parent_bone) { + return parent_bone->get_skeleton_rest() * rest; + } else { + return rest; + } +} + +void Bone2D::apply_rest() { + set_transform(rest); +} + +String Bone2D::get_configuration_warning() const { + if (!skeleton) { + if (parent_bone) { + return TTR("This Bone2D chain should end at a Skeleton2D node."); + } else { + return TTR("A Bone2D only works with a Skeleton2D or another Bone2D as parent node."); + } + } + + return Node2D::get_configuration_warning(); +} + +Bone2D::Bone2D() { + skeleton = NULL; + parent_bone = NULL; + set_notify_local_transform(true); +} + +////////////////////////////////////// + +void Skeleton2D::_make_bone_setup_dirty() { + + if (bone_setup_dirty) + return; + bone_setup_dirty = true; + if (is_inside_tree()) { + call_deferred("_update_bone_setup"); + } +} + +void Skeleton2D::_update_bone_setup() { + + if (!bone_setup_dirty) + return; + + bone_setup_dirty = false; + VS::get_singleton()->skeleton_allocate(skeleton, bones.size(), true); + + bones.sort(); //sorty so they are always in the same order/index + + for (int i = 0; i < bones.size(); i++) { + bones[i].rest_inverse = bones[i].bone->get_skeleton_rest(); //bind pose + } + + transform_dirty = true; + _update_transform(); +} + +void Skeleton2D::_make_transform_dirty() { + + if (transform_dirty) + return; + transform_dirty = true; + if (is_inside_tree()) { + call_deferred("_update_transform"); + } +} + +void Skeleton2D::_update_transform() { + + if (bone_setup_dirty) { + _update_bone_setup(); + return; //above will update transform anyway + } + if (!transform_dirty) + return; + + transform_dirty = false; + + Transform2D global_xform = get_global_transform(); + Transform2D global_xform_inverse = global_xform.affine_inverse(); + + for (int i = 0; i < bones.size(); i++) { + + Transform2D final_xform = bones[i].rest_inverse * bones[i].bone->get_relative_transform_to_parent(this); + VS::get_singleton()->skeleton_bone_set_transform_2d(skeleton, i, global_xform * (final_xform * global_xform_inverse)); + } +} + +int Skeleton2D::get_bone_count() const { + + ERR_FAIL_COND_V(!is_inside_tree(), 0); + + if (bone_setup_dirty) { + const_cast<Skeleton2D *>(this)->_update_bone_setup(); + } + + return bones.size(); +} + +Bone2D *Skeleton2D::get_bone(int p_idx) { + + ERR_FAIL_COND_V(!is_inside_tree(), NULL); + ERR_FAIL_INDEX_V(p_idx, bones.size(), NULL); + + return bones[p_idx].bone; +} + +void Skeleton2D::_notification(int p_what) { + + if (p_what == NOTIFICATION_READY) { + + if (bone_setup_dirty) + _update_bone_setup(); + if (transform_dirty) + _update_transform(); + } + + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + _make_transform_dirty(); + } +} + +RID Skeleton2D::get_skeleton() const { + return skeleton; +} +void Skeleton2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_update_bone_setup"), &Skeleton2D::_update_bone_setup); + ClassDB::bind_method(D_METHOD("_update_transform"), &Skeleton2D::_update_transform); + + ClassDB::bind_method(D_METHOD("get_bone_count"), &Skeleton2D::get_bone_count); + ClassDB::bind_method(D_METHOD("get_bone"), &Skeleton2D::get_bone); + + ClassDB::bind_method(D_METHOD("get_skeleton"), &Skeleton2D::get_skeleton); +} + +Skeleton2D::Skeleton2D() { + bone_setup_dirty = true; + transform_dirty = true; + skeleton = VS::get_singleton()->skeleton_create(); +} + +Skeleton2D::~Skeleton2D() { + + VS::get_singleton()->free(skeleton); +} diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h new file mode 100644 index 0000000000..49199f684f --- /dev/null +++ b/scene/2d/skeleton_2d.h @@ -0,0 +1,68 @@ +#ifndef SKELETON_2D_H +#define SKELETON_2D_H + +#include "scene/2d/node_2d.h" + +class Skeleton2D; + +class Bone2D : public Node2D { + GDCLASS(Bone2D, Node2D) + + Bone2D *parent_bone; + Skeleton2D *skeleton; + Transform2D rest; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_rest(const Transform2D &p_rest); + Transform2D get_rest() const; + void apply_rest(); + Transform2D get_skeleton_rest() const; + + String get_configuration_warning() const; + + Bone2D(); +}; + +class Skeleton2D : public Node2D { + GDCLASS(Skeleton2D, Node2D); + + friend class Bone2D; + + struct Bone { + bool operator<(const Bone &p_bone) const { + return p_bone.bone->is_greater_than(bone); + } + Bone2D *bone; + Transform2D rest_inverse; + }; + + Vector<Bone> bones; + + bool bone_setup_dirty; + void _make_bone_setup_dirty(); + void _update_bone_setup(); + + bool transform_dirty; + void _make_transform_dirty(); + void _update_transform(); + + RID skeleton; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + int get_bone_count() const; + Bone2D *get_bone(int p_idx); + + RID get_skeleton() const; + Skeleton2D(); + ~Skeleton2D(); +}; + +#endif // SKELETON_2D_H diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 9c344b9581..67f016ae79 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -34,17 +34,27 @@ #include "scene/main/viewport.h" #include "scene/scene_string_names.h" -void Sprite::_edit_set_pivot(const Point2 &p_pivot) { +Dictionary Sprite::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = offset; + return state; +} - set_offset(p_pivot); +void Sprite::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_offset(p_state["offset"]); } -Point2 Sprite::_edit_get_pivot() const { +void Sprite::_edit_set_pivot(const Point2 &p_pivot) { + set_offset(get_offset() - p_pivot); + set_position(get_transform().xform(p_pivot)); +} - return get_offset(); +Point2 Sprite::_edit_get_pivot() const { + return Vector2(); } -bool Sprite::_edit_use_pivot() const { +bool Sprite::_edit_use_pivot() const { return true; } @@ -63,8 +73,8 @@ void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_cli s = s / Size2(hframes, vframes); r_src_rect.size = s; - r_src_rect.position.x += float(frame % hframes) * s.x; - r_src_rect.position.y += float(frame / hframes) * s.y; + r_src_rect.position.x = float(frame % hframes) * s.x; + r_src_rect.position.y = float(frame / hframes) * s.y; } Point2 ofs = offset; @@ -111,7 +121,15 @@ void Sprite::set_texture(const Ref<Texture> &p_texture) { if (p_texture == texture) return; + + if (texture.is_valid()) + texture->remove_change_receptor(this); + texture = p_texture; + + if (texture.is_valid()) + texture->add_change_receptor(this); + update(); emit_signal("texture_changed"); item_rect_changed(); @@ -271,13 +289,39 @@ bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc Rect2 src_rect, dst_rect; bool filter_clip; _get_rects(src_rect, dst_rect, filter_clip); + dst_rect.size = dst_rect.size.abs(); if (!dst_rect.has_point(p_point)) return false; - Vector2 q = ((p_point - dst_rect.position) / dst_rect.size) * src_rect.size + src_rect.position; + Vector2 q = (p_point - dst_rect.position) / dst_rect.size; + if (hflip) + q.x = 1.0f - q.x; + if (vflip) + q.y = 1.0f - q.y; + q = q * src_rect.size + src_rect.position; + + Ref<Image> image; + Ref<AtlasTexture> atlasTexture = texture; + if (atlasTexture.is_null()) { + image = texture->get_data(); + } else { + ERR_FAIL_COND_V(atlasTexture->get_atlas().is_null(), false); + + image = atlasTexture->get_atlas()->get_data(); + + Rect2 region = atlasTexture->get_region(); + Rect2 margin = atlasTexture->get_margin(); + + q -= margin.position; + + if ((q.x > region.size.width) || (q.y > region.size.height)) { + return false; + } + + q += region.position; + } - Ref<Image> image = texture->get_data(); ERR_FAIL_COND_V(image.is_null(), false); image->lock(); @@ -287,7 +331,7 @@ bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc return c.a > 0.01; } -Rect2 Sprite::_edit_get_rect() const { +Rect2 Sprite::get_rect() const { if (texture.is_null()) return Rect2(0, 0, 1, 1); @@ -326,6 +370,15 @@ void Sprite::_validate_property(PropertyInfo &property) const { } } +void Sprite::_changed_callback(Object *p_changed, const char *p_prop) { + + // Changes to the texture need to trigger an update to make + // the editor redraw the sprite with the updated texture. + if (texture.is_valid() && texture.ptr() == p_changed) { + update(); + } +} + void Sprite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite::set_texture); @@ -364,6 +417,8 @@ void Sprite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite::set_hframes); ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite::get_hframes); + ClassDB::bind_method(D_METHOD("get_rect"), &Sprite::get_rect); + ADD_SIGNAL(MethodInfo("frame_changed")); ADD_SIGNAL(MethodInfo("texture_changed")); @@ -398,3 +453,8 @@ Sprite::Sprite() { vframes = 1; hframes = 1; } + +Sprite::~Sprite() { + if (texture.is_valid()) + texture->remove_change_receptor(this); +} diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index 261165bbf9..abd04515ec 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -64,12 +64,17 @@ protected: virtual void _validate_property(PropertyInfo &property) const; + virtual void _changed_callback(Object *p_changed, const char *p_prop); + public: + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + virtual void _edit_set_pivot(const Point2 &p_pivot); virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; - virtual Rect2 _edit_get_rect() const; + virtual Rect2 _edit_get_rect() const { return get_rect(); } void set_texture(const Ref<Texture> &p_texture); Ref<Texture> get_texture() const; @@ -107,7 +112,10 @@ public: void set_hframes(int p_amount); int get_hframes() const; + Rect2 get_rect() const; + Sprite(); + ~Sprite(); }; #endif // SPRITE_H diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 361d765c97..b602839b99 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -142,16 +142,20 @@ void TileMap::_update_quadrant_transform() { void TileMap::set_tileset(const Ref<TileSet> &p_tileset) { - if (tile_set.is_valid()) + if (tile_set.is_valid()) { tile_set->disconnect("changed", this, "_recreate_quadrants"); + tile_set->remove_change_receptor(this); + } _clear_quadrants(); tile_set = p_tileset; - if (tile_set.is_valid()) + if (tile_set.is_valid()) { tile_set->connect("changed", this, "_recreate_quadrants"); - else + tile_set->add_change_receptor(this); + } else { clear(); + } _recreate_quadrants(); emit_signal("settings_changed"); @@ -353,7 +357,7 @@ void TileMap::_update_dirty_quadrants() { } Rect2 r = tile_set->tile_get_region(c.id); - if (tile_set->tile_get_is_autotile(c.id)) { + if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE) { int spacing = tile_set->autotile_get_spacing(c.id); r.size = tile_set->autotile_get_size(c.id); r.position += (r.size + Vector2(spacing, spacing)) * Vector2(c.autotile_coord_x, c.autotile_coord_y); @@ -447,7 +451,7 @@ void TileMap::_update_dirty_quadrants() { for (int i = 0; i < shapes.size(); i++) { Ref<Shape2D> shape = shapes[i].shape; if (shape.is_valid()) { - if (!tile_set->tile_get_is_autotile(c.id) || (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[i].autotile_coord.x == c.autotile_coord_x && shapes[i].autotile_coord.y == c.autotile_coord_y)) { Transform2D xform; xform.set_origin(offset.floor()); @@ -474,7 +478,7 @@ void TileMap::_update_dirty_quadrants() { if (navigation) { Ref<NavigationPolygon> navpoly; Vector2 npoly_ofs; - if (tile_set->tile_get_is_autotile(c.id)) { + if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE) { navpoly = tile_set->autotile_get_navigation_polygon(c.id, Vector2(c.autotile_coord_x, c.autotile_coord_y)); npoly_ofs = Vector2(); } else { @@ -497,7 +501,7 @@ void TileMap::_update_dirty_quadrants() { } Ref<OccluderPolygon2D> occluder; - if (tile_set->tile_get_is_autotile(c.id)) { + if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE) { occluder = tile_set->autotile_get_light_occluder(c.id, Vector2(c.autotile_coord_x, c.autotile_coord_y)); } else { occluder = tile_set->tile_get_light_occluder(c.id); @@ -766,7 +770,7 @@ void TileMap::update_cell_bitmask(int p_x, int p_y) { Map<PosKey, Cell>::Element *E = tile_map.find(p); if (E != NULL) { int id = get_cell(p_x, p_y); - if (tile_set->tile_get_is_autotile(id)) { + if (tile_set->tile_get_tile_mode(id) == TileSet::AUTO_TILE) { uint16_t mask = 0; if (tile_set->autotile_get_bitmask_mode(id) == TileSet::BITMASK_2X2) { if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) { @@ -830,6 +834,16 @@ void TileMap::update_dirty_bitmask() { } } +void TileMap::fix_invalid_tiles() { + + for (Map<PosKey, Cell>::Element *E = tile_map.front(); E; E = E->next()) { + + if (!tile_set->has_tile(get_cell(E->key().x, E->key().y))) { + set_cell(E->key().x, E->key().y, INVALID_CELL); + } + } +} + int TileMap::get_cell(int p_x, int p_y) const { PosKey pk(p_x, p_y); @@ -1515,6 +1529,7 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("is_cell_y_flipped", "x", "y"), &TileMap::is_cell_y_flipped); ClassDB::bind_method(D_METHOD("is_cell_transposed", "x", "y"), &TileMap::is_cell_transposed); + ClassDB::bind_method(D_METHOD("fix_invalid_tiles"), &TileMap::fix_invalid_tiles); ClassDB::bind_method(D_METHOD("clear"), &TileMap::clear); ClassDB::bind_method(D_METHOD("get_used_cells"), &TileMap::get_used_cells); @@ -1573,6 +1588,12 @@ void TileMap::_bind_methods() { BIND_ENUM_CONSTANT(TILE_ORIGIN_BOTTOM_LEFT); } +void TileMap::_changed_callback(Object *p_changed, const char *p_prop) { + if (tile_set.is_valid() && tile_set.ptr() == p_changed) { + emit_signal("settings_changed"); + } +} + TileMap::TileMap() { rect_cache_dirty = true; @@ -1601,5 +1622,8 @@ TileMap::TileMap() { TileMap::~TileMap() { + if (tile_set.is_valid()) + tile_set->remove_change_receptor(this); + clear(); } diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 973e527b42..587bd3b684 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -217,6 +217,8 @@ protected: void _notification(int p_what); static void _bind_methods(); + virtual void _changed_callback(Object *p_changed, const char *p_prop); + public: enum { INVALID_CELL = -1 @@ -308,6 +310,7 @@ public: void set_clip_uv(bool p_enable); bool get_clip_uv() const; + void fix_invalid_tiles(); void clear(); TileMap(); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index d448ef024d..c2a50ec7bb 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -536,14 +536,14 @@ void AudioStreamPlayer3D::_notification(int p_what) { setseek = setplay; active = true; setplay = -1; - //do not update, this makes it easier to animate (will shut off otherise) + //do not update, this makes it easier to animate (will shut off otherwise) ///_change_notify("playing"); //update property in editor } //stop playing if no longer active if (!active) { set_physics_process_internal(false); - //do not update, this makes it easier to animate (will shut off otherise) + //do not update, this makes it easier to animate (will shut off otherwise) //_change_notify("playing"); //update property in editor emit_signal("finished"); } diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index fa4e6492a1..204aaef7ec 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -316,7 +316,7 @@ bool BakedLightmap::_bake_time(void *ud, float p_secs, float p_progress) { int mins_left = p_secs / 60; int secs_left = Math::fmod(p_secs, 60.0f); int percent = p_progress * 100; - bool abort = bake_step_function(btd->pass + percent, btd->text + " " + itos(percent) + "% (Time Left: " + itos(mins_left) + ":" + itos(secs_left) + "s)"); + bool abort = bake_step_function(btd->pass + percent, btd->text + " " + vformat(RTR("%d%%"), percent) + " " + vformat(RTR("(Time Left: %d:%02d s)"), mins_left, secs_left)); btd->last_step = time; if (abort) return true; diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index 07235b3da4..1d5d1b2afe 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -373,7 +373,7 @@ String CollisionObject::get_configuration_warning() const { if (warning == String()) { warning += "\n"; } - warning += TTR("This node has no children shapes, so it can't interact with the space.\nConsider adding CollisionShape or CollisionPolygon children nodes to define its shape."); + warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape or CollisionPolygon as a child to define its shape."); } return warning; diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp index 9865fe156a..ffa283f634 100644 --- a/scene/3d/interpolated_camera.cpp +++ b/scene/3d/interpolated_camera.cpp @@ -38,10 +38,10 @@ void InterpolatedCamera::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { if (Engine::get_singleton()->is_editor_hint() && enabled) - set_physics_process(false); + set_process_internal(false); } break; - case NOTIFICATION_PROCESS: { + case NOTIFICATION_INTERNAL_PROCESS: { if (!enabled) break; @@ -111,9 +111,9 @@ void InterpolatedCamera::set_interpolation_enabled(bool p_enable) { if (p_enable) { if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) return; - set_process(true); + set_process_internal(true); } else - set_process(false); + set_process_internal(false); } bool InterpolatedCamera::is_interpolation_enabled() const { diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index e7ab6cde8a..77bf703706 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -35,6 +35,7 @@ void Navigation::_navmesh_link(int p_id) { ERR_FAIL_COND(!navmesh_map.has(p_id)); NavMesh &nm = navmesh_map[p_id]; ERR_FAIL_COND(nm.linked); + ERR_FAIL_COND(nm.navmesh.is_null()); PoolVector<Vector3> vertices = nm.navmesh->get_vertices(); int len = vertices.size(); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 5c814312dd..ff4a807de0 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -694,6 +694,10 @@ void RigidBody::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); } +void RigidBody::apply_torque_impulse(const Vector3 &p_impulse) { + PhysicsServer::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse); +} + void RigidBody::set_use_continuous_collision_detection(bool p_enable) { ccd = p_enable; @@ -833,6 +837,7 @@ void RigidBody::_bind_methods() { ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody::set_axis_velocity); ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &RigidBody::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody::apply_torque_impulse); ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody::set_sleeping); ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody::is_sleeping); @@ -923,10 +928,10 @@ RigidBody::~RigidBody() { ////////////////////////////////////////////////////// ////////////////////////// -Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion) { +Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_infinite_inertia) { Collision col; - if (move_and_collide(p_motion, col)) { + if (move_and_collide(p_motion, p_infinite_inertia, col)) { if (motion_cache.is_null()) { motion_cache.instance(); motion_cache->owner = this; @@ -940,11 +945,11 @@ Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion) { return Ref<KinematicCollision>(); } -bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_collision) { +bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision) { Transform gt = get_global_transform(); PhysicsServer::MotionResult result; - bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, &result); + bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result); if (colliding) { r_collision.collider_metadata = result.collider_metadata; @@ -970,7 +975,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli return colliding; } -Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) { +Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) { Vector3 lv = p_linear_velocity; @@ -992,7 +997,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve Collision collision; - bool collided = move_and_collide(motion, collision); + bool collided = move_and_collide(motion, p_infinite_inertia, collision); if (collided) { @@ -1065,11 +1070,11 @@ Vector3 KinematicBody::get_floor_velocity() const { return floor_velocity; } -bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion) { +bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia) { ERR_FAIL_COND_V(!is_inside_tree(), false); - return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion); + return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia); } void KinematicBody::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) { @@ -1118,10 +1123,10 @@ Ref<KinematicCollision> KinematicBody::_get_slide_collision(int p_bounce) { void KinematicBody::_bind_methods() { - ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec"), &KinematicBody::_move); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_slides", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); + ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia"), &KinematicBody::_move, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_slides", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(true), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); - ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody::test_move); + ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move); ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling); diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index c7556c0c5f..ffdc9ab309 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -242,6 +242,7 @@ public: Array get_colliding_bodies() const; void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + void apply_torque_impulse(const Vector3 &p_impulse); virtual String get_configuration_warning() const; @@ -285,15 +286,15 @@ private: _FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const; - Ref<KinematicCollision> _move(const Vector3 &p_motion); + Ref<KinematicCollision> _move(const Vector3 &p_motion, bool p_infinite_inertia = true); Ref<KinematicCollision> _get_slide_collision(int p_bounce); protected: static void _bind_methods(); public: - bool move_and_collide(const Vector3 &p_motion, Collision &r_collision); - bool test_move(const Transform &p_from, const Vector3 &p_motion); + bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision); + bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia); void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock); bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const; @@ -301,7 +302,7 @@ public: void set_safe_margin(float p_margin); float get_safe_margin() const; - Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), float p_slope_stop_min_velocity = 0.05, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45)); + Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_infinite_inertia = true, float p_slope_stop_min_velocity = 0.05, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45)); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 721641e09b..f8a5c7f400 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -188,7 +188,9 @@ void Spatial::_notification(int p_what) { if (data.gizmo.is_valid()) { data.gizmo->create(); if (data.gizmo->can_draw()) { - data.gizmo->redraw(); + if (is_visible_in_tree()) { + data.gizmo->redraw(); + } } data.gizmo->transform(); } @@ -409,7 +411,9 @@ void Spatial::set_gizmo(const Ref<SpatialGizmo> &p_gizmo) { data.gizmo->create(); if (data.gizmo->can_draw()) { - data.gizmo->redraw(); + if (is_visible_in_tree()) { + data.gizmo->redraw(); + } } data.gizmo->transform(); } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 9db4a5fb04..04e7d5cc10 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -1010,6 +1010,7 @@ void AnimationPlayer::stop(bool p_reset) { c.blend.clear(); if (p_reset) { c.current.from = NULL; + c.current.speed_scale = 1; } _set_process(false); queued.clear(); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 9dfd388c3d..562dd155f9 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -211,6 +211,11 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { if (!toggle_mode) { //mouse press attempt pressed(); + if (get_script_instance()) { + Variant::CallError ce; + get_script_instance()->call(SceneStringNames::get_singleton()->_pressed, NULL, 0, ce); + } + emit_signal("pressed"); } else { @@ -307,6 +312,8 @@ void BaseButton::toggled(bool p_pressed) { } void BaseButton::set_disabled(bool p_disabled) { + if (status.disabled == p_disabled) + return; status.disabled = p_disabled; update(); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 30bcc48149..31be18612f 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -77,8 +77,7 @@ void ColorPicker::_notification(int p_what) { void ColorPicker::set_focus_on_line_edit() { - c_text->grab_focus(); - c_text->select(); + c_text->call_deferred("grab_focus"); } void ColorPicker::_update_controls() { @@ -159,14 +158,16 @@ void ColorPicker::_update_color() { updating = true; for (int i = 0; i < 4; i++) { - scroll[i]->set_max(255); scroll[i]->set_step(0.01); if (raw_mode_enabled) { + scroll[i]->set_max(100); if (i == 3) scroll[i]->set_max(1); scroll[i]->set_value(color.components[i]); } else { - scroll[i]->set_value(color.components[i] * 255); + const int byte_value = color.components[i] * 255; + scroll[i]->set_max(next_power_of_2(MAX(255, byte_value)) - 1); + scroll[i]->set_value(byte_value); } } @@ -242,6 +243,7 @@ bool ColorPicker::is_raw_mode() const { } void ColorPicker::_update_text_value() { + bool visible = true; if (text_is_constructor) { String t = "Color(" + String::num(color.r) + "," + String::num(color.g) + "," + String::num(color.b); if (edit_alpha && color.a < 1) @@ -250,8 +252,13 @@ void ColorPicker::_update_text_value() { t += ")"; c_text->set_text(t); } else { - c_text->set_text(color.to_html(edit_alpha && color.a < 1)); + if (color.r > 1 || color.g > 1 || color.b > 1 || color.r < 0 || color.g < 0 || color.b < 0) { + visible = false; + } else { + c_text->set_text(color.to_html(edit_alpha && color.a < 1)); + } } + c_text->set_visible(visible); } void ColorPicker::_sample_draw() { @@ -462,6 +469,31 @@ void ColorPicker::_screen_pick_pressed() { screen->show_modal(); } +void ColorPicker::_focus_enter() { + if (c_text->has_focus()) { + c_text->select_all(); + return; + } + for (int i = 0; i < 4; i++) { + if (values[i]->get_line_edit()->has_focus()) { + values[i]->get_line_edit()->select_all(); + break; + } + } +} + +void ColorPicker::_focus_exit() { + for (int i = 0; i < 4; i++) { + values[i]->get_line_edit()->select(0, 0); + } + c_text->select(0, 0); +} + +void ColorPicker::_html_focus_exit() { + _html_entered(c_text->get_text()); + _focus_exit(); +} + void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPicker::set_pick_color); @@ -483,6 +515,9 @@ void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("_w_input"), &ColorPicker::_w_input); ClassDB::bind_method(D_METHOD("_preset_input"), &ColorPicker::_preset_input); ClassDB::bind_method(D_METHOD("_screen_input"), &ColorPicker::_screen_input); + ClassDB::bind_method(D_METHOD("_focus_enter"), &ColorPicker::_focus_enter); + ClassDB::bind_method(D_METHOD("_focus_exit"), &ColorPicker::_focus_exit); + ClassDB::bind_method(D_METHOD("_html_focus_exit"), &ColorPicker::_html_focus_exit); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha"); @@ -559,11 +594,14 @@ ColorPicker::ColorPicker() : scroll[i] = memnew(HSlider); scroll[i]->set_v_size_flags(SIZE_SHRINK_CENTER); + scroll[i]->set_focus_mode(FOCUS_NONE); hbc->add_child(scroll[i]); values[i] = memnew(SpinBox); scroll[i]->share(values[i]); hbc->add_child(values[i]); + values[i]->get_line_edit()->connect("focus_entered", this, "_focus_enter"); + values[i]->get_line_edit()->connect("focus_exited", this, "_focus_exit"); scroll[i]->set_min(0); scroll[i]->set_page(0); @@ -589,6 +627,9 @@ ColorPicker::ColorPicker() : c_text = memnew(LineEdit); hhb->add_child(c_text); c_text->connect("text_entered", this, "_html_entered"); + c_text->connect("focus_entered", this, "_focus_enter"); + c_text->connect("focus_exited", this, "_html_focus_exit"); + text_type->set_text("#"); c_text->set_h_size_flags(SIZE_EXPAND_FILL); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 01ae1cc464..40ded4fff5 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -88,6 +88,9 @@ private: void _screen_input(const Ref<InputEvent> &p_event); void _add_preset_pressed(); void _screen_pick_pressed(); + void _focus_enter(); + void _focus_exit(); + void _html_focus_exit(); protected: void _notification(int); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 01415594d3..a5883863cd 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -49,31 +49,41 @@ Dictionary Control::_edit_get_state() const { Dictionary s; - s["rect"] = get_rect(); s["rotation"] = get_rotation(); s["scale"] = get_scale(); + s["pivot"] = get_pivot_offset(); Array anchors; anchors.push_back(get_anchor(MARGIN_LEFT)); anchors.push_back(get_anchor(MARGIN_TOP)); anchors.push_back(get_anchor(MARGIN_RIGHT)); anchors.push_back(get_anchor(MARGIN_BOTTOM)); s["anchors"] = anchors; + Array margins; + margins.push_back(get_margin(MARGIN_LEFT)); + margins.push_back(get_margin(MARGIN_TOP)); + margins.push_back(get_margin(MARGIN_RIGHT)); + margins.push_back(get_margin(MARGIN_BOTTOM)); + s["margins"] = margins; return s; } void Control::_edit_set_state(const Dictionary &p_state) { Dictionary state = p_state; - Rect2 rect = state["rect"]; - set_position(rect.position); - set_size(rect.size); set_rotation(state["rotation"]); set_scale(state["scale"]); + set_pivot_offset(state["pivot"]); Array anchors = state["anchors"]; - set_anchor(MARGIN_LEFT, anchors[0]); - set_anchor(MARGIN_TOP, anchors[1]); - set_anchor(MARGIN_RIGHT, anchors[2]); - set_anchor(MARGIN_BOTTOM, anchors[3]); + data.anchor[MARGIN_LEFT] = anchors[0]; + data.anchor[MARGIN_TOP] = anchors[1]; + data.anchor[MARGIN_RIGHT] = anchors[2]; + data.anchor[MARGIN_BOTTOM] = anchors[3]; + Array margins = state["margins"]; + data.margin[MARGIN_LEFT] = margins[0]; + data.margin[MARGIN_TOP] = margins[1]; + data.margin[MARGIN_RIGHT] = margins[2]; + data.margin[MARGIN_BOTTOM] = margins[3]; + _size_changed(); } void Control::_edit_set_position(const Point2 &p_position) { @@ -85,19 +95,8 @@ Point2 Control::_edit_get_position() const { }; void Control::_edit_set_rect(const Rect2 &p_edit_rect) { - - Transform2D xform = _get_internal_transform(); - - Vector2 new_pos = xform.basis_xform(p_edit_rect.position); - - Vector2 pos = get_position() + new_pos; - - Rect2 new_rect = get_rect(); - new_rect.position = pos.snapped(Vector2(1, 1)); - new_rect.size = p_edit_rect.size.snapped(Vector2(1, 1)); - - set_position(new_rect.position); - set_size(new_rect.size); + set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1))); + set_size(p_edit_rect.size.snapped(Vector2(1, 1))); } Rect2 Control::_edit_get_rect() const { @@ -121,6 +120,9 @@ bool Control::_edit_use_rotation() const { } void Control::_edit_set_pivot(const Point2 &p_pivot) { + Vector2 delta_pivot = p_pivot - get_pivot_offset(); + Vector2 move = Vector2((cos(data.rotation) - 1.0) * delta_pivot.x - sin(data.rotation) * delta_pivot.y, sin(data.rotation) * delta_pivot.x + (cos(data.rotation) - 1.0) * delta_pivot.y); + set_position(get_position() + move); set_pivot_offset(p_pivot); } @@ -1297,7 +1299,8 @@ void Control::_size_changed() { new_size_cache.height = MAX(minimum_size.height, new_size_cache.height); } - if (get_viewport()->is_snap_controls_to_pixels_enabled()) { + // We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot() + if (Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) { new_size_cache = new_size_cache.floor(); new_pos_cache = new_pos_cache.floor(); } @@ -1378,7 +1381,6 @@ void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bo data.margin[(p_margin + 2) % 4] = _s2a(previous_opposite_margin_pos, data.anchor[(p_margin + 2) % 4], parent_range); } } - if (is_inside_tree()) { _size_changed(); } @@ -2847,7 +2849,7 @@ void Control::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_degrees", "get_rotation_degrees"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); ADD_GROUP("Hint", "hint_"); ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "_get_tooltip"); diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index e61ede7c3d..feb080dd06 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -108,7 +108,7 @@ class AcceptDialog : public WindowDialog { HBoxContainer *hbc; Label *label; Button *ok; - //Button *cancel; no more cancel (there is X on tht titlebar) + //Button *cancel; no more cancel (there is X on that titlebar) bool hide_on_ok; void _custom_action(const String &p_action); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 58717edbae..4bd92d888d 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -210,7 +210,7 @@ void FileDialog::_action_pressed() { bool valid = false; if (filter->get_selected() == filter->get_item_count() - 1) { - valid = true; //match none + valid = true; // match none } else if (filters.size() > 1 && filter->get_selected() == 0) { // match all filters for (int i = 0; i < filters.size(); i++) { @@ -287,7 +287,7 @@ bool FileDialog::_is_open_should_be_disabled() { TreeItem *ti = tree->get_selected(); // We have something that we can't select? if (!ti) - return true; + return mode != MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder. Dictionary d = ti->get_metadata(0); @@ -319,17 +319,15 @@ void FileDialog::deselect_items() { case MODE_OPEN_FILE: case MODE_OPEN_FILES: - get_ok()->set_text(TTR("Open")); - get_ok()->set_disabled(false); + get_ok()->set_text(RTR("Open")); break; - case MODE_OPEN_DIR: - get_ok()->set_text(TTR("Select Current Folder")); - get_ok()->set_disabled(false); + get_ok()->set_text(RTR("Select Current Folder")); break; } } } + void FileDialog::_tree_selected() { TreeItem *ti = tree->get_selected(); @@ -341,13 +339,13 @@ void FileDialog::_tree_selected() { file->set_text(d["name"]); } else if (mode == MODE_OPEN_DIR) { - get_ok()->set_text(TTR("Select this Folder")); + get_ok()->set_text(RTR("Select this Folder")); } get_ok()->set_disabled(_is_open_should_be_disabled()); } -void FileDialog::_tree_dc_selected() { +void FileDialog::_tree_item_activated() { TreeItem *ti = tree->get_selected(); if (!ti) @@ -756,7 +754,7 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("_unhandled_input"), &FileDialog::_unhandled_input); ClassDB::bind_method(D_METHOD("_tree_selected"), &FileDialog::_tree_selected); - ClassDB::bind_method(D_METHOD("_tree_db_selected"), &FileDialog::_tree_dc_selected); + ClassDB::bind_method(D_METHOD("_tree_item_activated"), &FileDialog::_tree_item_activated); ClassDB::bind_method(D_METHOD("_dir_entered"), &FileDialog::_dir_entered); ClassDB::bind_method(D_METHOD("_file_entered"), &FileDialog::_file_entered); ClassDB::bind_method(D_METHOD("_action_pressed"), &FileDialog::_action_pressed); @@ -845,7 +843,7 @@ FileDialog::FileDialog() { HBoxContainer *hbc = memnew(HBoxContainer); dir_up = memnew(ToolButton); - dir_up->set_tooltip(TTR("Go to parent folder")); + dir_up->set_tooltip(RTR("Go to parent folder")); hbc->add_child(dir_up); dir_up->connect("pressed", this, "_go_up"); @@ -881,7 +879,7 @@ FileDialog::FileDialog() { filter = memnew(OptionButton); filter->set_stretch_ratio(3); filter->set_h_size_flags(SIZE_EXPAND_FILL); - filter->set_clip_text(true); //too many extensions overflow it + filter->set_clip_text(true); // too many extensions overflows it hbc->add_child(filter); vbc->add_child(hbc); @@ -890,9 +888,8 @@ FileDialog::FileDialog() { _update_drives(); connect("confirmed", this, "_action_pressed"); - //cancel->connect("pressed", this,"_cancel_pressed"); tree->connect("cell_selected", this, "_tree_selected", varray(), CONNECT_DEFERRED); - tree->connect("item_activated", this, "_tree_db_selected", varray()); + tree->connect("item_activated", this, "_tree_item_activated", varray()); tree->connect("nothing_selected", this, "deselect_items"); dir->connect("text_entered", this, "_dir_entered"); file->connect("text_entered", this, "_file_entered"); @@ -922,7 +919,6 @@ FileDialog::FileDialog() { exterr->set_text(RTR("Must use a valid extension.")); add_child(exterr); - //update_file_list(); update_filters(); update_dir(); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 2a09494682..ad483d5dab 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -107,7 +107,7 @@ private: void _tree_selected(); void _select_drive(int p_idx); - void _tree_dc_selected(); + void _tree_item_activated(); void _dir_entered(String p_dir); void _file_entered(const String &p_file); void _action_pressed(); diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 3985039716..9fc8e98a7f 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -367,6 +367,13 @@ void GradientEdit::_notification(int p_what) { draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); } } + + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + + if (!is_visible()) { + grabbing = false; + } + } } void GradientEdit::_draw_checker(int x, int y, int w, int h) { diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index c2b8a7dfab..b401abd436 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -36,10 +36,10 @@ void GridContainer::_notification(int p_what) { case NOTIFICATION_SORT_CHILDREN: { - Map<int, int> col_minw; - Map<int, int> row_minh; - Set<int> col_expanded; - Set<int> row_expanded; + Map<int, int> col_minw; // max of min_width of all controls in each col (indexed by col) + Map<int, int> row_minh; // max of min_height of all controls in each row (indexed by row) + Set<int> col_expanded; // columns which have the SIZE_EXPAND flag set + Set<int> row_expanded; // rows which have the SIZE_EXPAND flag set int hsep = get_constant("hseparation"); int vsep = get_constant("vseparation"); @@ -84,17 +84,17 @@ void GridContainer::_notification(int p_what) { if (!row_expanded.has(E->key())) remaining_space.height -= E->get(); } - remaining_space.height -= vsep * (max_row - 1); - remaining_space.width -= hsep * (max_col - 1); + remaining_space.height -= vsep * MAX(max_row - 1, 0); + remaining_space.width -= hsep * MAX(max_col - 1, 0); bool can_fit = false; - while (!can_fit) { + while (!can_fit && col_expanded.size() > 0) { // Check if all minwidth constraints are ok if we use the remaining space can_fit = true; - int max_index = 0; + int max_index = col_expanded.front()->get(); for (Set<int>::Element *E = col_expanded.front(); E; E = E->next()) { if (col_minw[E->get()] > col_minw[max_index]) { - max_index = col_minw[E->get()]; + max_index = E->get(); } if (can_fit && (remaining_space.width / col_expanded.size()) < col_minw[E->get()]) { can_fit = false; @@ -109,13 +109,13 @@ void GridContainer::_notification(int p_what) { } can_fit = false; - while (!can_fit) { + while (!can_fit && row_expanded.size() > 0) { // Check if all minwidth constraints are ok if we use the remaining space can_fit = true; - int max_index = 0; + int max_index = row_expanded.front()->get(); for (Set<int>::Element *E = row_expanded.front(); E; E = E->next()) { if (row_minh[E->get()] > row_minh[max_index]) { - max_index = row_minh[E->get()]; + max_index = E->get(); } if (can_fit && (remaining_space.height / row_expanded.size()) < row_minh[E->get()]) { can_fit = false; @@ -130,8 +130,8 @@ void GridContainer::_notification(int p_what) { } // Finally, fit the nodes - int col_expand = remaining_space.width / col_expanded.size(); - int row_expand = remaining_space.height / row_expanded.size(); + int col_expand = col_expanded.size() > 0 ? remaining_space.width / col_expanded.size() : 0; + int row_expand = row_expanded.size() > 0 ? remaining_space.height / row_expanded.size() : 0; int col_ofs = 0; int row_ofs = 0; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index fe85d04003..cc17e6bcd8 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -295,35 +295,21 @@ int ItemList::get_current() const { return current; } -void ItemList::move_item(int p_item, int p_to_pos) { +void ItemList::move_item(int p_from_idx, int p_to_idx) { - ERR_FAIL_INDEX(p_item, items.size()); - ERR_FAIL_INDEX(p_to_pos, items.size() + 1); + ERR_FAIL_INDEX(p_from_idx, items.size()); + ERR_FAIL_INDEX(p_to_idx, items.size()); - Item it = items[p_item]; - items.remove(p_item); - - if (p_to_pos > p_item) { - p_to_pos--; - } - - if (p_to_pos >= items.size()) { - items.push_back(it); - } else { - items.insert(p_to_pos, it); + if (is_anything_selected() && get_selected_items()[0] == p_from_idx) { + current = p_to_idx; } - if (current < 0) { - //do none - } else if (p_item == current) { - current = p_to_pos; - } else if (p_to_pos > p_item && current > p_item && current < p_to_pos) { - current--; - } else if (p_to_pos < p_item && current < p_item && current > p_to_pos) { - current++; - } + Item item = items[p_from_idx]; + items.remove(p_from_idx); + items.insert(p_to_idx, item); update(); + shape_changed = true; } int ItemList::get_item_count() const { @@ -961,12 +947,36 @@ void ItemList::_notification(int p_what) { Vector2 base_ofs = bg->get_offset(); base_ofs.y -= int(scroll_bar->get_value()); - Rect2 clip(Point2(), size - bg->get_minimum_size() + Vector2(0, scroll_bar->get_value())); + const Rect2 clip(-base_ofs, size); // visible frame, don't need to draw outside of there + + int first_item_visible; + { + // do a binary search to find the first item whose rect reaches below clip.position.y + int lo = 0; + int hi = items.size(); + while (lo < hi) { + const int mid = (lo + hi) / 2; + const Rect2 &rcache = items[mid].rect_cache; + if (rcache.position.y + rcache.size.y < clip.position.y) { + lo = mid + 1; + } else { + hi = mid; + } + } + // we might have ended up with column 2, or 3, ..., so let's find the first column + while (lo > 0 && items[lo - 1].rect_cache.position.y == items[lo].rect_cache.position.y) { + lo -= 1; + } + first_item_visible = lo; + } - for (int i = 0; i < items.size(); i++) { + for (int i = first_item_visible; i < items.size(); i++) { Rect2 rcache = items[i].rect_cache; + if (rcache.position.y > clip.position.y + clip.size.y) + break; // done + if (!clip.intersects(rcache)) continue; @@ -1138,8 +1148,28 @@ void ItemList::_notification(int p_what) { } } - for (int i = 0; i < separators.size(); i++) { - draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(width, base_ofs.y + separators[i]), guide_color); + int first_visible_separator = 0; + { + // do a binary search to find the first separator that is below clip_position.y + int lo = 0; + int hi = separators.size(); + while (lo < hi) { + const int mid = (lo + hi) / 2; + if (separators[mid] < clip.position.y) { + lo = mid + 1; + } else { + hi = mid; + } + } + first_visible_separator = lo; + } + + for (int i = first_visible_separator; i < separators.size(); i++) { + if (separators[i] > clip.position.y + clip.size.y) + break; // done + + const int y = base_ofs.y + separators[i]; + draw_line(Vector2(bg->get_margin(MARGIN_LEFT), y), Vector2(width, y), guide_color); } } } @@ -1379,9 +1409,13 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("select", "idx", "single"), &ItemList::select, DEFVAL(true)); ClassDB::bind_method(D_METHOD("unselect", "idx"), &ItemList::unselect); + ClassDB::bind_method(D_METHOD("unselect_all"), &ItemList::unselect_all); + ClassDB::bind_method(D_METHOD("is_selected", "idx"), &ItemList::is_selected); ClassDB::bind_method(D_METHOD("get_selected_items"), &ItemList::get_selected_items); + ClassDB::bind_method(D_METHOD("move_item", "p_from_idx", "p_to_idx"), &ItemList::move_item); + ClassDB::bind_method(D_METHOD("get_item_count"), &ItemList::get_item_count); ClassDB::bind_method(D_METHOD("remove_item", "idx"), &ItemList::remove_item); @@ -1421,6 +1455,8 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("set_auto_height", "enable"), &ItemList::set_auto_height); ClassDB::bind_method(D_METHOD("has_auto_height"), &ItemList::has_auto_height); + ClassDB::bind_method(D_METHOD("is_anything_selected"), &ItemList::is_anything_selected); + ClassDB::bind_method(D_METHOD("get_item_at_position", "position", "exact"), &ItemList::get_item_at_position, DEFVAL(false)); ClassDB::bind_method(D_METHOD("ensure_current_is_visible"), &ItemList::ensure_current_is_visible); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 7f34a250bd..0fa0dd415b 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -169,7 +169,7 @@ public: void set_current(int p_current); int get_current() const; - void move_item(int p_item, int p_to_pos); + void move_item(int p_from_idx, int p_to_idx); int get_item_count() const; void remove_item(int p_idx); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 03dc6686b8..5c0e8fefc7 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -373,12 +373,14 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { case KEY_UP: { shift_selection_check_pre(k->get_shift()); + if (get_cursor_position() == 0) handled = false; set_cursor_position(0); shift_selection_check_post(k->get_shift()); } break; case KEY_DOWN: { shift_selection_check_pre(k->get_shift()); + if (get_cursor_position() == text.length()) handled = false; set_cursor_position(text.length()); shift_selection_check_post(k->get_shift()); } break; diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 1a46921561..6e53f11b99 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -75,6 +75,10 @@ void OptionButton::_notification(int p_what) { } } +void OptionButton::_focused(int p_which) { + emit_signal("item_focused", p_which); +} + void OptionButton::_selected(int p_which) { int selid = -1; @@ -290,6 +294,7 @@ void OptionButton::get_translatable_strings(List<String> *p_strings) const { void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_selected"), &OptionButton::_selected); + ClassDB::bind_method(D_METHOD("_focused"), &OptionButton::_focused); ClassDB::bind_method(D_METHOD("add_item", "label", "id"), &OptionButton::add_item, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id"), &OptionButton::add_icon_item); @@ -318,9 +323,11 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_items"), &OptionButton::_set_items); ClassDB::bind_method(D_METHOD("_get_items"), &OptionButton::_get_items); - ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); + // "selected" property must come after "items", otherwise GH-10213 occurs + ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected"); ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "ID"))); + ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "ID"))); } OptionButton::OptionButton() { @@ -335,6 +342,7 @@ OptionButton::OptionButton() { popup->set_as_toplevel(true); popup->set_pass_on_modal_close_click(false); popup->connect("id_pressed", this, "_selected"); + popup->connect("id_focused", this, "_focused"); } OptionButton::~OptionButton() { diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index f65fa1b631..d5f866d806 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -43,6 +43,7 @@ class OptionButton : public Button { PopupMenu *popup; int current; + void _focused(int p_which); void _selected(int p_which); void _select(int p_which, bool p_emit = false); void _select_int(int p_which); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 89000fcde1..747230e69f 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -211,86 +211,69 @@ void PopupMenu::_scroll(float p_factor, const Point2 &p_over) { void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { - Ref<InputEventKey> k = p_event; - - if (k.is_valid()) { - - if (!k->is_pressed()) - return; - - switch (k->get_scancode()) { - - case KEY_DOWN: { - - int search_from = mouse_over + 1; - if (search_from >= items.size()) - search_from = 0; - - for (int i = search_from; i < items.size(); i++) { + if (p_event->is_action("ui_down") && p_event->is_pressed()) { - if (i < 0 || i >= items.size()) - continue; + int search_from = mouse_over + 1; + if (search_from >= items.size()) + search_from = 0; - if (!items[i].separator && !items[i].disabled) { + for (int i = search_from; i < items.size(); i++) { - mouse_over = i; - update(); - break; - } - } - } break; - case KEY_UP: { - - int search_from = mouse_over - 1; - if (search_from < 0) - search_from = items.size() - 1; - - for (int i = search_from; i >= 0; i--) { - - if (i < 0 || i >= items.size()) - continue; - - if (!items[i].separator && !items[i].disabled) { + if (i < 0 || i >= items.size()) + continue; - mouse_over = i; - update(); - break; - } - } - } break; + if (!items[i].separator && !items[i].disabled) { - case KEY_LEFT: { + mouse_over = i; + emit_signal("id_focused", i); + update(); + accept_event(); + break; + } + } + } else if (p_event->is_action("ui_up") && p_event->is_pressed()) { - Node *n = get_parent(); - if (!n) - break; + int search_from = mouse_over - 1; + if (search_from < 0) + search_from = items.size() - 1; - PopupMenu *pm = Object::cast_to<PopupMenu>(n); - if (!pm) - break; + for (int i = search_from; i >= 0; i--) { - hide(); - } break; + if (i < 0 || i >= items.size()) + continue; - case KEY_RIGHT: { + if (!items[i].separator && !items[i].disabled) { - if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) - _activate_submenu(mouse_over); - } break; + mouse_over = i; + emit_signal("id_focused", i); + update(); + accept_event(); + break; + } + } + } else if (p_event->is_action("ui_left") && p_event->is_pressed()) { - case KEY_ENTER: - case KEY_KP_ENTER: { + Node *n = get_parent(); + if (n && Object::cast_to<PopupMenu>(n)) { + hide(); + accept_event(); + } + } else if (p_event->is_action("ui_right") && p_event->is_pressed()) { - if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { + if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) { + _activate_submenu(mouse_over); + accept_event(); + } + } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { - if (items[mouse_over].submenu != "" && submenu_over != mouse_over) { - _activate_submenu(mouse_over); - break; - } + if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { - activate_item(mouse_over); - } - } break; + if (items[mouse_over].submenu != "" && submenu_over != mouse_over) { + _activate_submenu(mouse_over); + } else { + activate_item(mouse_over); + } + accept_event(); } } @@ -1229,6 +1212,7 @@ void PopupMenu::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection"); ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "ID"))); + ADD_SIGNAL(MethodInfo("id_focused", PropertyInfo(Variant::INT, "ID"))); ADD_SIGNAL(MethodInfo("index_pressed", PropertyInfo(Variant::INT, "index"))); } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 381c6c75a5..ae07d5e671 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -125,6 +125,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & l.descent_caches.clear(); l.char_count = 0; l.minimum_width = 0; + l.maximum_width = 0; } int wofs = margin; @@ -200,7 +201,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & #define ENSURE_WIDTH(m_width) \ if (p_mode == PROCESS_CACHE) { \ - l.minimum_width = MAX(l.minimum_width, wofs + m_width); \ + l.maximum_width = MAX(l.maximum_width, MIN(p_width, wofs + m_width)); \ + l.minimum_width = MAX(l.minimum_width, m_width); \ } \ if (wofs + m_width > p_width) { \ if (p_mode == PROCESS_CACHE) { \ @@ -247,6 +249,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int rchar = 0; int lh = 0; bool line_is_blank = true; + int fh = 0; while (it) { @@ -262,14 +265,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & const CharType *c = text->text.c_str(); const CharType *cf = c; - int fh = font->get_height(); int ascent = font->get_ascent(); int descent = font->get_descent(); - line_ascent = MAX(line_ascent, ascent); - line_descent = MAX(line_descent, descent); - fh = MAX(fh, line_ascent + line_descent); // various fonts! - Color color; bool underline = false; @@ -317,8 +315,13 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & end++; } + CHECK_HEIGHT(fh); ENSURE_WIDTH(w); + line_ascent = MAX(line_ascent, ascent); + line_descent = MAX(line_descent, descent); + fh = line_ascent + line_descent; + if (end && c[end - 1] == ' ') { if (p_mode == PROCESS_CACHE) { spaces_size += font->get_char_size(' ').width; @@ -468,6 +471,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & //set minimums to zero for (int i = 0; i < table->columns.size(); i++) { table->columns[i].min_width = 0; + table->columns[i].max_width = 0; table->columns[i].width = 0; } //compute minimum width for each cell @@ -485,6 +489,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & _process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color()); table->columns[column].min_width = MAX(table->columns[column].min_width, frame->lines[i].minimum_width); + table->columns[column].max_width = MAX(table->columns[column].max_width, frame->lines[i].maximum_width); } idx++; } @@ -497,12 +502,13 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < table->columns.size(); i++) { remaining_width -= table->columns[i].min_width; + if (table->columns[i].max_width > table->columns[i].min_width) + table->columns[i].expand = true; if (table->columns[i].expand) total_ratio += table->columns[i].expand_ratio; } //assign actual widths - for (int i = 0; i < table->columns.size(); i++) { table->columns[i].width = table->columns[i].min_width; if (table->columns[i].expand) @@ -1632,7 +1638,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { tag_stack.push_front(tag); } else if (tag.begins_with("cell=")) { - int ratio = tag.substr(6, tag.length()).to_int(); + int ratio = tag.substr(5, tag.length()).to_int(); if (ratio < 1) ratio = 1; //use monospace font diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index e7d5e6bb1b..83938cff61 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -87,6 +87,7 @@ private: int height_accum_cache; int char_count; int minimum_width; + int maximum_width; Line() { from = NULL; @@ -199,6 +200,7 @@ private: bool expand; int expand_ratio; int min_width; + int max_width; int width; }; diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index 95fcda2db3..e1cabd3f88 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -199,54 +199,40 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { } } - Ref<InputEventKey> k = p_event; + if (p_event->is_pressed()) { - if (k.is_valid()) { + if (p_event->is_action("ui_left")) { - if (!k->is_pressed()) - return; - - switch (k->get_scancode()) { - - case KEY_LEFT: { - - if (orientation != HORIZONTAL) - return; - set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); + if (orientation != HORIZONTAL) + return; + set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); - } break; - case KEY_RIGHT: { + } else if (p_event->is_action("ui_right")) { - if (orientation != HORIZONTAL) - return; - set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - - } break; - case KEY_UP: { + if (orientation != HORIZONTAL) + return; + set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - if (orientation != VERTICAL) - return; + } else if (p_event->is_action("ui_up")) { - set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); + if (orientation != VERTICAL) + return; - } break; - case KEY_DOWN: { + set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); - if (orientation != VERTICAL) - return; - set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); + } else if (p_event->is_action("ui_down")) { - } break; - case KEY_HOME: { + if (orientation != VERTICAL) + return; + set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - set_value(get_min()); + } else if (p_event->is_action("ui_home")) { - } break; - case KEY_END: { + set_value(get_min()); - set_value(get_max()); + } else if (p_event->is_action("ui_end")) { - } break; + set_value(get_max()); } } } diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index a7a1b499c3..46215c9277 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -118,28 +118,14 @@ void Slider::_gui_input(Ref<InputEvent> p_event) { return; set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); accept_event(); + } else if (p_event->is_action("ui_home") && p_event->is_pressed()) { - } else { - - Ref<InputEventKey> k = p_event; - - if (!k.is_valid() || !k->is_pressed()) - return; - - switch (k->get_scancode()) { - - case KEY_HOME: { - - set_value(get_min()); - accept_event(); - } break; - case KEY_END: { - - set_value(get_max()); - accept_event(); + set_value(get_min()); + accept_event(); + } else if (p_event->is_action("ui_end") && p_event->is_pressed()) { - } break; - } + set_value(get_max()); + accept_event(); } } } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 0312e58094..6e85ce5eb4 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -474,21 +474,24 @@ void TabContainer::remove_child_notify(Node *p_child) { Control::remove_child_notify(p_child); - int tc = get_tab_count(); - if (current == tc - 1) { - current--; - if (current < 0) - current = 0; - else { - call_deferred("set_current_tab", current); - } - } + call_deferred("_update_current_tab"); p_child->disconnect("renamed", this, "_child_renamed_callback"); update(); } +void TabContainer::_update_current_tab() { + + int tc = get_tab_count(); + if (current >= tc) + current = tc - 1; + if (current < 0) + current = 0; + else + set_current_tab(current); +} + void TabContainer::set_tab_align(TabAlign p_align) { ERR_FAIL_INDEX(p_align, 3); @@ -664,6 +667,7 @@ void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("_child_renamed_callback"), &TabContainer::_child_renamed_callback); ClassDB::bind_method(D_METHOD("_on_theme_changed"), &TabContainer::_on_theme_changed); + ClassDB::bind_method(D_METHOD("_update_current_tab"), &TabContainer::_update_current_tab); ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab"))); ADD_SIGNAL(MethodInfo("tab_selected", PropertyInfo(Variant::INT, "tab"))); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 0ba8c205ea..4bc6e00145 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -62,6 +62,7 @@ private: Vector<Control *> _get_tabs() const; int _get_tab_width(int p_index) const; void _on_theme_changed(); + void _update_current_tab(); protected: void _child_renamed_callback(); diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index f0e89877cd..dee32aef7a 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -882,4 +882,6 @@ Tabs::Tabs() { min_width = 0; scrolling_enabled = true; + buttons_visible = false; + hover = -1; } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index e8454e021f..48bd733e80 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -628,7 +628,7 @@ void TextEdit::_notification(int p_what) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color); } //compute actual region to start (may be inside say, a comment). - //slow in very large documments :( but ok for source! + //slow in very large documents :( but ok for source! for (int i = 0; i < cursor.line_ofs; i++) { @@ -776,7 +776,6 @@ void TextEdit::_notification(int p_what) { j--; } if (escaped) { - j--; cc = '\\'; continue; } @@ -2142,9 +2141,12 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (completion_index > 0) { completion_index--; - completion_current = completion_options[completion_index]; - update(); + } else { + completion_index = completion_options.size() - 1; } + completion_current = completion_options[completion_index]; + update(); + accept_event(); return; } @@ -2153,9 +2155,12 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (completion_index < completion_options.size() - 1) { completion_index++; - completion_current = completion_options[completion_index]; - update(); + } else { + completion_index = 0; } + completion_current = completion_options[completion_index]; + update(); + accept_event(); return; } @@ -4471,7 +4476,7 @@ bool TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_from_l ERR_FAIL_INDEX_V(p_from_line, text.size(), false); ERR_FAIL_INDEX_V(p_from_column, text[p_from_line].length() + 1, false); - //search through the whole documment, but start by current line + //search through the whole document, but start by current line int line = p_from_line; int pos = -1; @@ -5233,7 +5238,7 @@ void TextEdit::_update_completion_candidates() { } else { - while (cofs > 0 && l[cofs - 1] > 32 && _is_completable(l[cofs - 1])) { + while (cofs > 0 && l[cofs - 1] > 32 && (l[cofs - 1] == '/' || _is_completable(l[cofs - 1]))) { s = String::chr(l[cofs - 1]) + s; if (l[cofs - 1] == '\'' || l[cofs - 1] == '"' || l[cofs - 1] == '$') break; diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 01b00c34ea..4b3ba6df3c 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -117,22 +117,45 @@ Point2 TextureProgress::unit_val_to_uv(float val) { Point2 p = get_relative_center(); - if (val < 0.125) - return Point2(p.x + (1 - p.x) * val * 8, 0); - if (val < 0.25) - return Point2(1, p.y * (val - 0.125) * 8); - if (val < 0.375) - return Point2(1, p.y + (1 - p.y) * (val - 0.25) * 8); - if (val < 0.5) - return Point2(1 - (1 - p.x) * (val - 0.375) * 8, 1); - if (val < 0.625) - return Point2(p.x * (1 - (val - 0.5) * 8), 1); - if (val < 0.75) - return Point2(0, 1 - ((1 - p.y) * (val - 0.625) * 8)); - if (val < 0.875) - return Point2(0, p.y - p.y * (val - 0.75) * 8); - else - return Point2(p.x * (val - 0.875) * 8, 0); + // Minimal version of Liang-Barsky clipping algorithm + float angle = (val * Math_TAU) - Math_PI * 0.5; + Point2 dir = Vector2(Math::cos(angle), Math::sin(angle)); + float t1 = 1.0; + float cp; + float cq; + float cr; + float edgeLeft = 0.0; + float edgeRight = 1.0; + float edgeBottom = 0.0; + float edgeTop = 1.0; + + for (int edge = 0; edge < 4; edge++) { + if (edge == 0) { + if (dir.x > 0) + continue; + cp = -dir.x; + cq = -(edgeLeft - p.x); + } else if (edge == 1) { + if (dir.x < 0) + continue; + cp = dir.x; + cq = (edgeRight - p.x); + } else if (edge == 2) { + if (dir.y > 0) + continue; + cp = -dir.y; + cq = -(edgeBottom - p.y); + } else if (edge == 3) { + if (dir.y < 0) + continue; + cp = dir.y; + cq = (edgeTop - p.y); + } + cr = cq / cp; + if (cr >= 0 && cr < t1) + t1 = cr; + } + return (p + t1 * dir); } Point2 TextureProgress::get_relative_center() { @@ -158,7 +181,7 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F if (p_ratio < 1.0) { // Drawing a partially-filled 9-patch is a little tricky - // texture is divided by 3 sections toward fill direction, - // then middle section is streching while the other two aren't. + // then middle section is stretching while the other two aren't. double width_total = 0.0; double width_texture = 0.0; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index cdbdc9b0d7..e7f63997f2 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2061,322 +2061,318 @@ void Tree::popup_select(int p_option) { item_edited(popup_edited_item_col, popup_edited_item); } -void Tree::_gui_input(Ref<InputEvent> p_event) { - - Ref<InputEventKey> k = p_event; +void Tree::_go_left() { + if (selected_col == 0) { + if (selected_item->get_children() != NULL && !selected_item->is_collapsed()) { + selected_item->set_collapsed(true); + } else { + if (columns.size() == 1) { // goto parent with one column + TreeItem *parent = selected_item->get_parent(); + if (selected_item != get_root() && parent && parent->is_selectable(selected_col) && !(hide_root && parent == get_root())) { + select_single_item(parent, get_root(), selected_col); + } + } else if (selected_item->get_prev_visible()) { + selected_col = columns.size() - 1; + _go_up(); // go to upper column if possible + } + } + } else { + if (select_mode == SELECT_MULTI) { + selected_col--; + emit_signal("cell_selected"); + } else { - if (k.is_valid()) { + selected_item->select(selected_col - 1); + } + } + update(); + accept_event(); + ensure_cursor_is_visible(); +} - if (!k->is_pressed()) - return; - if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) - return; - if (!root) +void Tree::_go_right() { + if (selected_col == (columns.size() - 1)) { + if (selected_item->get_children() != NULL && selected_item->is_collapsed()) { + selected_item->set_collapsed(false); + } else if (selected_item->get_next_visible()) { + selected_item->select(0); + _go_down(); return; + } + } else { + if (select_mode == SELECT_MULTI) { + selected_col++; + emit_signal("cell_selected"); + } else { - if (hide_root && !root->get_next_visible()) + selected_item->select(selected_col + 1); + } + } + update(); + ensure_cursor_is_visible(); + accept_event(); +} + +void Tree::_go_up() { + TreeItem *prev = NULL; + if (!selected_item) { + prev = get_last_item(); + selected_col = 0; + } else { + + prev = selected_item->get_prev_visible(); + if (last_keypress != 0) { + //incr search next + int col; + prev = _search_item_text(prev, incr_search, &col, true, true); + if (!prev) { + accept_event(); + return; + } + } + } + + if (select_mode == SELECT_MULTI) { + + if (!prev) return; + selected_item = prev; + emit_signal("cell_selected"); + update(); + } else { - switch (k->get_scancode()) { -#define EXIT_BREAK \ - { \ - if (!cursor_can_exit_tree) accept_event(); \ - break; \ + int col = selected_col < 0 ? 0 : selected_col; + while (prev && !prev->cells[col].selectable) + prev = prev->get_prev_visible(); + if (!prev) + return; // do nothing.. + prev->select(col); } - case KEY_RIGHT: { - bool dobreak = true; - //TreeItem *next = NULL; - if (!selected_item) - break; - if (select_mode == SELECT_ROW) { - EXIT_BREAK; - } - if (selected_col > (columns.size() - 1)) { - EXIT_BREAK; - } - if (k->get_alt()) { - selected_item->set_collapsed(false); - TreeItem *next = selected_item->get_children(); - while (next && next != selected_item->next) { - next->set_collapsed(false); - next = next->get_next_visible(); - } - } else if (selected_col == (columns.size() - 1)) { - if (selected_item->get_children() != NULL && selected_item->is_collapsed()) { - selected_item->set_collapsed(false); - } else { - selected_col = 0; - dobreak = false; // fall through to key_down - } - } else { - if (select_mode == SELECT_MULTI) { - selected_col++; - emit_signal("cell_selected"); - } else { + ensure_cursor_is_visible(); + accept_event(); +} - selected_item->select(selected_col + 1); - } - } - update(); - ensure_cursor_is_visible(); +void Tree::_go_down() { + TreeItem *next = NULL; + if (!selected_item) { + + next = hide_root ? root->get_next_visible() : root; + selected_item = 0; + } else { + + next = selected_item->get_next_visible(); + + if (last_keypress != 0) { + //incr search next + int col; + next = _search_item_text(next, incr_search, &col, true); + if (!next) { accept_event(); - if (dobreak) { - break; - } + return; } - case KEY_DOWN: { + } + } - TreeItem *next = NULL; - if (!selected_item) { + if (select_mode == SELECT_MULTI) { - next = hide_root ? root->get_next_visible() : root; - selected_item = 0; - } else { + if (!next) { + return; + } - next = selected_item->get_next_visible(); + selected_item = next; + emit_signal("cell_selected"); + update(); + } else { - //if (diff < uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000))) { - if (last_keypress != 0) { - //incr search next - int col; - next = _search_item_text(next, incr_search, &col, true); - if (!next) { - accept_event(); - return; - } - } - } + int col = selected_col < 0 ? 0 : selected_col; - if (select_mode == SELECT_MULTI) { + while (next && !next->cells[col].selectable) + next = next->get_next_visible(); + if (!next) { + return; // do nothing.. + } + next->select(col); + } - if (!next) - EXIT_BREAK; + ensure_cursor_is_visible(); + accept_event(); +} - selected_item = next; - emit_signal("cell_selected"); - update(); - } else { +void Tree::_gui_input(Ref<InputEvent> p_event) { - int col = selected_col < 0 ? 0 : selected_col; + Ref<InputEventKey> k = p_event; - while (next && !next->cells[col].selectable) - next = next->get_next_visible(); - if (!next) - EXIT_BREAK; // do nothing.. - next->select(col); - } + if (p_event->is_action("ui_right") && p_event->is_pressed()) { - ensure_cursor_is_visible(); - accept_event(); + if (!cursor_can_exit_tree) accept_event(); - } break; - case KEY_LEFT: { - bool dobreak = true; + if (!selected_item || select_mode == SELECT_ROW || selected_col > (columns.size() - 1)) { + return; + } + if (k.is_valid() && k->get_alt()) { + selected_item->set_collapsed(false); + TreeItem *next = selected_item->get_children(); + while (next && next != selected_item->next) { + next->set_collapsed(false); + next = next->get_next_visible(); + } + } else { + _go_right(); + } + } else if (p_event->is_action("ui_left") && p_event->is_pressed()) { - //TreeItem *next = NULL; - if (!selected_item) - break; - if (select_mode == SELECT_ROW) { - EXIT_BREAK; - } - if (selected_col < 0) { - EXIT_BREAK; - } - if (k->get_alt()) { - selected_item->set_collapsed(true); - TreeItem *next = selected_item->get_children(); - while (next && next != selected_item->next) { - next->set_collapsed(true); - next = next->get_next_visible(); - } - } else if (selected_col == 0) { - if (selected_item->get_children() != NULL && !selected_item->is_collapsed()) { - selected_item->set_collapsed(true); - } else { - if (columns.size() == 1) { // goto parent with one column - TreeItem *parent = selected_item->get_parent(); - if (selected_item != get_root() && parent && parent->is_selectable(selected_col) && !(hide_root && parent == get_root())) { - select_single_item(parent, get_root(), selected_col); - } - } else { - selected_col = columns.size() - 1; - dobreak = false; // fall through to key_up - } - } - } else { - if (select_mode == SELECT_MULTI) { - selected_col--; - emit_signal("cell_selected"); - } else { + if (!cursor_can_exit_tree) accept_event(); - selected_item->select(selected_col - 1); - } - } - update(); - accept_event(); - ensure_cursor_is_visible(); + if (!selected_item || select_mode == SELECT_ROW || selected_col < 0) { + return; + } - if (dobreak) { - break; - } + if (k.is_valid() && k->get_alt()) { + selected_item->set_collapsed(true); + TreeItem *next = selected_item->get_children(); + while (next && next != selected_item->next) { + next->set_collapsed(true); + next = next->get_next_visible(); } - case KEY_UP: { + } else { + _go_left(); + } - TreeItem *prev = NULL; - if (!selected_item) { - prev = get_last_item(); - selected_col = 0; - } else { + } else if (p_event->is_action("ui_up") && p_event->is_pressed()) { - prev = selected_item->get_prev_visible(); - if (last_keypress != 0) { - //incr search next - int col; - prev = _search_item_text(prev, incr_search, &col, true, true); - if (!prev) { - accept_event(); - return; - } - } - } + if (!cursor_can_exit_tree) accept_event(); - if (select_mode == SELECT_MULTI) { + _go_up(); - if (!prev) - break; - selected_item = prev; - emit_signal("cell_selected"); - update(); - } else { + } else if (p_event->is_action("ui_down") && p_event->is_pressed()) { - int col = selected_col < 0 ? 0 : selected_col; - while (prev && !prev->cells[col].selectable) - prev = prev->get_prev_visible(); - if (!prev) - break; // do nothing.. - prev->select(col); - } + if (!cursor_can_exit_tree) accept_event(); - ensure_cursor_is_visible(); - accept_event(); + _go_down(); - } break; - case KEY_PAGEDOWN: { + } else if (p_event->is_action("ui_page_down") && p_event->is_pressed()) { - TreeItem *next = NULL; - if (!selected_item) - break; - next = selected_item; + if (!cursor_can_exit_tree) accept_event(); - for (int i = 0; i < 10; i++) { + TreeItem *next = NULL; + if (!selected_item) + return; + next = selected_item; - TreeItem *_n = next->get_next_visible(); - if (_n) { - next = _n; - } else { + for (int i = 0; i < 10; i++) { - break; - } - } - if (next == selected_item) - break; + TreeItem *_n = next->get_next_visible(); + if (_n) { + next = _n; + } else { - if (select_mode == SELECT_MULTI) { + return; + } + } + if (next == selected_item) + return; - selected_item = next; - emit_signal("cell_selected"); - update(); - } else { + if (select_mode == SELECT_MULTI) { - while (next && !next->cells[selected_col].selectable) - next = next->get_next_visible(); - if (!next) - EXIT_BREAK; // do nothing.. - next->select(selected_col); - } + selected_item = next; + emit_signal("cell_selected"); + update(); + } else { - ensure_cursor_is_visible(); - } break; - case KEY_PAGEUP: { + while (next && !next->cells[selected_col].selectable) + next = next->get_next_visible(); + if (!next) { + return; // do nothing.. + } + next->select(selected_col); + } - TreeItem *prev = NULL; - if (!selected_item) - break; - prev = selected_item; + ensure_cursor_is_visible(); + } else if (p_event->is_action("ui_page_up") && p_event->is_pressed()) { - for (int i = 0; i < 10; i++) { + if (!cursor_can_exit_tree) accept_event(); - TreeItem *_n = prev->get_prev_visible(); - if (_n) { - prev = _n; - } else { + TreeItem *prev = NULL; + if (!selected_item) + return; + prev = selected_item; - break; - } - } - if (prev == selected_item) - break; + for (int i = 0; i < 10; i++) { - if (select_mode == SELECT_MULTI) { + TreeItem *_n = prev->get_prev_visible(); + if (_n) { + prev = _n; + } else { - selected_item = prev; - emit_signal("cell_selected"); - update(); - } else { + return; + } + } + if (prev == selected_item) + return; - while (prev && !prev->cells[selected_col].selectable) - prev = prev->get_prev_visible(); - if (!prev) - EXIT_BREAK; // do nothing.. - prev->select(selected_col); - } + if (select_mode == SELECT_MULTI) { - ensure_cursor_is_visible(); + selected_item = prev; + emit_signal("cell_selected"); + update(); + } else { - } break; - case KEY_F2: - case KEY_ENTER: - case KEY_KP_ENTER: { - - if (selected_item) { - //bring up editor if possible - if (!edit_selected()) { - emit_signal("item_activated"); - incr_search.clear(); - } - } - accept_event(); + while (prev && !prev->cells[selected_col].selectable) + prev = prev->get_prev_visible(); + if (!prev) { + return; // do nothing.. + } + prev->select(selected_col); + } + ensure_cursor_is_visible(); + } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { - } break; - case KEY_SPACE: { - if (select_mode == SELECT_MULTI) { - if (!selected_item) - break; - if (selected_item->is_selected(selected_col)) { - selected_item->deselect(selected_col); - emit_signal("multi_selected", selected_item, selected_col, false); - } else if (selected_item->is_selectable(selected_col)) { - selected_item->select(selected_col); - emit_signal("multi_selected", selected_item, selected_col, true); - } - } - accept_event(); + if (selected_item) { + //bring up editor if possible + if (!edit_selected()) { + emit_signal("item_activated"); + incr_search.clear(); + } + } + accept_event(); + } else if (p_event->is_action("ui_select") && p_event->is_pressed()) { - } break; - default: { + if (select_mode == SELECT_MULTI) { + if (!selected_item) + return; + if (selected_item->is_selected(selected_col)) { + selected_item->deselect(selected_col); + emit_signal("multi_selected", selected_item, selected_col, false); + } else if (selected_item->is_selectable(selected_col)) { + selected_item->select(selected_col); + emit_signal("multi_selected", selected_item, selected_col, true); + } + } + accept_event(); + } + + if (k.is_valid()) { // Incremental search + + if (!k->is_pressed()) + return; + if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) + return; + if (!root) + return; - if (k->get_unicode() > 0) { + if (hide_root && !root->get_next_visible()) + return; - _do_incr_search(String::chr(k->get_unicode())); - accept_event(); + if (k->get_unicode() > 0) { - return; - } else { - if (k->get_scancode() != KEY_SHIFT) - last_keypress = 0; - } - } break; + _do_incr_search(String::chr(k->get_unicode())); + accept_event(); + + return; + } else { + if (k->get_scancode() != KEY_SHIFT) + last_keypress = 0; } } @@ -3911,6 +3907,8 @@ Tree::Tree() { cache.click_id = -1; cache.click_item = NULL; cache.click_column = 0; + cache.hover_cell = -1; + cache.hover_index = -1; last_keypress = 0; focus_in_id = 0; diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 2a8546a743..5af66c5faa 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -507,6 +507,10 @@ private: ValueEvaluator *evaluator; int _count_selected_items(TreeItem *p_from) const; + void _go_left(); + void _go_right(); + void _go_down(); + void _go_up(); protected: static void _bind_methods(); diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 3d58aa65f8..ae21775c55 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -121,7 +121,7 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h } if (!has_user_agent) { - headers.push_back("User-Agent: GodotEngine/" + String(VERSION_MKSTRING) + " (" + OS::get_singleton()->get_name() + ")"); + headers.push_back("User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")"); } if (!has_accept) { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index ac85dd64af..cf22383e36 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2010,7 +2010,7 @@ void Node::set_editable_instance(Node *p_node, bool p_editable) { if (!p_editable) { data.editable_instances.erase(p); // Avoid this flag being needlessly saved; - // also give more visual feedback if editable children is reenabled + // also give more visual feedback if editable children is re-enabled set_display_folded(false); } else { data.editable_instances[p] = true; diff --git a/scene/main/node.h b/scene/main/node.h index 4655071228..341869f7ba 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -104,7 +104,7 @@ private: StringName name; SceneTree *tree; bool inside_tree; - bool ready_notified; //this is a small hack, so if a node is added during _ready() to the tree, it corretly gets the _ready() notification + bool ready_notified; //this is a small hack, so if a node is added during _ready() to the tree, it correctly gets the _ready() notification bool ready_first; #ifdef TOOLS_ENABLED NodePath import_path; //path used when imported, used by scene editors to keep tracking diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 55ae9fe1ec..037331dec1 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -498,14 +498,14 @@ bool SceneTree::idle(float p_time) { Size2 win_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height); if (win_size != last_screen_size) { + last_screen_size = win_size; + _update_root_rect(); + if (use_font_oversampling) { DynamicFontAtSize::font_oversampling = OS::get_singleton()->get_window_size().width / root->get_visible_rect().size.width; DynamicFont::update_oversampling(); } - last_screen_size = win_size; - _update_root_rect(); - emit_signal("screen_resized"); } @@ -615,6 +615,8 @@ void SceneTree::_notification(int p_notification) { } } break; case NOTIFICATION_OS_MEMORY_WARNING: + case NOTIFICATION_WM_MOUSE_ENTER: + case NOTIFICATION_WM_MOUSE_EXIT: case NOTIFICATION_WM_FOCUS_IN: case NOTIFICATION_WM_FOCUS_OUT: { @@ -1778,7 +1780,7 @@ void SceneTree::_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, cons psc->id = last_send_cache_id++; } - //create base packet, lots of harcode because it must be tight + //create base packet, lots of hardcode because it must be tight int ofs = 0; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 1ff1f4b6d8..08fbf44469 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -192,6 +192,7 @@ Viewport::GUI::GUI() { } ///////////////////////////////////// + void Viewport::_update_stretch_transform() { if (size_override_stretch && size_override) { @@ -318,6 +319,11 @@ void Viewport::_notification(int p_what) { first->make_current(); } #endif + + // Enable processing for tooltips, collision debugging, physics object picking, etc. + set_process_internal(true); + set_physics_process_internal(true); + } break; case NOTIFICATION_EXIT_TREE: { @@ -345,15 +351,18 @@ void Viewport::_notification(int p_what) { VS::get_singleton()->viewport_set_active(viewport, false); } break; - case NOTIFICATION_PHYSICS_PROCESS: { + case NOTIFICATION_INTERNAL_PROCESS: { if (gui.tooltip_timer >= 0) { - gui.tooltip_timer -= get_physics_process_delta_time(); + gui.tooltip_timer -= get_process_delta_time(); if (gui.tooltip_timer < 0) { _gui_show_tooltip(); } } + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (get_tree()->is_debugging_collisions_hint() && contact_2d_debug.is_valid()) { VisualServer::get_singleton()->canvas_item_clear(contact_2d_debug); @@ -1925,6 +1934,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Ref<InputEventGesture> gesture_event = p_event; if (gesture_event.is_valid()) { + gui.key_event_accepted = false; + _gui_cancel_tooltip(); Size2 pos = gesture_event->get_position(); @@ -2017,6 +2028,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { top->notification(Control::NOTIFICATION_MODAL_CLOSE); top->_modal_stack_remove(); top->hide(); + // Close modal, set input as handled + get_tree()->set_input_as_handled(); + return; } } @@ -2404,9 +2418,14 @@ Rect2 Viewport::get_attach_to_screen_rect() const { void Viewport::set_physics_object_picking(bool p_enable) { physics_object_picking = p_enable; - set_physics_process(physics_object_picking); - if (!physics_object_picking) + if (!physics_object_picking) { physics_picking_events.clear(); + } +} + +bool Viewport::get_physics_object_picking() { + + return physics_object_picking; } Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const { @@ -2420,11 +2439,6 @@ Vector2 Viewport::get_camera_rect_size() const { return size; } -bool Viewport::get_physics_object_picking() { - - return physics_object_picking; -} - bool Viewport::gui_has_modal_stack() const { return gui.modal_stack.size(); @@ -2789,6 +2803,7 @@ Viewport::Viewport() { gui.drag_preview = NULL; gui.drag_attempted = false; gui.canvas_sort_index = 0; + gui.roots_order_dirty = false; msaa = MSAA_DISABLED; hdr = true; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index bb0cf168af..19d8f09ebe 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -46,6 +46,7 @@ #include "scene/2d/light_2d.h" #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/parallax_background.h" #include "scene/2d/parallax_layer.h" @@ -434,6 +435,7 @@ void register_scene_types() { ClassDB::register_class<AnimatedSprite>(); ClassDB::register_class<Position2D>(); ClassDB::register_class<Line2D>(); + ClassDB::register_class<MeshInstance2D>(); ClassDB::register_virtual_class<CollisionObject2D>(); ClassDB::register_virtual_class<PhysicsBody2D>(); ClassDB::register_class<StaticBody2D>(); diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp index ea313b5a20..29ffefd9d6 100644 --- a/scene/resources/bit_mask.cpp +++ b/scene/resources/bit_mask.cpp @@ -42,7 +42,7 @@ void BitMap::create(const Size2 &p_size) { zeromem(bitmask.ptrw(), bitmask.size()); } -void BitMap::create_from_image_alpha(const Ref<Image> &p_image) { +void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshold) { ERR_FAIL_COND(p_image.is_null() || p_image->empty()); Ref<Image> img = p_image->duplicate(); @@ -58,8 +58,9 @@ void BitMap::create_from_image_alpha(const Ref<Image> &p_image) { int bbyte = i / 8; int bbit = i % 8; - if (r[i * 2]) + if (r[i * 2 + 1] / 255.0 > p_threshold) { w[bbyte] |= (1 << bbit); + } } } @@ -168,10 +169,351 @@ Dictionary BitMap::_get_data() const { return d; } +Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) const { + + int stepx = 0; + int stepy = 0; + int prevx = 0; + int prevy = 0; + int startx = start.x; + int starty = start.y; + int curx = startx; + int cury = starty; + unsigned int count = 0; + Set<Point2i> case9s; + Set<Point2i> case6s; + int i; + Vector<Vector2> _points; + do { + int sv = 0; + { //square value + + /* + checking the 2x2 pixel grid, assigning these values to each pixel, if not transparent + +---+---+ + | 1 | 2 | + +---+---+ + | 4 | 8 | <- current pixel (curx,cury) + +---+---+ + */ + //NOTE: due to the way we pick points from texture, rect needs to be smaller, otherwise it goes outside 1 pixel + Rect2i fixed_rect = Rect2i(rect.position, rect.size - Size2i(2, 2)); + Point2i tl = Point2i(curx - 1, cury - 1); + sv += (fixed_rect.has_point(tl) && get_bit(tl)) ? 1 : 0; + Point2i tr = Point2i(curx, cury - 1); + sv += (fixed_rect.has_point(tr) && get_bit(tr)) ? 2 : 0; + Point2i bl = Point2i(curx - 1, cury); + sv += (fixed_rect.has_point(bl) && get_bit(bl)) ? 4 : 0; + Point2i br = Point2i(curx, cury); + sv += (fixed_rect.has_point(br) && get_bit(br)) ? 8 : 0; + ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector2>()); + } + + switch (sv) { + + case 1: + case 5: + case 13: + /* going UP with these cases: + 1 5 13 + +---+---+ +---+---+ +---+---+ + | 1 | | | 1 | | | 1 | | + +---+---+ +---+---+ +---+---+ + | | | | 4 | | | 4 | 8 | + +---+---+ +---+---+ +---+---+ + */ + stepx = 0; + stepy = -1; + break; + + case 8: + case 10: + case 11: + /* going DOWN with these cases: + 8 10 11 + +---+---+ +---+---+ +---+---+ + | | | | | 2 | | 1 | 2 | + +---+---+ +---+---+ +---+---+ + | | 8 | | | 8 | | | 8 | + +---+---+ +---+---+ +---+---+ + */ + stepx = 0; + stepy = 1; + break; + + case 4: + case 12: + case 14: + /* going LEFT with these cases: + 4 12 14 + +---+---+ +---+---+ +---+---+ + | | | | | | | | 2 | + +---+---+ +---+---+ +---+---+ + | 4 | | | 4 | 8 | | 4 | 8 | + +---+---+ +---+---+ +---+---+ + */ + stepx = -1; + stepy = 0; + break; + + case 2: + case 3: + case 7: + /* going RIGHT with these cases: + 2 3 7 + +---+---+ +---+---+ +---+---+ + | | 2 | | 1 | 2 | | 1 | 2 | + +---+---+ +---+---+ +---+---+ + | | | | | | | 4 | | + +---+---+ +---+---+ +---+---+ + */ + stepx = 1; + stepy = 0; + break; + case 9: + /* + +---+---+ + | 1 | | + +---+---+ + | | 8 | + +---+---+ + this should normally go UP, but if we already been here, we go down + */ + if (case9s.has(Point2i(curx, cury))) { + //found, so we go down, and delete from case9s; + stepx = 0; + stepy = 1; + case9s.erase(Point2i(curx, cury)); + } else { + //not found, we go up, and add to case9s; + stepx = 0; + stepy = -1; + case9s.insert(Point2i(curx, cury)); + } + break; + case 6: + /* + 6 + +---+---+ + | | 2 | + +---+---+ + | 4 | | + +---+---+ + this normally go RIGHT, but if its coming from UP, it should go LEFT + */ + if (case6s.has(Point2i(curx, cury))) { + //found, so we go down, and delete from case6s; + stepx = -1; + stepy = 0; + case6s.erase(Point2i(curx, cury)); + } else { + //not found, we go up, and add to case6s; + stepx = 1; + stepy = 0; + case6s.insert(Point2i(curx, cury)); + } + break; + default: + ERR_PRINT("this shouldn't happen."); + } + //little optimization + // if previous direction is same as current direction, + // then we should modify the last vec to current + curx += stepx; + cury += stepy; + if (stepx == prevx && stepy == prevy) { + _points[_points.size() - 1].x = (float)(curx - rect.position.x); + _points[_points.size() - 1].y = (float)(cury + rect.position.y); + } else { + _points.push_back(Vector2((float)(curx - rect.position.x), (float)(cury + rect.position.y))); + } + + count++; + prevx = stepx; + prevy = stepy; + + ERR_FAIL_COND_V(count > width * height, _points); + } while (curx != startx || cury != starty); + return _points; +} + +static float perpendicular_distance(const Vector2 &i, const Vector2 &start, const Vector2 &end) { + float res; + float slope; + float intercept; + + if (start.x == end.x) { + res = Math::absf(i.x - end.x); + } else if (start.y == end.y) { + res = Math::absf(i.y - end.y); + } else { + slope = (end.y - start.y) / (end.x - start.x); + intercept = start.y - (slope * start.x); + res = Math::absf(slope * i.x - i.y + intercept) / Math::sqrt(Math::pow(slope, 2.0f) + 1.0); + } + return res; +} + +static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) { + if (v.size() < 3) + return v; + + int index = -1; + float dist = 0; + //not looping first and last point + for (size_t i = 1, size = v.size(); i < size - 1; ++i) { + float cdist = perpendicular_distance(v[i], v[0], v[v.size() - 1]); + if (cdist > dist) { + dist = cdist; + index = static_cast<int>(i); + } + } + if (dist > optimization) { + + Vector<Vector2> left, right; + left.resize(index); + for (int i = 0; i < index; i++) { + left[i] = v[i]; + } + right.resize(v.size() - index); + for (int i = 0; i < right.size(); i++) { + right[i] = v[index + i]; + } + Vector<Vector2> r1 = rdp(left, optimization); + Vector<Vector2> r2 = rdp(right, optimization); + + int middle = r1.size(); + r1.resize(r1.size() + r2.size()); + for (int i = 0; i < r2.size(); i++) { + r1[middle + i] = r2[i]; + } + return r1; + } else { + Vector<Vector2> ret; + ret.push_back(v[0]); + ret.push_back(v[v.size() - 1]); + return ret; + } +} + +static Vector<Vector2> reduce(const Vector<Vector2> &points, const Rect2i &rect, float epsilon) { + int size = points.size(); + // if there are less than 3 points, then we have nothing + ERR_FAIL_COND_V(size < 3, Vector<Vector2>()); + // if there are less than 9 points (but more than 3), then we don't need to reduce it + if (size < 9) { + return points; + } + + float maxEp = MIN(rect.size.width, rect.size.height); + float ep = CLAMP(epsilon, 0.0, maxEp / 2); + Vector<Vector2> result = rdp(points, ep); + + Vector2 last = result[result.size() - 1]; + + if (last.y > result[0].y && last.distance_to(result[0]) < ep * 0.5f) { + result[0].y = last.y; + result.resize(result.size() - 1); + } + return result; +} + +static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_pos, const Rect2i &rect) { + + for (int i = p_pos.x - 1; i <= p_pos.x + 1; i++) { + for (int j = p_pos.y - 1; j <= p_pos.y + 1; j++) { + + if (i < rect.position.x || i >= rect.position.x + rect.size.x) + continue; + if (j < rect.position.y || j >= rect.position.y + rect.size.y) + continue; + + if (p_map->get_bit(Vector2(i, j))) + continue; + + else if (p_src->get_bit(Vector2(i, j))) { + p_map->set_bit(Vector2(i, j), true); + fill_bits(p_src, p_map, Point2i(i, j), rect); + } + } + } +} +Vector<Vector<Vector2> > BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const { + + Rect2i r = Rect2i(0, 0, width, height).clip(p_rect); + + print_line("Rect: " + r); + Point2i from; + Ref<BitMap> fill; + fill.instance(); + fill->create(get_size()); + + Vector<Vector<Vector2> > polygons; + for (int i = r.position.y; i < r.position.y + r.size.height; i++) { + for (int j = r.position.x; j < r.position.x + r.size.width; j++) { + if (!fill->get_bit(Point2(j, i)) && get_bit(Point2(j, i))) { + + Vector<Vector2> polygon = _march_square(r, Point2i(j, i)); + print_line("pre reduce: " + itos(polygon.size())); + polygon = reduce(polygon, r, p_epsilon); + print_line("post reduce: " + itos(polygon.size())); + polygons.push_back(polygon); + fill_bits(this, fill, Point2i(j, i), r); + } + } + } + + return polygons; +} + +void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) { + + Rect2i r = Rect2i(0, 0, width, height).clip(p_rect); + + Ref<BitMap> copy; + copy.instance(); + copy->create(get_size()); + copy->bitmask = bitmask; + + for (int i = r.position.y; i < r.position.y + r.size.height; i++) { + for (int j = r.position.x; j < r.position.x + r.size.width; j++) { + if (copy->get_bit(Point2(j, i))) + continue; + + bool found = false; + + for (int y = i - p_pixels; y <= i + p_pixels; y++) { + for (int x = j - p_pixels; x <= j + p_pixels; x++) { + + if (x < p_rect.position.x || x >= p_rect.position.x + p_rect.size.x) + continue; + if (y < p_rect.position.y || y >= p_rect.position.y + p_rect.size.y) + continue; + + float d = Point2(j, i).distance_to(Point2(x, y)) - CMP_EPSILON; + if (d > p_pixels) + continue; + + if (copy->get_bit(Point2(x, y))) { + found = true; + break; + } + } + if (found) + break; + } + + if (found) { + set_bit(Point2(j, i), true); + } + } + } +} + void BitMap::_bind_methods() { ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create); - ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image"), &BitMap::create_from_image_alpha); + ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image", "threshold"), &BitMap::create_from_image_alpha, DEFVAL(0.1)); ClassDB::bind_method(D_METHOD("set_bit", "position", "bit"), &BitMap::set_bit); ClassDB::bind_method(D_METHOD("get_bit", "position"), &BitMap::get_bit); diff --git a/scene/resources/bit_mask.h b/scene/resources/bit_mask.h index cf126ef96b..dcd5edb4fb 100644 --- a/scene/resources/bit_mask.h +++ b/scene/resources/bit_mask.h @@ -44,6 +44,8 @@ class BitMap : public Resource { int width; int height; + Vector<Vector2> _march_square(const Rect2i &rect, const Point2i &start) const; + protected: void _set_data(const Dictionary &p_d); Dictionary _get_data() const; @@ -52,7 +54,7 @@ protected: public: void create(const Size2 &p_size); - void create_from_image_alpha(const Ref<Image> &p_image); + void create_from_image_alpha(const Ref<Image> &p_image, float p_threshold = 0.1); void set_bit(const Point2 &p_pos, bool p_value); bool get_bit(const Point2 &p_pos) const; @@ -61,6 +63,10 @@ public: Size2 get_size() const; + void grow_mask(int p_pixels, const Rect2 &p_rect); + + Vector<Vector<Vector2> > clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon = 2.0) const; + BitMap(); }; diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index e9d5ca969e..26e29b3ccb 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -80,6 +80,14 @@ void DynamicFontData::set_force_autohinter(bool p_force) { void DynamicFontData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_font_path", "path"), &DynamicFontData::set_font_path); ClassDB::bind_method(D_METHOD("get_font_path"), &DynamicFontData::get_font_path); + ClassDB::bind_method(D_METHOD("set_hinting", "mode"), &DynamicFontData::set_hinting); + ClassDB::bind_method(D_METHOD("get_hinting"), &DynamicFontData::get_hinting); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting"); + + BIND_ENUM_CONSTANT(HINTING_NONE); + BIND_ENUM_CONSTANT(HINTING_LIGHT); + BIND_ENUM_CONSTANT(HINTING_NORMAL); ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_path", PROPERTY_HINT_FILE, "*.ttf,*.otf"), "set_font_path", "get_font_path"); } @@ -87,6 +95,7 @@ void DynamicFontData::_bind_methods() { DynamicFontData::DynamicFontData() { force_autohinter = false; + hinting = DynamicFontData::HINTING_NORMAL; font_mem = NULL; font_mem_size = 0; } @@ -186,10 +195,25 @@ Error DynamicFontAtSize::_load() { ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER ); }*/ - error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling); + if (FT_HAS_COLOR(face)) { + int best_match = 0; + int diff = ABS(id.size - face->available_sizes[0].width); + scale_color_font = float(id.size) / face->available_sizes[0].width; + for (int i = 1; i < face->num_fixed_sizes; i++) { + int ndiff = ABS(id.size - face->available_sizes[i].width); + if (ndiff < diff) { + best_match = i; + diff = ndiff; + scale_color_font = float(id.size) / face->available_sizes[i].width; + } + } + error = FT_Select_Size(face, best_match); + } else { + error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling); + } - ascent = (face->size->metrics.ascender >> 6) / oversampling; - descent = (-face->size->metrics.descender >> 6) / oversampling; + ascent = (face->size->metrics.ascender >> 6) / oversampling * scale_color_font; + descent = (-face->size->metrics.descender >> 6) / oversampling * scale_color_font; linegap = 0; texture_flags = 0; if (id.mipmaps) @@ -197,8 +221,6 @@ Error DynamicFontAtSize::_load() { if (id.filter) texture_flags |= Texture::FLAG_FILTER; - //print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER)); - valid = true; return OK; } @@ -286,7 +308,6 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const V ret.x += (delta.x >> 6) / oversampling; } } - return ret; } @@ -328,14 +349,18 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT if (!ch->found) continue; - Point2 cpos = p_pos; cpos.x += ch->h_align; - cpos.y -= get_ascent(); + cpos.y -= fb->get_ascent(); cpos.y += ch->v_align; ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= fb->textures.size(), 0); - if (ch->texture_idx != -1) - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect_uv, p_modulate, false, RID(), false); + if (ch->texture_idx != -1) { + Color modulate = p_modulate; + if (FT_HAS_COLOR(fb->face)) { + modulate.r = modulate.g = modulate.b = 1; + } + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size * Vector2(fb->scale_color_font, fb->scale_color_font)), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect_uv, modulate, false, RID(), false); + } advance = ch->advance; used_fallback = true; break; @@ -356,8 +381,13 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT cpos.y -= get_ascent(); cpos.y += c->v_align; ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0); - if (c->texture_idx != -1) - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect_uv, p_modulate, false, RID(), false); + if (c->texture_idx != -1) { + Color modulate = p_modulate; + if (FT_HAS_COLOR(face)) { + modulate.r = modulate.g = modulate.b = 1; + } + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size * Vector2(scale_color_font, scale_color_font)), textures[c->texture_idx].texture->get_rid(), c->rect_uv, modulate, false, RID(), false); + } advance = c->advance; //textures[c->texture_idx].texture->draw(p_canvas_item,Vector2()); } @@ -431,15 +461,28 @@ void DynamicFontAtSize::_update_char(CharType p_char) { char_map[p_char] = ch; return; } - int error = FT_Load_Char(face, p_char, FT_LOAD_RENDER | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); + + int ft_hinting; + + switch (font->hinting) { + case DynamicFontData::HINTING_NONE: + ft_hinting = FT_LOAD_NO_HINTING; + break; + case DynamicFontData::HINTING_LIGHT: + ft_hinting = FT_LOAD_TARGET_LIGHT; + break; + default: + ft_hinting = FT_LOAD_TARGET_NORMAL; + break; + } + + int error = FT_Load_Char(face, p_char, FT_HAS_COLOR(face) ? FT_LOAD_COLOR : FT_LOAD_DEFAULT | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0) | ft_hinting); if (!error) { - error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); } if (error) { int advance = 0; - //stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0); - //print_line("char has no bitmap: "+itos(p_char)+" but advance is "+itos(advance*scale)); Character ch; ch.texture_idx = -1; ch.advance = advance; @@ -454,7 +497,6 @@ void DynamicFontAtSize::_update_char(CharType p_char) { int w = slot->bitmap.width; int h = slot->bitmap.rows; - //int p = slot->bitmap.pitch; int yofs = slot->bitmap_top; int xofs = slot->bitmap_left; int advance = slot->advance.x >> 6; @@ -470,6 +512,8 @@ void DynamicFontAtSize::_update_char(CharType p_char) { //find a texture to fit this... + int color_size = slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2; + Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; int tex_index = -1; int tex_x = 0; int tex_y = 0; @@ -478,6 +522,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) { CharTexture &ct = textures[i]; + if (ct.texture->get_format() != require_format) + continue; + if (mw > ct.texture_size || mh > ct.texture_size) //too big for this texture continue; @@ -508,8 +555,6 @@ void DynamicFontAtSize::_update_char(CharType p_char) { break; } - //print_line("CHAR: "+String::chr(p_char)+" TEX INDEX: "+itos(tex_index)+" X: "+itos(tex_x)+" Y: "+itos(tex_y)); - if (tex_index == -1) { //could not find texture to fit, create one tex_x = 0; @@ -527,13 +572,13 @@ void DynamicFontAtSize::_update_char(CharType p_char) { CharTexture tex; tex.texture_size = texsize; - tex.imgdata.resize(texsize * texsize * 2); //grayscale alpha + tex.imgdata.resize(texsize * texsize * color_size); { //zero texture PoolVector<uint8_t>::Write w = tex.imgdata.write(); - ERR_FAIL_COND(texsize * texsize * 2 > tex.imgdata.size()); - for (int i = 0; i < texsize * texsize * 2; i++) { + ERR_FAIL_COND(texsize * texsize * color_size > tex.imgdata.size()); + for (int i = 0; i < texsize * texsize * color_size; i++) { w[i] = 0; } } @@ -555,7 +600,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { - int ofs = ((i + tex_y + rect_margin) * tex.texture_size + j + tex_x + rect_margin) * 2; + int ofs = ((i + tex_y + rect_margin) * tex.texture_size + j + tex_x + rect_margin) * color_size; ERR_FAIL_COND(ofs >= tex.imgdata.size()); switch (slot->bitmap.pixel_mode) { case FT_PIXEL_MODE_MONO: { @@ -568,7 +613,14 @@ void DynamicFontAtSize::_update_char(CharType p_char) { wr[ofs + 0] = 255; //grayscale as 1 wr[ofs + 1] = slot->bitmap.buffer[i * slot->bitmap.pitch + j]; break; - // TODO: FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_BGRA + case FT_PIXEL_MODE_BGRA: { + int ofs_color = i * slot->bitmap.pitch + (j << 2); + wr[ofs + 2] = slot->bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = slot->bitmap.buffer[ofs_color + 1]; + wr[ofs + 0] = slot->bitmap.buffer[ofs_color + 2]; + wr[ofs + 3] = slot->bitmap.buffer[ofs_color + 3]; + } break; + // TODO: FT_PIXEL_MODE_LCD default: ERR_EXPLAIN("Font uses unsupported pixel format: " + itos(slot->bitmap.pixel_mode)); ERR_FAIL(); @@ -581,7 +633,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { //blit to image and texture { - Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata)); + Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, require_format, tex.imgdata)); if (tex.texture.is_null()) { tex.texture.instance(); @@ -599,9 +651,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) { } Character chr; - chr.h_align = xofs / oversampling; - chr.v_align = ascent - (yofs / oversampling); // + ascent - descent; - chr.advance = advance / oversampling; + chr.h_align = xofs * scale_color_font / oversampling; + chr.v_align = ascent - (yofs * scale_color_font / oversampling); // + ascent - descent; + chr.advance = advance * scale_color_font / oversampling; chr.texture_idx = tex_index; chr.found = true; @@ -610,8 +662,6 @@ void DynamicFontAtSize::_update_char(CharType p_char) { chr.rect.position /= oversampling; chr.rect.size /= oversampling; - //print_line("CHAR: "+String::chr(p_char)+" TEX INDEX: "+itos(tex_index)+" RECT: "+chr.rect+" X OFS: "+itos(xofs)+" Y OFS: "+itos(yofs)); - char_map[p_char] = chr; } @@ -640,6 +690,7 @@ DynamicFontAtSize::DynamicFontAtSize() { linegap = 1; texture_flags = 0; oversampling = font_oversampling; + scale_color_font = 1; } DynamicFontAtSize::~DynamicFontAtSize() { @@ -722,6 +773,18 @@ void DynamicFont::set_use_filter(bool p_enable) { _reload_cache(); } +DynamicFontData::Hinting DynamicFontData::get_hinting() const { + + return hinting; +} + +void DynamicFontData::set_hinting(Hinting p_hinting) { + + if (hinting == p_hinting) + return; + hinting = p_hinting; +} + int DynamicFont::get_spacing(int p_type) const { if (p_type == SPACING_TOP) { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 92bb77bed3..db8bd87587 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -64,10 +64,20 @@ public: } }; + enum Hinting { + HINTING_NONE, + HINTING_LIGHT, + HINTING_NORMAL + }; + + Hinting get_hinting() const; + void set_hinting(Hinting p_hinting); + private: const uint8_t *font_mem; int font_mem_size; bool force_autohinter; + Hinting hinting; String font_path; Map<CacheID, DynamicFontAtSize *> size_cache; @@ -91,6 +101,8 @@ public: ~DynamicFontData(); }; +VARIANT_ENUM_CAST(DynamicFontData::Hinting); + class DynamicFontAtSize : public Reference { GDCLASS(DynamicFontAtSize, Reference) @@ -106,6 +118,7 @@ class DynamicFontAtSize : public Reference { float linegap; float rect_margin; float oversampling; + float scale_color_font; uint32_t texture_flags; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 8a1978cf85..a83ef198fb 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -737,15 +737,18 @@ void SpatialMaterial::_update_shader() { } } - if (features[FEATURE_REFRACTION] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //refraction not supported with triplanar + if (features[FEATURE_REFRACTION]) { if (features[FEATURE_NORMAL_MAPPING]) { code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * NORMALMAP.x + BINORMAL * NORMALMAP.y + NORMAL * NORMALMAP.z,NORMALMAP_DEPTH) );\n"; } else { code += "\tvec3 ref_normal = NORMAL;\n"; } - - code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(triplanar_texture(texture_refraction,uv1_power_normal,uv1_triplanar_pos),refraction_texture_channel) * refraction;\n"; + } else { + code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n"; + } code += "\tfloat ref_amount = 1.0 - albedo.a * albedo_tex.a;\n"; code += "\tEMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n"; code += "\tALBEDO *= 1.0 - ref_amount;\n"; @@ -1479,9 +1482,9 @@ bool SpatialMaterial::is_grow_enabled() const { return grow_enabled; } -void SpatialMaterial::set_alpha_scissor_threshold(float p_treshold) { - alpha_scissor_threshold = p_treshold; - VS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_treshold); +void SpatialMaterial::set_alpha_scissor_threshold(float p_threshold) { + alpha_scissor_threshold = p_threshold; + VS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold); } float SpatialMaterial::get_alpha_scissor_threshold() const { diff --git a/scene/resources/material.h b/scene/resources/material.h index 10bbcfd642..2c297cda41 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -566,7 +566,7 @@ public: void set_grow(float p_grow); float get_grow() const; - void set_alpha_scissor_threshold(float p_treshold); + void set_alpha_scissor_threshold(float p_threshold); float get_alpha_scissor_threshold() const; void set_on_top_of_alpha(); diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 1eaa007bd7..94a7a055a3 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -189,7 +189,7 @@ public: }; /** - Similar to quadmesh but with tesselation support + Similar to quadmesh but with tessellation support */ class PlaneMesh : public PrimitiveMesh { diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp index 78a19050f1..a9dec3e87c 100644 --- a/scene/resources/ray_shape.cpp +++ b/scene/resources/ray_shape.cpp @@ -43,7 +43,10 @@ Vector<Vector3> RayShape::_gen_debug_mesh_lines() { void RayShape::_update_shape() { - PhysicsServer::get_singleton()->shape_set_data(get_shape(), length); + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); emit_changed(); } @@ -52,6 +55,7 @@ void RayShape::set_length(float p_length) { length = p_length; _update_shape(); notify_change_to_owners(); + _change_notify("length"); } float RayShape::get_length() const { @@ -59,16 +63,33 @@ float RayShape::get_length() const { return length; } +void RayShape::set_slips_on_slope(bool p_active) { + + slips_on_slope = p_active; + _update_shape(); + notify_change_to_owners(); + _change_notify("slips_on_slope"); +} + +bool RayShape::get_slips_on_slope() const { + return slips_on_slope; +} + void RayShape::_bind_methods() { ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape::set_length); ClassDB::bind_method(D_METHOD("get_length"), &RayShape::get_length); + ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape::set_slips_on_slope); + ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape::get_slips_on_slope); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "length", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_length", "get_length"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); } RayShape::RayShape() : Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_RAY)) { set_length(1.0); + set_slips_on_slope(false); } diff --git a/scene/resources/ray_shape.h b/scene/resources/ray_shape.h index 4bd96116fe..f11b2e7c3c 100644 --- a/scene/resources/ray_shape.h +++ b/scene/resources/ray_shape.h @@ -36,6 +36,7 @@ class RayShape : public Shape { GDCLASS(RayShape, Shape); float length; + bool slips_on_slope; protected: static void _bind_methods(); @@ -46,6 +47,9 @@ public: void set_length(float p_length); float get_length() const; + void set_slips_on_slope(bool p_active); + bool get_slips_on_slope() const; + RayShape(); }; #endif // RAY_SHAPE_H diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index 91c801c016..030b822f3b 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -1445,8 +1445,15 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, static String _valprop(const String &p_name) { - if (p_name.find("\"") != -1 || p_name.find("=") != -1 || p_name.find(" ") != -1) - return "\"" + p_name.c_escape_multiline() + "\""; + // Escape and quote strings with extended ASCII or further Unicode characters + // as well as '"', '=' or ' ' (32) + const CharType *cstr = p_name.c_str(); + for (int i = 0; cstr[i]; i++) { + if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] < 33 || cstr[i] > 126) { + return "\"" + p_name.c_escape_multiline() + "\""; + } + } + // Keep as is return p_name; } @@ -1506,7 +1513,6 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r title += "load_steps=" + itos(load_steps) + " "; } title += "format=" + itos(FORMAT_VERSION) + ""; - //title+="engine_version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\""; f->store_string(title); f->store_line("]\n"); //one empty line diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp index 81110015b5..58027c127d 100644 --- a/scene/resources/segment_shape_2d.cpp +++ b/scene/resources/segment_shape_2d.cpp @@ -106,7 +106,10 @@ SegmentShape2D::SegmentShape2D() : void RayShape2D::_update_shape() { - Physics2DServer::get_singleton()->shape_set_data(get_rid(), length); + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + Physics2DServer::get_singleton()->shape_set_data(get_rid(), d); emit_changed(); } @@ -140,7 +143,11 @@ void RayShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape2D::set_length); ClassDB::bind_method(D_METHOD("get_length"), &RayShape2D::get_length); + ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape2D::set_slips_on_slope); + ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape2D::get_slips_on_slope); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "length"), "set_length", "get_length"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); } void RayShape2D::set_length(real_t p_length) { @@ -153,9 +160,20 @@ real_t RayShape2D::get_length() const { return length; } +void RayShape2D::set_slips_on_slope(bool p_active) { + + slips_on_slope = p_active; + _update_shape(); +} + +bool RayShape2D::get_slips_on_slope() const { + return slips_on_slope; +} + RayShape2D::RayShape2D() : Shape2D(Physics2DServer::get_singleton()->ray_shape_create()) { length = 20; + slips_on_slope = false; _update_shape(); } diff --git a/scene/resources/segment_shape_2d.h b/scene/resources/segment_shape_2d.h index 4ed30c0443..700982ac0a 100644 --- a/scene/resources/segment_shape_2d.h +++ b/scene/resources/segment_shape_2d.h @@ -63,6 +63,7 @@ class RayShape2D : public Shape2D { GDCLASS(RayShape2D, Shape2D); real_t length; + bool slips_on_slope; void _update_shape(); @@ -72,6 +73,10 @@ protected: public: void set_length(real_t p_length); real_t get_length() const; + + void set_slips_on_slope(bool p_active); + bool get_slips_on_slope() const; + virtual void draw(const RID &p_to_rid, const Color &p_color); virtual Rect2 get_rect() const; diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index ed655b8a93..7eb0406bd8 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -45,7 +45,7 @@ protected: Shape2D(const RID &p_rid); public: - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return true; } + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return get_rect().has_point(p_point); } void set_custom_solver_bias(real_t p_bias); real_t get_custom_solver_bias() const; diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index de75bb3976..626fda50df 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -101,7 +101,7 @@ StyleBox::StyleBox() { } } -void StyleBoxTexture::set_texture(RES p_texture) { +void StyleBoxTexture::set_texture(Ref<Texture> p_texture) { if (texture == p_texture) return; @@ -112,12 +112,12 @@ void StyleBoxTexture::set_texture(RES p_texture) { _change_notify("texture"); } -RES StyleBoxTexture::get_texture() const { +Ref<Texture> StyleBoxTexture::get_texture() const { return texture; } -void StyleBoxTexture::set_normal_map(RES p_normal_map) { +void StyleBoxTexture::set_normal_map(Ref<Texture> p_normal_map) { if (normal_map == p_normal_map) return; @@ -125,7 +125,7 @@ void StyleBoxTexture::set_normal_map(RES p_normal_map) { emit_changed(); } -RES StyleBoxTexture::get_normal_map() const { +Ref<Texture> StyleBoxTexture::get_normal_map() const { return normal_map; } @@ -650,14 +650,14 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { style_rect = style_rect.grow(-((aa_size + 1) / 2)); } - //adapt borders (prevent weired overlapping/glitchy drawings) + //adapt borders (prevent weird overlapping/glitchy drawings) int width = MAX(style_rect.size.width, 0); int height = MAX(style_rect.size.height, 0); int adapted_border[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX }; adapt_values(MARGIN_TOP, MARGIN_BOTTOM, adapted_border, border_width, height, height, height); adapt_values(MARGIN_LEFT, MARGIN_RIGHT, adapted_border, border_width, width, width, width); - //adapt corners (prevent weired overlapping/glitchy drawings) + //adapt corners (prevent weird overlapping/glitchy drawings) int adapted_corner[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX }; adapt_values(CORNER_TOP_RIGHT, CORNER_BOTTOM_RIGHT, adapted_corner, corner_radius, height, height - adapted_border[MARGIN_BOTTOM], height - adapted_border[MARGIN_TOP]); adapt_values(CORNER_TOP_LEFT, CORNER_BOTTOM_LEFT, adapted_corner, corner_radius, height, height - adapted_border[MARGIN_BOTTOM], height - adapted_border[MARGIN_TOP]); diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index fb79aa360e..c1d84fe19f 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -112,11 +112,11 @@ public: void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; - void set_texture(RES p_texture); - RES get_texture() const; + void set_texture(Ref<Texture> p_texture); + Ref<Texture> get_texture() const; - void set_normal_map(RES p_normal_map); - RES get_normal_map() const; + void set_normal_map(Ref<Texture> p_normal_map); + Ref<Texture> get_normal_map() const; void set_draw_center(bool p_enabled); bool is_draw_center_enabled() const; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 3138d73caf..4463f98b07 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -57,8 +57,8 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { tile_set_modulate(id, p_value); else if (what == "region") tile_set_region(id, p_value); - else if (what == "is_autotile") - tile_set_is_autotile(id, p_value); + else if (what == "tile_mode") + tile_set_tile_mode(id, (TileMode)((int)p_value)); else if (what.left(9) == "autotile/") { what = what.right(9); if (what == "bitmask_mode") @@ -174,8 +174,8 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { r_ret = tile_get_modulate(id); else if (what == "region") r_ret = tile_get_region(id); - else if (what == "is_autotile") - r_ret = tile_get_is_autotile(id); + else if (what == "tile_mode") + r_ret = tile_get_tile_mode(id); else if (what.left(9) == "autotile/") { what = what.right(9); if (what == "bitmask_mode") @@ -258,13 +258,13 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial")); p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate")); p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region")); - p_list->push_back(PropertyInfo(Variant::BOOL, pre + "is_autotile", PROPERTY_HINT_NONE, "")); - if (tile_get_is_autotile(id)) { + p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE")); + if (tile_get_tile_mode(id) == AUTO_TILE) { p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/icon_coordinate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/tile_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/spacing", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/occluder_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/navpoly_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/priority_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); @@ -282,7 +282,6 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } void TileSet::create_tile(int p_id) { - ERR_FAIL_COND(tile_map.has(p_id)); tile_map[p_id] = TileData(); tile_map[p_id].autotile_data = AutotileData(); @@ -291,7 +290,6 @@ void TileSet::create_tile(int p_id) { } void TileSet::autotile_set_bitmask_mode(int p_id, BitmaskMode p_mode) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].autotile_data.bitmask_mode = p_mode; _change_notify(""); @@ -375,6 +373,7 @@ void TileSet::tile_set_region(int p_id, const Rect2 &p_region) { ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].region = p_region; emit_changed(); + _change_notify("region"); } Rect2 TileSet::tile_get_region(int p_id) const { @@ -383,18 +382,17 @@ Rect2 TileSet::tile_get_region(int p_id) const { return tile_map[p_id].region; } -void TileSet::tile_set_is_autotile(int p_id, bool p_is_autotile) { - +void TileSet::tile_set_tile_mode(int p_id, TileMode p_tile_mode) { ERR_FAIL_COND(!tile_map.has(p_id)); - tile_map[p_id].is_autotile = p_is_autotile; + tile_map[p_id].tile_mode = p_tile_mode; emit_changed(); - _change_notify("is_autotile"); + _change_notify("tile_mode"); } -bool TileSet::tile_get_is_autotile(int p_id) const { +TileSet::TileMode TileSet::tile_get_tile_mode(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), false); - return tile_map[p_id].is_autotile; + ERR_FAIL_COND_V(!tile_map.has(p_id), SINGLE_TILE); + return tile_map[p_id].tile_mode; } void TileSet::autotile_set_icon_coordinate(int p_id, Vector2 coord) { @@ -534,6 +532,7 @@ void TileSet::tile_set_name(int p_id, const String &p_name) { ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].name = p_name; emit_changed(); + _change_notify("name"); } String TileSet::tile_get_name(int p_id) const { diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 1306e2878c..46f34b6252 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -71,6 +71,12 @@ public: BIND_BOTTOMRIGHT = 256 }; + enum TileMode { + SINGLE_TILE, + AUTO_TILE, + ANIMATED_TILE + }; + struct AutotileData { BitmaskMode bitmask_mode; int spacing; @@ -84,6 +90,7 @@ public: // Default size to prevent invalid value explicit AutotileData() : size(64, 64), + spacing(0), icon_coord(0, 0) { bitmask_mode = BITMASK_2X2; } @@ -104,13 +111,13 @@ private: Ref<NavigationPolygon> navigation_polygon; Ref<ShaderMaterial> material; Color modulate; - bool is_autotile; + TileMode tile_mode; AutotileData autotile_data; // Default modulate for back-compat explicit TileData() : - modulate(1, 1, 1), - is_autotile(false) {} + tile_mode(SINGLE_TILE), + modulate(1, 1, 1) {} }; Map<int, TileData> tile_map; @@ -146,8 +153,8 @@ public: void tile_set_region(int p_id, const Rect2 &p_region); Rect2 tile_get_region(int p_id) const; - void tile_set_is_autotile(int p_id, bool p_is_autotile); - bool tile_get_is_autotile(int p_id) const; + void tile_set_tile_mode(int p_id, TileMode p_tile_mode); + TileMode tile_get_tile_mode(int p_id) const; void autotile_set_icon_coordinate(int p_id, Vector2 coord); Vector2 autotile_get_icon_coordinate(int p_id) const; diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp index 8620b182df..f9d402fe7b 100644 --- a/servers/arvr_server.cpp +++ b/servers/arvr_server.cpp @@ -44,6 +44,7 @@ void ARVRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_world_scale"), &ARVRServer::set_world_scale); ClassDB::bind_method(D_METHOD("get_reference_frame"), &ARVRServer::get_reference_frame); ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &ARVRServer::center_on_hmd); + ClassDB::bind_method(D_METHOD("get_hmd_transform"), &ARVRServer::get_hmd_transform); ADD_PROPERTY(PropertyInfo(Variant::REAL, "world_scale"), "set_world_scale", "get_world_scale"); @@ -54,8 +55,13 @@ void ARVRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tracker_count"), &ARVRServer::get_tracker_count); ClassDB::bind_method(D_METHOD("get_tracker", "idx"), &ARVRServer::get_tracker); + ClassDB::bind_method(D_METHOD("get_primary_interface"), &ARVRServer::get_primary_interface); ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &ARVRServer::set_primary_interface); + ClassDB::bind_method(D_METHOD("get_last_process_usec"), &ARVRServer::get_last_process_usec); + ClassDB::bind_method(D_METHOD("get_last_commit_usec"), &ARVRServer::get_last_commit_usec); + ClassDB::bind_method(D_METHOD("get_last_frame_usec"), &ARVRServer::get_last_frame_usec); + BIND_ENUM_CONSTANT(TRACKER_CONTROLLER); BIND_ENUM_CONSTANT(TRACKER_BASESTATION); BIND_ENUM_CONSTANT(TRACKER_ANCHOR); @@ -132,6 +138,14 @@ void ARVRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) }; }; +Transform ARVRServer::get_hmd_transform() { + Transform hmd_transform; + if (primary_interface != NULL) { + hmd_transform = primary_interface->get_transform_for_eye(ARVRInterface::EYE_MONO, hmd_transform); + }; + return hmd_transform; +}; + void ARVRServer::add_interface(const Ref<ARVRInterface> &p_interface) { ERR_FAIL_COND(p_interface.is_null()); @@ -314,6 +328,42 @@ void ARVRServer::clear_primary_interface_if(const Ref<ARVRInterface> &p_primary_ }; }; +uint64_t ARVRServer::get_last_process_usec() { + return last_process_usec; +}; + +uint64_t ARVRServer::get_last_commit_usec() { + return last_commit_usec; +}; + +uint64_t ARVRServer::get_last_frame_usec() { + return last_frame_usec; +}; + +void ARVRServer::_process() { + /* called from visual_server_viewport.draw_viewports right before we start drawing our viewports */ + + /* mark for our frame timing */ + last_process_usec = OS::get_singleton()->get_ticks_usec(); + + /* process all active interfaces */ + for (int i = 0; i < interfaces.size(); i++) { + if (!interfaces[i].is_valid()) { + // ignore, not a valid reference + } else if (interfaces[i]->is_initialized()) { + interfaces[i]->process(); + }; + }; +}; + +void ARVRServer::_mark_commit() { + /* time this */ + last_commit_usec = OS::get_singleton()->get_ticks_usec(); + + /* now store our difference as we may overwrite last_process_usec before this is accessed */ + last_frame_usec = last_commit_usec - last_process_usec; +}; + ARVRServer::ARVRServer() { singleton = this; world_scale = 1.0; diff --git a/servers/arvr_server.h b/servers/arvr_server.h index 34f143c0e0..1f4d84fe19 100644 --- a/servers/arvr_server.h +++ b/servers/arvr_server.h @@ -31,6 +31,7 @@ #ifndef ARVR_SERVER_H #define ARVR_SERVER_H +#include "os/os.h" #include "os/thread_safe.h" #include "reference.h" #include "rid.h" @@ -49,7 +50,7 @@ class ARVRPositionalTracker; Also each positioning tracker is accessible from here. I've added some additional info into this header file that should move - into the documention, I will do so when we're close to accepting this PR + into the documentation, I will do so when we're close to accepting this PR or as a separate PR once this has been merged into the master branch. **/ @@ -84,6 +85,10 @@ private: Transform world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */ Transform reference_frame; /* our reference frame */ + uint64_t last_process_usec; /* for frame timing, usec when we did our processing */ + uint64_t last_commit_usec; /* for frame timing, usec when we finished committing both eyes */ + uint64_t last_frame_usec; /* time it took between process and commiting, we should probably average this over the last x frames */ + protected: static ARVRServer *singleton; @@ -134,6 +139,11 @@ public: void center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height); /* + get_hmd_transform gets our hmd transform (centered between eyes) with most up to date tracking, relative to the origin + */ + Transform get_hmd_transform(); + + /* Interfaces are objects that 'glue' Godot to an AR or VR SDK such as the Oculus SDK, OpenVR, OpenHMD, etc. */ void add_interface(const Ref<ARVRInterface> &p_interface); @@ -163,6 +173,13 @@ public: ARVRPositionalTracker *get_tracker(int p_index) const; ARVRPositionalTracker *find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const; + uint64_t get_last_process_usec(); + uint64_t get_last_commit_usec(); + uint64_t get_last_frame_usec(); + + void _process(); + void _mark_commit(); + ARVRServer(); ~ARVRServer(); }; diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp index 0252b2f341..8c70b51f8d 100644 --- a/servers/audio/effects/audio_effect_compressor.cpp +++ b/servers/audio/effects/audio_effect_compressor.cpp @@ -236,7 +236,7 @@ void AudioEffectCompressor::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "attack_us", PROPERTY_HINT_RANGE, "20,2000,1"), "set_attack_us", "get_attack_us"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "release_ms", PROPERTY_HINT_RANGE, "20,2000,1"), "set_release_ms", "get_release_ms"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_mix", "get_mix"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sidechain", PROPERTY_HINT_ENUM), "set_sidechain", "get_sidechain"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "sidechain", PROPERTY_HINT_ENUM), "set_sidechain", "get_sidechain"); } AudioEffectCompressor::AudioEffectCompressor() { diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 5c453a3113..c3b0de6d9a 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -153,7 +153,7 @@ void AudioDriverManager::initialize(int p_driver) { ERR_PRINT("AudioDriverManager: all drivers failed, falling back to dummy driver"); dummy_driver.set_singleton(); } else { - ERR_PRINT("AudioDriverManager: dummy driver faild to init()"); + ERR_PRINT("AudioDriverManager: dummy driver failed to init()"); } } @@ -172,6 +172,12 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { int todo = p_frames; + if (channel_count != get_channel_count()) { + // Amount of channels changed due to a device change + // reinitialize the buses channels and buffers + init_channels_and_buffers(); + } + while (todo) { if (to_mix == 0) { @@ -485,8 +491,8 @@ void AudioServer::set_bus_count(int p_count) { } buses[i] = memnew(Bus); - buses[i]->channels.resize(get_channel_count()); - for (int j = 0; j < get_channel_count(); j++) { + buses[i]->channels.resize(channel_count); + for (int j = 0; j < channel_count; j++) { buses[i]->channels[j].buffer.resize(buffer_size); } buses[i]->name = attempt; @@ -518,6 +524,8 @@ void AudioServer::remove_bus(int p_index) { memdelete(buses[p_index]); buses.remove(p_index); unlock(); + + emit_signal("bus_layout_changed"); } void AudioServer::add_bus(int p_at_pos) { @@ -555,8 +563,8 @@ void AudioServer::add_bus(int p_at_pos) { } Bus *bus = memnew(Bus); - bus->channels.resize(get_channel_count()); - for (int j = 0; j < get_channel_count(); j++) { + bus->channels.resize(channel_count); + for (int j = 0; j < channel_count; j++) { bus->channels[j].buffer.resize(buffer_size); } bus->name = attempt; @@ -571,6 +579,8 @@ void AudioServer::add_bus(int p_at_pos) { buses.push_back(bus); else buses.insert(p_at_pos, bus); + + emit_signal("bus_layout_changed"); } void AudioServer::move_bus(int p_bus, int p_to_pos) { @@ -593,6 +603,8 @@ void AudioServer::move_bus(int p_bus, int p_to_pos) { } else { buses.insert(p_to_pos - 1, bus); } + + emit_signal("bus_layout_changed"); } int AudioServer::get_bus_count() const { @@ -854,17 +866,29 @@ bool AudioServer::is_bus_channel_active(int p_bus, int p_channel) const { return buses[p_bus]->channels[p_channel].active; } +void AudioServer::init_channels_and_buffers() { + channel_count = get_channel_count(); + temp_buffer.resize(channel_count); + + for (int i = 0; i < temp_buffer.size(); i++) { + temp_buffer[i].resize(buffer_size); + } + + for (int i = 0; i < buses.size(); i++) { + buses[i]->channels.resize(channel_count); + for (int j = 0; j < channel_count; j++) { + buses[i]->channels[j].buffer.resize(buffer_size); + } + } +} + void AudioServer::init() { channel_disable_threshold_db = GLOBAL_DEF("audio/channel_disable_threshold_db", -60.0); channel_disable_frames = float(GLOBAL_DEF("audio/channel_disable_time", 2.0)) * get_mix_rate(); - buffer_size = 1024; //harcoded for now - - temp_buffer.resize(get_channel_count()); + buffer_size = 1024; //hardcoded for now - for (int i = 0; i < temp_buffer.size(); i++) { - temp_buffer[i].resize(buffer_size); - } + init_channels_and_buffers(); mix_count = 0; set_bus_count(1); @@ -1046,8 +1070,8 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) { bus_map[bus->name] = bus; buses[i] = bus; - buses[i]->channels.resize(get_channel_count()); - for (int j = 0; j < get_channel_count(); j++) { + buses[i]->channels.resize(channel_count); + for (int j = 0; j < channel_count; j++) { buses[i]->channels[j].buffer.resize(buffer_size); } _update_bus_effects(i); @@ -1148,6 +1172,7 @@ AudioServer::AudioServer() { audio_data_max_mem = 0; audio_data_lock = Mutex::create(); mix_frames = 0; + channel_count = 0; to_mix = 0; } diff --git a/servers/audio_server.h b/servers/audio_server.h index 188d38db94..a8be48b4c3 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -130,6 +130,7 @@ private: float channel_disable_threshold_db; uint32_t channel_disable_frames; + int channel_count; int to_mix; struct Bus { @@ -186,6 +187,8 @@ private: Mutex *audio_data_lock; + void init_channels_and_buffers(); + void _mix_step(); struct CallbackItem { diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index e8ea5531e5..fd2ab16b84 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -245,12 +245,21 @@ public: biased_angular_velocity += _inv_inertia_tensor.xform(p_j); } + _FORCE_INLINE_ void add_central_force(const Vector3 &p_force) { + + applied_force += p_force; + } + _FORCE_INLINE_ void add_force(const Vector3 &p_force, const Vector3 &p_pos) { applied_force += p_force; applied_torque += p_pos.cross(p_force); } + _FORCE_INLINE_ void add_torque(const Vector3 &p_torque) { + applied_torque += p_torque; + } + void set_active(bool p_active); _FORCE_INLINE_ bool is_active() const { return active; } @@ -401,7 +410,9 @@ public: virtual void set_transform(const Transform &p_transform) { body->set_state(PhysicsServer::BODY_STATE_TRANSFORM, p_transform); } virtual Transform get_transform() const { return body->get_transform(); } + virtual void add_central_force(const Vector3 &p_force) { body->add_central_force(p_force); } virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->add_force(p_force, p_pos); } + virtual void add_torque(const Vector3 &p_torque) { body->add_torque(p_torque); } virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { body->apply_impulse(p_pos, p_j); } virtual void apply_torque_impulse(const Vector3 &p_j) { body->apply_torque_impulse(p_j); } diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index e26a7a4d89..0037b9a862 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -90,6 +90,10 @@ bool CollisionSolverSW::solve_ray(const ShapeSW *p_shape_A, const Transform &p_t return false; Vector3 support_B = p_transform_B.xform(p); + if (ray->get_slips_on_slope()) { + Vector3 global_n = ai.basis.xform_inv(n).normalized(); + support_B = support_A + (support_B - support_A).length() * global_n; + } if (p_result_callback) { if (p_swap_result) diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 0f7c6deaac..f2dbb635f8 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -902,7 +902,7 @@ bool PhysicsServerSW::body_is_ray_pickable(RID p_body) const { return body->is_ray_pickable(); } -bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result) { +bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body, false); @@ -911,7 +911,7 @@ bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, cons _update_shapes(); - return body->get_space()->test_body_motion(body, p_from, p_motion, body->get_kinematic_margin(), r_result); + return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, body->get_kinematic_margin(), r_result); } PhysicsDirectBodyState *PhysicsServerSW::body_get_direct_state(RID p_body) { diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 923b59d28f..3f56ba26d0 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -225,7 +225,7 @@ public: virtual void body_set_ray_pickable(RID p_body, bool p_enable); virtual bool body_is_ray_pickable(RID p_body) const; - virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL); + virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL); // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp index b918a42ca5..9d2e5e846d 100644 --- a/servers/physics/shape_sw.cpp +++ b/servers/physics/shape_sw.cpp @@ -165,6 +165,10 @@ real_t RayShapeSW::get_length() const { return length; } +bool RayShapeSW::get_slips_on_slope() const { + return slips_on_slope; +} + void RayShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { // don't think this will be even used @@ -221,25 +225,31 @@ Vector3 RayShapeSW::get_moment_of_inertia(real_t p_mass) const { return Vector3(); } -void RayShapeSW::_setup(real_t p_length) { +void RayShapeSW::_setup(real_t p_length, bool p_slips_on_slope) { length = p_length; + slips_on_slope = p_slips_on_slope; configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length))); } void RayShapeSW::set_data(const Variant &p_data) { - _setup(p_data); + Dictionary d = p_data; + _setup(d["length"], d["slips_on_slope"]); } Variant RayShapeSW::get_data() const { - return length; + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + return d; } RayShapeSW::RayShapeSW() { length = 1; + slips_on_slope = false; } /********** SPHERE *************/ diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h index 4a9a6289ff..7be818b23c 100644 --- a/servers/physics/shape_sw.h +++ b/servers/physics/shape_sw.h @@ -149,11 +149,13 @@ public: class RayShapeSW : public ShapeSW { real_t length; + bool slips_on_slope; - void _setup(real_t p_length); + void _setup(real_t p_length, bool p_slips_on_slope); public: real_t get_length() const; + bool get_slips_on_slope() const; virtual real_t get_area() const { return 0.0; } virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_RAY; } @@ -238,7 +240,7 @@ public: _FORCE_INLINE_ real_t get_height() const { return height; } _FORCE_INLINE_ real_t get_radius() const { return radius; } - virtual real_t get_area() { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; } + virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; } virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CAPSULE; } diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index fe6c42a531..b604e5cdf6 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -541,7 +541,7 @@ int SpaceSW::_cull_aabb_for_body(BodySW *p_body, const AABB &p_aabb) { return amount; } -bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer::MotionResult *r_result) { +bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer::MotionResult *r_result) { //give me back regular physics engine logic //this is madness diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h index 0d519ea50b..2452d6a187 100644 --- a/servers/physics/space_sw.h +++ b/servers/physics/space_sw.h @@ -197,7 +197,7 @@ public: void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; } uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; } - bool test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer::MotionResult *r_result); + bool test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer::MotionResult *r_result); SpaceSW(); ~SpaceSW(); diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index 80cdd58aeb..ce06aa9a2b 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -100,6 +100,7 @@ void CollisionObject2DSW::remove_shape(int p_index) { shapes[p_index].shape->remove_owner(this); shapes.remove(p_index); + _update_shapes(); _shapes_changed(); } diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp index a6ef110149..efee98a35a 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/collision_solver_2d_sw.cpp @@ -95,6 +95,10 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Transf } Vector2 support_B = p_transform_B.xform(p); + if (ray->get_slips_on_slope()) { + Vector2 global_n = invb.basis_xform_inv(n).normalized(); + support_B = support_A + (support_B - support_A).length() * global_n; + } if (p_result_callback) { if (p_swap_result) diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp index 7fba8acebd..d49c1b8376 100644 --- a/servers/physics_2d/joints_2d_sw.cpp +++ b/servers/physics_2d/joints_2d_sw.cpp @@ -146,14 +146,19 @@ bool PinJoint2DSW::setup(real_t p_step) { return true; } +inline Vector2 custom_cross(const Vector2 &p_vec, real_t p_other) { + + return Vector2(p_other * p_vec.y, -p_other * p_vec.x); +} + void PinJoint2DSW::solve(real_t p_step) { // compute relative velocity - Vector2 vA = A->get_linear_velocity() - rA.cross(A->get_angular_velocity()); + Vector2 vA = A->get_linear_velocity() - custom_cross(rA, A->get_angular_velocity()); Vector2 rel_vel; if (B) - rel_vel = B->get_linear_velocity() - rB.cross(B->get_angular_velocity()) - vA; + rel_vel = B->get_linear_velocity() - custom_cross(rB, B->get_angular_velocity()) - vA; else rel_vel = -vA; diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 0603287a79..a14fed8184 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -962,14 +962,14 @@ void Physics2DServerSW::body_set_pickable(RID p_body, bool p_pickable) { body->set_pickable(p_pickable); } -bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result) { +bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); ERR_FAIL_COND_V(body->get_space()->is_locked(), false); - return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result); + return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result); } Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) { diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index cf9c2957bf..036eb934e1 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -232,7 +232,7 @@ public: virtual void body_set_pickable(RID p_body, bool p_pickable); - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = NULL); + virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL); // this function only works on physics process, errors and returns null otherwise virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index d625bc9892..a15e8bde8b 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -245,10 +245,10 @@ public: FUNC2(body_set_pickable, RID, bool); - bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = NULL) { + bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL) { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result); + return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result); } // this function only works on physics process, errors and returns null otherwise diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 5893f19827..433942708e 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -184,13 +184,18 @@ real_t RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) void RayShape2DSW::set_data(const Variant &p_data) { - length = p_data; + Dictionary d = p_data; + length = d["length"]; + slips_on_slope = d["slips_on_slope"]; configure(Rect2(0, 0, 0.001, length)); } Variant RayShape2DSW::get_data() const { - return length; + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + return d; } /*********************************************************/ diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index c4c267b368..d937301f3c 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -197,9 +197,11 @@ public: class RayShape2DSW : public Shape2DSW { real_t length; + bool slips_on_slope; public: _FORCE_INLINE_ real_t get_length() const { return length; } + _FORCE_INLINE_ bool get_slips_on_slope() const { return slips_on_slope; } virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RAY; } diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index d3b81c627a..c29093d1af 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -483,7 +483,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) { return amount; } -bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result) { +bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result) { //give me back regular physics engine logic //this is madness @@ -550,6 +550,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co const CollisionObject2DSW *col_obj = intersection_query_results[i]; int shape_idx = intersection_query_subindex_results[i]; + if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) { + const Body2DSW *b = static_cast<const Body2DSW *>(col_obj); + if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) { + continue; + } + } + if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) { cbk.valid_dir = body_shape_xform.get_axis(1).normalized(); @@ -638,6 +645,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co int col_shape_idx = intersection_query_subindex_results[i]; Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx); + if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) { + const Body2DSW *b = static_cast<const Body2DSW *>(col_obj); + if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) { + continue; + } + } + bool excluded = false; for (int k = 0; k < excluded_shape_pair_count; k++) { @@ -768,6 +782,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co const CollisionObject2DSW *col_obj = intersection_query_results[i]; int shape_idx = intersection_query_subindex_results[i]; + if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) { + const Body2DSW *b = static_cast<const Body2DSW *>(col_obj); + if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) { + continue; + } + } + Shape2DSW *against_shape = col_obj->get_shape(shape_idx); bool excluded = false; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index a18bb2be2d..79349c46f3 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -182,7 +182,7 @@ public: int get_collision_pairs() const { return collision_pairs; } - bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result); + bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result); void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); } diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 5f08cd9243..fafc239c7f 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "physics_2d_server.h" +#include "core/method_bind_ext.gen.inc" #include "core/project_settings.h" #include "print_string.h" @@ -476,12 +477,12 @@ Physics2DTestMotionResult::Physics2DTestMotionResult() { /////////////////////////////////////// -bool Physics2DServer::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) { +bool Physics2DServer::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) { MotionResult *r = NULL; if (p_result.is_valid()) r = p_result->get_result_ptr(); - return body_test_motion(p_body, p_from, p_motion, p_margin, r); + return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r); } void Physics2DServer::_bind_methods() { @@ -598,7 +599,7 @@ void Physics2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &Physics2DServer::body_set_force_integration_callback, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result"), &Physics2DServer::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &Physics2DServer::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &Physics2DServer::body_get_direct_state); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 462244c667..ba5232f7fe 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -217,7 +217,7 @@ class Physics2DServer : public Object { static Physics2DServer *singleton; - virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>()); + virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>()); protected: static void _bind_methods(); @@ -479,7 +479,7 @@ public: Variant collider_metadata; }; - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, float p_margin = 0.001, MotionResult *r_result = NULL) = 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) = 0; /* JOINT API */ diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index 9d4807fcf0..f01a4c2f64 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -92,9 +92,11 @@ void PhysicsDirectBodyState::_bind_methods() { ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState::set_transform); ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState::get_transform); + ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState::add_central_force); ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState::add_force); + ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState::add_torque); ClassDB::bind_method(D_METHOD("apply_impulse", "position", "j"), &PhysicsDirectBodyState::apply_impulse); - ClassDB::bind_method(D_METHOD("apply_torqe_impulse", "j"), &PhysicsDirectBodyState::apply_torque_impulse); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "j"), &PhysicsDirectBodyState::apply_torque_impulse); ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState::set_sleep_state); ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState::is_sleeping); diff --git a/servers/physics_server.h b/servers/physics_server.h index 2ac405293e..6a342b36d4 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -63,7 +63,9 @@ public: virtual void set_transform(const Transform &p_transform) = 0; virtual Transform get_transform() const = 0; + virtual void add_central_force(const Vector3 &p_force) = 0; virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) = 0; + virtual void add_torque(const Vector3 &p_torque) = 0; virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) = 0; virtual void apply_torque_impulse(const Vector3 &p_j) = 0; @@ -472,7 +474,7 @@ public: Variant collider_metadata; }; - virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL) = 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) = 0; /* JOINT API */ diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index aaac32a4f2..1bad7e652b 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -80,6 +80,7 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag ShaderTypes *shader_types = NULL; PhysicsServer *_createGodotPhysicsCallback() { + WARN_PRINT("The GodotPhysics 3D physics engine is deprecated and will be removed in Godot 3.2. You should use the Bullet physics engine instead (configurable in your project settings)."); return memnew(PhysicsServerSW); } @@ -163,8 +164,8 @@ void register_server_types() { GLOBAL_DEF(PhysicsServerManager::setting_property_name, "DEFAULT"); ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServerManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServerManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); - PhysicsServerManager::register_server("GodotPhysics", &_createGodotPhysicsCallback); - PhysicsServerManager::set_default_server("GodotPhysics"); + PhysicsServerManager::register_server("GodotPhysics - deprecated", &_createGodotPhysicsCallback); + PhysicsServerManager::set_default_server("GodotPhysics - deprecated"); } void unregister_server_types() { diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index f2bb853a3b..8bf112b0de 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -749,14 +749,16 @@ public: struct CommandMesh : public Command { RID mesh; - RID skeleton; + RID texture; + RID normal_map; CommandMesh() { type = TYPE_MESH; } }; struct CommandMultiMesh : public Command { RID multimesh; - RID skeleton; + RID texture; + RID normal_map; CommandMultiMesh() { type = TYPE_MULTIMESH; } }; @@ -920,7 +922,7 @@ public: case Item::Command::TYPE_MESH: { const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c); - AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, mesh->skeleton); + AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID()); r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); @@ -1012,7 +1014,7 @@ public: virtual void canvas_begin() = 0; virtual void canvas_end() = 0; - virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light) = 0; + virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) = 0; virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0; struct LightOccluderInstance : public RID_Data { diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 29c27eee85..d5a9bfb606 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -124,6 +124,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "TYPE_ISAMPLER2D", "TYPE_USAMPLER2D", "TYPE_SAMPLERCUBE", + "INTERPOLATION_FLAT", + "INTERPOLATION_NO_PERSPECTIVE", + "INTERPOLATION_SMOOTH", "PRECISION_LOW", "PRECISION_MID", "PRECISION_HIGH", @@ -1374,6 +1377,17 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } }, //builtins - trigonometry + + { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + + { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, @@ -1423,6 +1437,21 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + + { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + + { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + //builtins - exponential { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } }, { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, @@ -1436,6 +1465,14 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, @@ -1482,6 +1519,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, @@ -1570,7 +1611,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BOOL, TYPE_VOID } }, - { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC3, TYPE_VOID } }, + { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID } }, { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID } }, { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } }, @@ -1603,10 +1644,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID } }, { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID } }, - { "floatBitsToUInt", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID } }, - { "floatBitsToUInt", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID } }, - { "floatBitsToUInt", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID } }, - { "floatBitsToUInt", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID } }, + { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID } }, + { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID } }, + { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID } }, + { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID } }, { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID } }, { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID } }, @@ -3661,26 +3702,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct //todo parse default value tk = _get_token(); - if (tk.type == TK_OP_ASSIGN) { - - Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); - if (!expr) - return ERR_PARSE_ERROR; - if (expr->type != Node::TYPE_CONSTANT) { - _set_error("Expected constant expression after '='"); - return ERR_PARSE_ERROR; - } - - ConstantNode *cn = static_cast<ConstantNode *>(expr); - - uniform.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)); - return ERR_PARSE_ERROR; - } - tk = _get_token(); - } if (tk.type == TK_COLON) { //hint @@ -3796,6 +3817,27 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } + if (tk.type == TK_OP_ASSIGN) { + + Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); + if (!expr) + return ERR_PARSE_ERROR; + if (expr->type != Node::TYPE_CONSTANT) { + _set_error("Expected constant expression after '='"); + return ERR_PARSE_ERROR; + } + + ConstantNode *cn = static_cast<ConstantNode *>(expr); + + uniform.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)); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } + shader->uniforms[name] = uniform; if (tk.type != TK_SEMICOLON) { diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index d82d93a59d..dd8d07f00d 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -46,7 +46,7 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra for (int i = 0; i < z_range; i++) { if (!z_list[i]) continue; - VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_modulate, p_lights); + VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_modulate, p_lights, p_transform); } } @@ -214,7 +214,7 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr _light_mask_canvas_items(VS::CANVAS_ITEM_Z_MIN + i, z_list[i], p_masked_lights); } - VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_canvas->modulate, p_lights); + VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_canvas->modulate, p_lights, p_transform); } } else { @@ -440,13 +440,17 @@ void VisualServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point if (p_antialiased) { pline->line_colors.push_back(Color(1, 1, 1, 1)); } - } - if (p_colors.size() == 1) { + } else if (p_colors.size() == 1) { pline->triangle_colors = p_colors; pline->line_colors = p_colors; } else { - pline->triangle_colors.resize(pline->triangles.size()); - pline->line_colors.resize(pline->lines.size()); + if (p_colors.size() != p_points.size()) { + pline->triangle_colors.push_back(p_colors[0]); + pline->line_colors.push_back(p_colors[0]); + } else { + pline->triangle_colors.resize(pline->triangles.size()); + pline->line_colors.resize(pline->lines.size()); + } } for (int i = 0; i < p_points.size(); i++) { @@ -742,7 +746,7 @@ void VisualServerCanvas::canvas_item_add_set_transform(RID p_item, const Transfo canvas_item->commands.push_back(tr); } -void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_skeleton) { +void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture, RID p_normal_map) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -750,7 +754,8 @@ void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID Item::CommandMesh *m = memnew(Item::CommandMesh); ERR_FAIL_COND(!m); m->mesh = p_mesh; - m->skeleton = p_skeleton; + m->texture = p_texture; + m->normal_map = p_normal_map; canvas_item->commands.push_back(m); } @@ -774,7 +779,7 @@ void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, canvas_item->commands.push_back(part); } -void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_skeleton) { +void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture, RID p_normal_map) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -782,7 +787,8 @@ void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p Item::CommandMultiMesh *mm = memnew(Item::CommandMultiMesh); ERR_FAIL_COND(!mm); mm->multimesh = p_mesh; - mm->skeleton = p_skeleton; + mm->texture = p_texture; + mm->normal_map = p_normal_map; canvas_item->rect_dirty = true; canvas_item->commands.push_back(mm); @@ -822,6 +828,15 @@ void VisualServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, boo canvas_item->z_relative = p_enable; } + +void VisualServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->skeleton = p_skeleton; +} + void VisualServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) { Item *canvas_item = canvas_item_owner.getornull(p_item); diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index f4331ad291..6a5a7623b6 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -51,6 +51,8 @@ public: Vector<Item *> child_items; + RID skeleton; + Item() { children_order_dirty = true; E = NULL; @@ -182,8 +184,8 @@ public: void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false); void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()); - void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_skeleton = RID()); - void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_skeleton = RID()); + void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()); + void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()); void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal, int p_h_frames, int p_v_frames); void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); @@ -191,6 +193,7 @@ public: void canvas_item_set_z_index(RID p_item, int p_z); void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect); + void canvas_item_attach_skeleton(RID p_item, RID p_skeleton); void canvas_item_clear(RID p_item); void canvas_item_set_draw_index(RID p_item, int p_index); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 64a3502e40..fca3126604 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -205,4 +205,5 @@ VisualServerRaster::~VisualServerRaster() { memdelete(VSG::canvas); memdelete(VSG::viewport); memdelete(VSG::rasterizer); + memdelete(VSG::scene); } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 106b84a6ff..a94e110b5d 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -581,8 +581,8 @@ public: BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) BIND7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool) BIND8(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, int, RID) - BIND3(canvas_item_add_mesh, RID, const RID &, RID) - BIND3(canvas_item_add_multimesh, RID, RID, RID) + BIND4(canvas_item_add_mesh, RID, const RID &, RID, RID) + BIND4(canvas_item_add_multimesh, RID, RID, RID, RID) BIND6(canvas_item_add_particles, RID, RID, RID, RID, int, int) BIND2(canvas_item_add_set_transform, RID, const Transform2D &) BIND2(canvas_item_add_clip_ignore, RID, bool) @@ -590,6 +590,7 @@ public: BIND2(canvas_item_set_z_index, RID, int) BIND2(canvas_item_set_z_as_relative_to_parent, RID, bool) BIND3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &) + BIND2(canvas_item_attach_skeleton, RID, RID) BIND1(canvas_item_clear, RID) BIND2(canvas_item_set_draw_index, RID, int) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 0920fa748b..04dcde1365 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -730,6 +730,11 @@ void VisualServerScene::instance_set_exterior(RID p_instance, bool p_enabled) { } void VisualServerScene::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) { + Instance *instance = instance_owner.get(p_instance); + ERR_FAIL_COND(!instance); + + instance->extra_margin = p_margin; + _instance_queue_update(instance, true, false); } Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const { @@ -3333,6 +3338,7 @@ VisualServerScene::~VisualServerScene() { #ifndef NO_THREADS probe_bake_thread_exit = true; + probe_bake_sem->post(); Thread::wait_to_finish(probe_bake_thread); memdelete(probe_bake_thread); memdelete(probe_bake_sem); diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 3eb8953c1f..83e05f6f25 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -239,10 +239,9 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E void VisualServerViewport::draw_viewports() { // get our arvr interface in case we need it Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); - if (arvr_interface.is_valid()) { - // update our positioning information as late as possible... - arvr_interface->process(); - } + + // process all our active interfaces + ARVRServer::get_singleton()->_process(); clear_color = GLOBAL_GET("rendering/environment/default_clear_color"); @@ -286,6 +285,9 @@ void VisualServerViewport::draw_viewports() { _draw_viewport(vp, ARVRInterface::EYE_RIGHT); arvr_interface->commit_for_eye(ARVRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect); } + + // and for our frame timing, mark when we've finished commiting our eyes + ARVRServer::get_singleton()->_mark_commit(); } else { VSG::rasterizer->set_current_render_target(vp->render_target); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index c86a8164ce..b91f80d137 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -499,8 +499,8 @@ public: FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool) FUNC8(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, int, RID) - FUNC3(canvas_item_add_mesh, RID, const RID &, RID) - FUNC3(canvas_item_add_multimesh, RID, RID, RID) + FUNC4(canvas_item_add_mesh, RID, const RID &, RID, RID) + FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID) FUNC6(canvas_item_add_particles, RID, RID, RID, RID, int, int) FUNC2(canvas_item_add_set_transform, RID, const Transform2D &) FUNC2(canvas_item_add_clip_ignore, RID, bool) @@ -508,6 +508,7 @@ public: FUNC2(canvas_item_set_z_index, RID, int) FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool) FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &) + FUNC2(canvas_item_attach_skeleton, RID, RID) FUNC1(canvas_item_clear, RID) FUNC2(canvas_item_set_draw_index, RID, int) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 0e33f3d109..f8640720cb 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1518,6 +1518,12 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("force_sync"), &VisualServer::sync); ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers"), &VisualServer::draw, DEFVAL(true)); + // "draw" and "sync" are deprecated duplicates of "force_draw" and "force_sync" + // FIXME: Add deprecation messages using GH-4397 once available, and retire + // once the warnings have been enabled for a full release cycle + ClassDB::bind_method(D_METHOD("sync"), &VisualServer::sync); + ClassDB::bind_method(D_METHOD("draw", "swap_buffers"), &VisualServer::draw, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("texture_create"), &VisualServer::texture_create); ClassDB::bind_method(D_METHOD("texture_create_from_image", "image", "flags"), &VisualServer::texture_create_from_image, DEFVAL(TEXTURE_FLAGS_DEFAULT)); ClassDB::bind_method(D_METHOD("texture_allocate", "texture", "width", "height", "format", "flags"), &VisualServer::texture_allocate, DEFVAL(TEXTURE_FLAGS_DEFAULT)); @@ -1822,8 +1828,8 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &VisualServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID())); ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &VisualServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "texture", "count", "normal_map"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "skeleton"), &VisualServer::canvas_item_add_mesh, DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "skeleton"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_mesh, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID())); ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map", "h_frames", "v_frames"), &VisualServer::canvas_item_add_particles); ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &VisualServer::canvas_item_add_set_transform); ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &VisualServer::canvas_item_add_clip_ignore); diff --git a/servers/visual_server.h b/servers/visual_server.h index a188fef17a..537588fd6f 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -846,8 +846,8 @@ public: virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false) = 0; virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()) = 0; - virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_skeleton = RID()) = 0; - virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_skeleton = RID()) = 0; + virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0; + virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0; virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, int p_h_frames, int p_v_frames) = 0; virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0; virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0; @@ -856,6 +856,8 @@ public: virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0; virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) = 0; + virtual void canvas_item_attach_skeleton(RID p_item, RID p_skeleton) = 0; + virtual void canvas_item_clear(RID p_item) = 0; virtual void canvas_item_set_draw_index(RID p_item, int p_index) = 0; diff --git a/thirdparty/README.md b/thirdparty/README.md index ff05f3d084..d3fa0e4664 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -11,6 +11,9 @@ The files were adapted to Godot by removing the dependency on b2Math (replacing it by b2Glue.h) and commenting out some verbose printf calls. Upstream code has not changed in 10 years, no need to keep track of changes. +Important: Some files have Godot-made changes. +They are marked with `// -- GODOT start --` and `// -- GODOT end --` +comments. ## bullet @@ -69,6 +72,9 @@ Files extracted from upstream source: - all .cpp and .h files in EtcLib/ - README.md, LICENSE, AUTHORS +Important: Some files have Godot-made changes. +They are marked with `// -- GODOT start --` and `// -- GODOT end --` +comments. ## fonts @@ -165,6 +171,9 @@ Files extracted from upstream source: TODO. +Important: Some files have Godot-made changes. +They are marked with `// -- GODOT start --` and `// -- GODOT end --` +comments. ## libtheora @@ -229,13 +238,13 @@ changes are marked with `// -- GODOT --` comments. - License: LGPLv2.1 + static linking exception File extracted from upstream source: -- Everything in `lib/` except `http2/`, `event-libs/`. +- Everything in `lib/` except `minilex.c`, `http2/`, `event-libs/`. - From `misc/` exclude `lws-genhash.c`, `lws-ring.c`, `romfs.{c,h}`, `smtp.c`. - From `plat/` exclude `lws-plat-{esp*,optee}.c`. - From `server/` exclude `access-log.c`, `cgi.c`, `daemonize.c`, `lws-spa.c`, `peer-limits.c`, `rewrite.c` - Also copy `win32helpers/` from `win32port/` -- `mbedtls_wrapper/include/platform/ssl_port.h` has a small change to check for OSX (missing `malloc.h`). +- `mbedtls_wrapper/include/platform/ssl_port.h` has a small change to check for OSX and FreeBSD (missing `malloc.h`). The bug is fixed in upstream master via `LWS_HAVE_MALLOC_H`, but not in the 2.4.1 branch (as the file structure has changed). Important: `lws_config.h` and `lws_config_private.h` contains custom diff --git a/thirdparty/b2d_convexdecomp/b2Polygon.cpp b/thirdparty/b2d_convexdecomp/b2Polygon.cpp index b6ead62c63..c80204ae21 100644 --- a/thirdparty/b2d_convexdecomp/b2Polygon.cpp +++ b/thirdparty/b2d_convexdecomp/b2Polygon.cpp @@ -1342,7 +1342,12 @@ b2Polygon TraceEdge(b2Polygon* p){ if (nodes[j].nConnected == 0) continue; b2Vec2 diff = nodes[i].position - nodes[j].position; if (diff.LengthSquared() <= COLLAPSE_DIST_SQR){ - if (nActive <= 3) return b2Polygon(); + if (nActive <= 3) { + // -- GODOT start -- + delete[] nodes; + // -- GODOT end -- + return b2Polygon(); + } //printf("Found dupe, %d left\n",nActive); --nActive; foundDupe = true; diff --git a/thirdparty/etc2comp/EtcFilter.cpp b/thirdparty/etc2comp/EtcFilter.cpp index bc899a533e..1ec8acdf3f 100644 --- a/thirdparty/etc2comp/EtcFilter.cpp +++ b/thirdparty/etc2comp/EtcFilter.cpp @@ -228,6 +228,9 @@ int FilterTwoPass( RGBCOLOR *pSrcImage, int srcWidth, int srcHeight, pTempImage = (RGBCOLOR *)malloc( destWidth * srcHeight * sizeof(RGBCOLOR) ); if ( pTempImage == NULL ) { + // -- GODOT start -- + free( contrib ); + // -- GODOT end -- return 0; } diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c index f87ec8cf93..c2aaea2144 100644 --- a/thirdparty/glad/glad.c +++ b/thirdparty/glad/glad.c @@ -1,21 +1,23 @@ /* - OpenGL loader generated by glad 0.1.16a0 on Thu Nov 30 06:21:28 2017. + OpenGL loader generated by glad 0.1.18a0 on Mon Mar 5 18:43:52 2018. Language/Generator: C/C++ Specification: gl APIs: gl=3.3 Profile: compatibility Extensions: - GL_ARB_debug_output + GL_ARB_debug_output, + GL_ARB_framebuffer_object, + GL_EXT_framebuffer_object Loader: True Local files: False Omit khrplatform: False Commandline: - --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output" + --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_object" Online: - http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output + http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object */ #include <stdio.h> @@ -47,8 +49,8 @@ int open_gl(void) { static void close_gl(void) { if(libGL != NULL) { - FreeLibrary(libGL); - libGL = NULL; + FreeLibrary((HMODULE) libGL); + libGL = NULL; } } #else @@ -112,7 +114,7 @@ void* get_proc(const char *namez) { #endif if(result == NULL) { #ifdef _WIN32 - result = (void*)GetProcAddress(libGL, namez); + result = (void*)GetProcAddress((HMODULE) libGL, namez); #else result = dlsym(libGL, namez); #endif @@ -168,7 +170,7 @@ static int get_exts(void) { const char *gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index); size_t len = strlen(gl_str_tmp); - char *local_str = (char*)malloc((len+1) * sizeof(*exts_i)); + char *local_str = (char*)malloc((len+1) * sizeof(char)); if(local_str != NULL) { #if _MSC_VER >= 1400 strncpy_s(local_str, len+1, gl_str_tmp, len); @@ -971,11 +973,30 @@ PFNGLCOLORPOINTERPROC glad_glColorPointer; PFNGLFRONTFACEPROC glad_glFrontFace; PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v; PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv; +int GLAD_GL_ARB_framebuffer_object; +int GLAD_GL_EXT_framebuffer_object; int GLAD_GL_ARB_debug_output; PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB; PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB; PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB; PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB; +PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT; +PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT; +PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT; +PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT; +PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT; +PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT; +PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT; +PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT; +PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT; +PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT; +PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT; +PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT; +PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT; +PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT; +PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT; static void load_GL_VERSION_1_0(GLADloadproc load) { if(!GLAD_GL_VERSION_1_0) return; glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace"); @@ -1746,9 +1767,54 @@ static void load_GL_ARB_debug_output(GLADloadproc load) { glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)load("glDebugMessageCallbackARB"); glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC)load("glGetDebugMessageLogARB"); } +static void load_GL_ARB_framebuffer_object(GLADloadproc load) { + if(!GLAD_GL_ARB_framebuffer_object) return; + glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer"); + glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer"); + glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers"); + glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers"); + glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage"); + glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv"); + glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer"); + glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer"); + glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers"); + glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers"); + glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus"); + glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)load("glFramebufferTexture1D"); + glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D"); + glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)load("glFramebufferTexture3D"); + glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer"); + glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv"); + glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap"); + glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)load("glBlitFramebuffer"); + glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample"); + glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer"); +} +static void load_GL_EXT_framebuffer_object(GLADloadproc load) { + if(!GLAD_GL_EXT_framebuffer_object) return; + glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)load("glIsRenderbufferEXT"); + glad_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)load("glBindRenderbufferEXT"); + glad_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)load("glDeleteRenderbuffersEXT"); + glad_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)load("glGenRenderbuffersEXT"); + glad_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)load("glRenderbufferStorageEXT"); + glad_glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)load("glGetRenderbufferParameterivEXT"); + glad_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)load("glIsFramebufferEXT"); + glad_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)load("glBindFramebufferEXT"); + glad_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)load("glDeleteFramebuffersEXT"); + glad_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)load("glGenFramebuffersEXT"); + glad_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)load("glCheckFramebufferStatusEXT"); + glad_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)load("glFramebufferTexture1DEXT"); + glad_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)load("glFramebufferTexture2DEXT"); + glad_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)load("glFramebufferTexture3DEXT"); + glad_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)load("glFramebufferRenderbufferEXT"); + glad_glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)load("glGetFramebufferAttachmentParameterivEXT"); + glad_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)load("glGenerateMipmapEXT"); +} static int find_extensionsGL(void) { if (!get_exts()) return 0; GLAD_GL_ARB_debug_output = has_ext("GL_ARB_debug_output"); + GLAD_GL_ARB_framebuffer_object = has_ext("GL_ARB_framebuffer_object"); + GLAD_GL_EXT_framebuffer_object = has_ext("GL_EXT_framebuffer_object"); free_exts(); return 1; } @@ -1828,6 +1894,8 @@ int gladLoadGLLoader(GLADloadproc load) { if (!find_extensionsGL()) return 0; load_GL_ARB_debug_output(load); + load_GL_ARB_framebuffer_object(load); + load_GL_EXT_framebuffer_object(load); return GLVersion.major != 0 || GLVersion.minor != 0; } diff --git a/thirdparty/glad/glad/glad.h b/thirdparty/glad/glad/glad.h index 69413ef65f..9de720fbc2 100644 --- a/thirdparty/glad/glad/glad.h +++ b/thirdparty/glad/glad/glad.h @@ -1,21 +1,23 @@ /* - OpenGL loader generated by glad 0.1.16a0 on Thu Nov 30 06:21:28 2017. + OpenGL loader generated by glad 0.1.18a0 on Mon Mar 5 18:43:52 2018. Language/Generator: C/C++ Specification: gl APIs: gl=3.3 Profile: compatibility Extensions: - GL_ARB_debug_output + GL_ARB_debug_output, + GL_ARB_framebuffer_object, + GL_EXT_framebuffer_object Loader: True Local files: False Omit khrplatform: False Commandline: - --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output" + --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_object" Online: - http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output + http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object */ @@ -3680,6 +3682,57 @@ GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv; #define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 #define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 #define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 #ifndef GL_ARB_debug_output #define GL_ARB_debug_output 1 GLAPI int GLAD_GL_ARB_debug_output; @@ -3696,6 +3749,65 @@ typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei GLAPI PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB; #define glGetDebugMessageLogARB glad_glGetDebugMessageLogARB #endif +#ifndef GL_ARB_framebuffer_object +#define GL_ARB_framebuffer_object 1 +GLAPI int GLAD_GL_ARB_framebuffer_object; +#endif +#ifndef GL_EXT_framebuffer_object +#define GL_EXT_framebuffer_object 1 +GLAPI int GLAD_GL_EXT_framebuffer_object; +typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC)(GLuint renderbuffer); +GLAPI PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT; +#define glIsRenderbufferEXT glad_glIsRenderbufferEXT +typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer); +GLAPI PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT; +#define glBindRenderbufferEXT glad_glBindRenderbufferEXT +typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint *renderbuffers); +GLAPI PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT; +#define glDeleteRenderbuffersEXT glad_glDeleteRenderbuffersEXT +typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint *renderbuffers); +GLAPI PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT; +#define glGenRenderbuffersEXT glad_glGenRenderbuffersEXT +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT; +#define glRenderbufferStorageEXT glad_glRenderbufferStorageEXT +typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT; +#define glGetRenderbufferParameterivEXT glad_glGetRenderbufferParameterivEXT +typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC)(GLuint framebuffer); +GLAPI PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT; +#define glIsFramebufferEXT glad_glIsFramebufferEXT +typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer); +GLAPI PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT; +#define glBindFramebufferEXT glad_glBindFramebufferEXT +typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint *framebuffers); +GLAPI PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT; +#define glDeleteFramebuffersEXT glad_glDeleteFramebuffersEXT +typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint *framebuffers); +GLAPI PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT; +#define glGenFramebuffersEXT glad_glGenFramebuffersEXT +typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target); +GLAPI PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT; +#define glCheckFramebufferStatusEXT glad_glCheckFramebufferStatusEXT +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT; +#define glFramebufferTexture1DEXT glad_glFramebufferTexture1DEXT +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT; +#define glFramebufferTexture2DEXT glad_glFramebufferTexture2DEXT +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +GLAPI PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT; +#define glFramebufferTexture3DEXT glad_glFramebufferTexture3DEXT +typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT; +#define glFramebufferRenderbufferEXT glad_glFramebufferRenderbufferEXT +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params); +GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT; +#define glGetFramebufferAttachmentParameterivEXT glad_glGetFramebufferAttachmentParameterivEXT +typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC)(GLenum target); +GLAPI PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT; +#define glGenerateMipmapEXT glad_glGenerateMipmapEXT +#endif #ifdef __cplusplus } diff --git a/thirdparty/libsimplewebm/libwebm/README.libvpx b/thirdparty/libsimplewebm/libwebm/README.libvpx index ae62f36525..1aa93b75aa 100644 --- a/thirdparty/libsimplewebm/libwebm/README.libvpx +++ b/thirdparty/libsimplewebm/libwebm/README.libvpx @@ -1,5 +1,5 @@ URL: https://chromium.googlesource.com/webm/libwebm -Version: 32d5ac49414a8914ec1e1f285f3f927c6e8ec29d +Version: d7c62173ff6b4a5e0a2f86683a5b67db98cf09bf License: BSD License File: LICENSE.txt diff --git a/thirdparty/libsimplewebm/libwebm/common/webmids.h b/thirdparty/libsimplewebm/libwebm/common/webmids.h index 32a0c5fb91..89d722a71b 100644 --- a/thirdparty/libsimplewebm/libwebm/common/webmids.h +++ b/thirdparty/libsimplewebm/libwebm/common/webmids.h @@ -124,6 +124,14 @@ enum MkvId { kMkvLuminanceMin = 0x55DA, // end mastering metadata // end colour + // projection + kMkvProjection = 0x7670, + kMkvProjectionType = 0x7671, + kMkvProjectionPrivate = 0x7672, + kMkvProjectionPoseYaw = 0x7673, + kMkvProjectionPosePitch = 0x7674, + kMkvProjectionPoseRoll = 0x7675, + // end projection // audio kMkvAudio = 0xE1, kMkvSamplingFrequency = 0xB5, diff --git a/thirdparty/libsimplewebm/libwebm/mkvparser/mkvparser.cc b/thirdparty/libsimplewebm/libwebm/mkvparser/mkvparser.cc index bda67a5758..e7b76f7da1 100644 --- a/thirdparty/libsimplewebm/libwebm/mkvparser/mkvparser.cc +++ b/thirdparty/libsimplewebm/libwebm/mkvparser/mkvparser.cc @@ -12,51 +12,30 @@ #define MSC_COMPAT #endif -#include <assert.h> -#include <float.h> -#include <limits.h> -#include <math.h> -#include <string.h> +#include <cassert> +#include <cfloat> +#include <climits> +#include <cmath> +#include <cstring> +#include <memory> +#include <new> #include "common/webmids.h" namespace mkvparser { +const long long kStringElementSizeLimit = 20 * 1000 * 1000; const float MasteringMetadata::kValueNotPresent = FLT_MAX; const long long Colour::kValueNotPresent = LLONG_MAX; +const float Projection::kValueNotPresent = FLT_MAX; #ifdef MSC_COMPAT inline bool isnan(double val) { return !!_isnan(val); } inline bool isinf(double val) { return !_finite(val); } +#else +inline bool isnan(double val) { return std::isnan(val); } +inline bool isinf(double val) { return std::isinf(val); } #endif // MSC_COMPAT -template<typename T> -class my_auto_ptr { - my_auto_ptr(const my_auto_ptr &); - T *operator =(const my_auto_ptr &); - - T *m_ptr; -public: - my_auto_ptr(T *ptr) : - m_ptr(ptr) - {} - my_auto_ptr() : - m_ptr(NULL) - {} - ~my_auto_ptr() { - delete m_ptr; - } - - T *release() { - T *ptr = m_ptr; - m_ptr = NULL; - return ptr; - } - - T *operator ->() const { - return m_ptr; - } -}; - IMkvReader::~IMkvReader() {} template <typename Type> @@ -72,7 +51,7 @@ Type* SafeArrayAlloc(unsigned long long num_elements, if (num_bytes != static_cast<size_t>(num_bytes)) return NULL; - return new Type[static_cast<size_t>(num_bytes)]; + return new (std::nothrow) Type[static_cast<size_t>(num_bytes)]; } void GetVersion(int& major, int& minor, int& build, int& revision) { @@ -304,7 +283,7 @@ long UnserializeFloat(IMkvReader* pReader, long long pos, long long size_, result = d; } - if (isinf(result) || isnan(result)) + if (mkvparser::isinf(result) || mkvparser::isnan(result)) return E_FILE_FORMAT_INVALID; return 0; @@ -347,7 +326,7 @@ long UnserializeString(IMkvReader* pReader, long long pos, long long size, delete[] str; str = NULL; - if (size >= LONG_MAX || size < 0) + if (size >= LONG_MAX || size < 0 || size > kStringElementSizeLimit) return E_FILE_FORMAT_INVALID; // +1 for '\0' terminator @@ -818,7 +797,9 @@ long long Segment::CreateInstance(IMkvReader* pReader, long long pos, else if ((pos + size) > total) size = -1; - pSegment = new Segment(pReader, idpos, pos, size); + pSegment = new (std::nothrow) Segment(pReader, idpos, pos, size); + if (pSegment == NULL) + return E_PARSE_FAILED; return 0; // success } @@ -954,7 +935,11 @@ long long Segment::ParseHeaders() { if (m_pInfo) return E_FILE_FORMAT_INVALID; - m_pInfo = new SegmentInfo(this, pos, size, element_start, element_size); + m_pInfo = new (std::nothrow) + SegmentInfo(this, pos, size, element_start, element_size); + + if (m_pInfo == NULL) + return -1; const long status = m_pInfo->Parse(); @@ -964,7 +949,11 @@ long long Segment::ParseHeaders() { if (m_pTracks) return E_FILE_FORMAT_INVALID; - m_pTracks = new Tracks(this, pos, size, element_start, element_size); + m_pTracks = new (std::nothrow) + Tracks(this, pos, size, element_start, element_size); + + if (m_pTracks == NULL) + return -1; const long status = m_pTracks->Parse(); @@ -972,11 +961,19 @@ long long Segment::ParseHeaders() { return status; } else if (id == libwebm::kMkvCues) { if (m_pCues == NULL) { - m_pCues = new Cues(this, pos, size, element_start, element_size); + m_pCues = new (std::nothrow) + Cues(this, pos, size, element_start, element_size); + + if (m_pCues == NULL) + return -1; } } else if (id == libwebm::kMkvSeekHead) { if (m_pSeekHead == NULL) { - m_pSeekHead = new SeekHead(this, pos, size, element_start, element_size); + m_pSeekHead = new (std::nothrow) + SeekHead(this, pos, size, element_start, element_size); + + if (m_pSeekHead == NULL) + return -1; const long status = m_pSeekHead->Parse(); @@ -985,7 +982,11 @@ long long Segment::ParseHeaders() { } } else if (id == libwebm::kMkvChapters) { if (m_pChapters == NULL) { - m_pChapters = new Chapters(this, pos, size, element_start, element_size); + m_pChapters = new (std::nothrow) + Chapters(this, pos, size, element_start, element_size); + + if (m_pChapters == NULL) + return -1; const long status = m_pChapters->Parse(); @@ -994,7 +995,11 @@ long long Segment::ParseHeaders() { } } else if (id == libwebm::kMkvTags) { if (m_pTags == NULL) { - m_pTags = new Tags(this, pos, size, element_start, element_size); + m_pTags = new (std::nothrow) + Tags(this, pos, size, element_start, element_size); + + if (m_pTags == NULL) + return -1; const long status = m_pTags->Parse(); @@ -1136,7 +1141,9 @@ long Segment::DoLoadCluster(long long& pos, long& len) { if (m_pCues == NULL) { const long long element_size = (pos - idpos) + size; - m_pCues = new Cues(this, pos, size, idpos, element_size); + m_pCues = new (std::nothrow) Cues(this, pos, size, idpos, element_size); + if (m_pCues == NULL) + return -1; } m_pos = pos + size; // consume payload @@ -1342,7 +1349,9 @@ bool Segment::AppendCluster(Cluster* pCluster) { if (count >= size) { const long n = (size <= 0) ? 2048 : 2 * size; - Cluster** const qq = new Cluster*[n]; + Cluster** const qq = new (std::nothrow) Cluster*[n]; + if (qq == NULL) + return false; Cluster** q = qq; Cluster** p = m_clusters; @@ -1397,7 +1406,9 @@ bool Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx) { if (count >= size) { const long n = (size <= 0) ? 2048 : 2 * size; - Cluster** const qq = new Cluster*[n]; + Cluster** const qq = new (std::nothrow) Cluster*[n]; + if (qq == NULL) + return false; Cluster** q = qq; Cluster** p = m_clusters; @@ -1466,6 +1477,8 @@ long Segment::Load() { } } +SeekHead::Entry::Entry() : id(0), pos(0), element_start(0), element_size(0) {} + SeekHead::SeekHead(Segment* pSegment, long long start, long long size_, long long element_start, long long element_size) : m_pSegment(pSegment), @@ -1516,9 +1529,19 @@ long SeekHead::Parse() { if (pos != stop) return E_FILE_FORMAT_INVALID; - m_entries = new Entry[entry_count]; + if (entry_count > 0) { + m_entries = new (std::nothrow) Entry[entry_count]; - m_void_elements = new VoidElement[void_element_count]; + if (m_entries == NULL) + return -1; + } + + if (void_element_count > 0) { + m_void_elements = new (std::nothrow) VoidElement[void_element_count]; + + if (m_void_elements == NULL) + return -1; + } // now parse the entries and void elements @@ -1537,14 +1560,14 @@ long SeekHead::Parse() { if (status < 0) // error return status; - if (id == libwebm::kMkvSeek) { + if (id == libwebm::kMkvSeek && entry_count > 0) { if (ParseEntry(pReader, pos, size, pEntry)) { Entry& e = *pEntry++; e.element_start = idpos; e.element_size = (pos + size) - idpos; } - } else if (id == libwebm::kMkvVoid) { + } else if (id == libwebm::kMkvVoid && void_element_count > 0) { VoidElement& e = *pVoidElement++; e.element_start = idpos; @@ -1706,7 +1729,10 @@ long Segment::ParseCues(long long off, long long& pos, long& len) { const long long element_size = element_stop - element_start; - m_pCues = new Cues(this, pos, size, element_start, element_size); + m_pCues = + new (std::nothrow) Cues(this, pos, size, element_start, element_size); + if (m_pCues == NULL) + return -1; return 0; // success } @@ -1748,18 +1774,7 @@ bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_, if ((pos + seekIdSize) > stop) return false; - // Note that the SeekId payload really is serialized - // as a "Matroska integer", not as a plain binary value. - // In fact, Matroska requires that ID values in the - // stream exactly match the binary representation as listed - // in the Matroska specification. - // - // This parser is more liberal, and permits IDs to have - // any width. (This could make the representation in the stream - // different from what's in the spec, but it doesn't matter here, - // since we always normalize "Matroska integer" values.) - - pEntry->id = ReadUInt(pReader, pos, len); // payload + pEntry->id = ReadID(pReader, pos, len); // payload if (pEntry->id <= 0) return false; @@ -1898,7 +1913,9 @@ bool Cues::PreloadCuePoint(long& cue_points_size, long long pos) const { if (m_preload_count >= cue_points_size) { const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size; - CuePoint** const qq = new CuePoint*[n]; + CuePoint** const qq = new (std::nothrow) CuePoint*[n]; + if (qq == NULL) + return false; CuePoint** q = qq; // beginning of target @@ -1914,7 +1931,9 @@ bool Cues::PreloadCuePoint(long& cue_points_size, long long pos) const { cue_points_size = n; } - CuePoint* const pCP = new CuePoint(m_preload_count, pos); + CuePoint* const pCP = new (std::nothrow) CuePoint(m_preload_count, pos); + if (pCP == NULL) + return false; m_cue_points[m_preload_count++] = pCP; return true; @@ -2320,7 +2339,9 @@ bool CuePoint::Load(IMkvReader* pReader) { // << " timecode=" << m_timecode // << endl; - m_track_positions = new TrackPosition[m_track_positions_count]; + m_track_positions = new (std::nothrow) TrackPosition[m_track_positions_count]; + if (m_track_positions == NULL) + return false; // Now parse track positions @@ -2410,7 +2431,9 @@ bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_, } const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const { - assert(pTrack); + if (pTrack == NULL) { + return NULL; + } const long long n = pTrack->GetNumber(); @@ -2915,7 +2938,10 @@ long Segment::DoParseNext(const Cluster*& pResult, long long& pos, long& len) { const long long element_size = element_stop - element_start; if (m_pCues == NULL) { - m_pCues = new Cues(this, pos, size, element_start, element_size); + m_pCues = new (std::nothrow) + Cues(this, pos, size, element_start, element_size); + if (m_pCues == NULL) + return false; } pos += size; // consume payload @@ -3266,7 +3292,10 @@ bool Chapters::ExpandEditionsArray() { const int size = (m_editions_size == 0) ? 1 : 2 * m_editions_size; - Edition* const editions = new Edition[size]; + Edition* const editions = new (std::nothrow) Edition[size]; + + if (editions == NULL) + return false; for (int idx = 0; idx < m_editions_count; ++idx) { m_editions[idx].ShallowCopy(editions[idx]); @@ -3378,7 +3407,10 @@ bool Chapters::Edition::ExpandAtomsArray() { const int size = (m_atoms_size == 0) ? 1 : 2 * m_atoms_size; - Atom* const atoms = new Atom[size]; + Atom* const atoms = new (std::nothrow) Atom[size]; + + if (atoms == NULL) + return false; for (int idx = 0; idx < m_atoms_count; ++idx) { m_atoms[idx].ShallowCopy(atoms[idx]); @@ -3563,7 +3595,10 @@ bool Chapters::Atom::ExpandDisplaysArray() { const int size = (m_displays_size == 0) ? 1 : 2 * m_displays_size; - Display* const displays = new Display[size]; + Display* const displays = new (std::nothrow) Display[size]; + + if (displays == NULL) + return false; for (int idx = 0; idx < m_displays_count; ++idx) { m_displays[idx].ShallowCopy(displays[idx]); @@ -3723,7 +3758,10 @@ bool Tags::ExpandTagsArray() { const int size = (m_tags_size == 0) ? 1 : 2 * m_tags_size; - Tag* const tags = new Tag[size]; + Tag* const tags = new (std::nothrow) Tag[size]; + + if (tags == NULL) + return false; for (int idx = 0; idx < m_tags_count; ++idx) { m_tags[idx].ShallowCopy(tags[idx]); @@ -3834,7 +3872,10 @@ bool Tags::Tag::ExpandSimpleTagsArray() { const int size = (m_simple_tags_size == 0) ? 1 : 2 * m_simple_tags_size; - SimpleTag* const displays = new SimpleTag[size]; + SimpleTag* const displays = new (std::nothrow) SimpleTag[size]; + + if (displays == NULL) + return false; for (int idx = 0; idx < m_simple_tags_count; ++idx) { m_simple_tags[idx].ShallowCopy(displays[idx]); @@ -3992,7 +4033,7 @@ long SegmentInfo::Parse() { } const double rollover_check = m_duration * m_timecodeScale; - if (rollover_check > LLONG_MAX) + if (rollover_check > static_cast<double>(LLONG_MAX)) return E_FILE_FORMAT_INVALID; if (pos != stop) @@ -4083,7 +4124,7 @@ ContentEncoding::~ContentEncoding() { } const ContentEncoding::ContentCompression* - ContentEncoding::GetCompressionByIndex(unsigned long idx) const { +ContentEncoding::GetCompressionByIndex(unsigned long idx) const { const ptrdiff_t count = compression_entries_end_ - compression_entries_; assert(count >= 0); @@ -4179,12 +4220,20 @@ long ContentEncoding::ParseContentEncodingEntry(long long start, long long size, return -1; if (compression_count > 0) { - compression_entries_ = new ContentCompression*[compression_count]; + compression_entries_ = + new (std::nothrow) ContentCompression*[compression_count]; + if (!compression_entries_) + return -1; compression_entries_end_ = compression_entries_; } if (encryption_count > 0) { - encryption_entries_ = new ContentEncryption*[encryption_count]; + encryption_entries_ = + new (std::nothrow) ContentEncryption*[encryption_count]; + if (!encryption_entries_) { + delete[] compression_entries_; + return -1; + } encryption_entries_end_ = encryption_entries_; } @@ -4204,7 +4253,10 @@ long ContentEncoding::ParseContentEncodingEntry(long long start, long long size, } else if (id == libwebm::kMkvContentEncodingType) { encoding_type_ = UnserializeUInt(pReader, pos, size); } else if (id == libwebm::kMkvContentCompression) { - ContentCompression* const compression = new ContentCompression(); + ContentCompression* const compression = + new (std::nothrow) ContentCompression(); + if (!compression) + return -1; status = ParseCompressionEntry(pos, size, pReader, compression); if (status) { @@ -4213,7 +4265,10 @@ long ContentEncoding::ParseContentEncodingEntry(long long start, long long size, } *compression_entries_end_++ = compression; } else if (id == libwebm::kMkvContentEncryption) { - ContentEncryption* const encryption = new ContentEncryption(); + ContentEncryption* const encryption = + new (std::nothrow) ContentEncryption(); + if (!encryption) + return -1; status = ParseEncryptionEntry(pos, size, pReader, encryption); if (status) { @@ -4419,7 +4474,11 @@ long Track::Create(Segment* pSegment, const Info& info, long long element_start, if (pResult) return -1; - Track* const pTrack = new Track(pSegment, element_start, element_size); + Track* const pTrack = + new (std::nothrow) Track(pSegment, element_start, element_size); + + if (pTrack == NULL) + return -1; // generic error const int status = info.Copy(pTrack->m_info); @@ -4871,7 +4930,10 @@ long Track::ParseContentEncodingsEntry(long long start, long long size) { if (count <= 0) return -1; - content_encoding_entries_ = new ContentEncoding*[count]; + content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count]; + if (!content_encoding_entries_) + return -1; + content_encoding_entries_end_ = content_encoding_entries_; pos = start; @@ -4883,7 +4945,10 @@ long Track::ParseContentEncodingsEntry(long long start, long long size) { // pos now designates start of element if (id == libwebm::kMkvContentEncoding) { - ContentEncoding* const content_encoding = new ContentEncoding(); + ContentEncoding* const content_encoding = + new (std::nothrow) ContentEncoding(); + if (!content_encoding) + return -1; status = content_encoding->ParseContentEncodingEntry(pos, size, pReader); if (status) { @@ -4917,20 +4982,27 @@ bool PrimaryChromaticity::Parse(IMkvReader* reader, long long read_pos, if (!reader) return false; - my_auto_ptr<PrimaryChromaticity> chromaticity_ptr(*chromaticity ? *chromaticity : new PrimaryChromaticity()); + if (!*chromaticity) + *chromaticity = new PrimaryChromaticity(); - float* value = is_x ? &chromaticity_ptr->x : &chromaticity_ptr->y; + if (!*chromaticity) + return false; + + PrimaryChromaticity* pc = *chromaticity; + float* value = is_x ? &pc->x : &pc->y; double parser_value = 0; - const long long value_parse_status = + const long long parse_status = UnserializeFloat(reader, read_pos, value_size, parser_value); - *value = static_cast<float>(parser_value); - - if (value_parse_status < 0 || *value < 0.0 || *value > 1.0) + // Valid range is [0, 1]. Make sure the double is representable as a float + // before casting. + if (parse_status < 0 || parser_value < 0.0 || parser_value > 1.0 || + (parser_value > 0.0 && parser_value < FLT_MIN)) return false; - *chromaticity = chromaticity_ptr.release(); + *value = static_cast<float>(parser_value); + return true; } @@ -4939,7 +5011,9 @@ bool MasteringMetadata::Parse(IMkvReader* reader, long long mm_start, if (!reader || *mm) return false; - my_auto_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata()); + std::unique_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata()); + if (!mm_ptr.get()) + return false; const long long mm_end = mm_start + mm_size; long long read_pos = mm_start; @@ -4957,6 +5031,10 @@ bool MasteringMetadata::Parse(IMkvReader* reader, long long mm_start, double value = 0; const long long value_parse_status = UnserializeFloat(reader, read_pos, child_size, value); + if (value < -FLT_MAX || value > FLT_MAX || + (value > 0.0 && value < FLT_MIN)) { + return false; + } mm_ptr->luminance_max = static_cast<float>(value); if (value_parse_status < 0 || mm_ptr->luminance_max < 0.0 || mm_ptr->luminance_max > 9999.99) { @@ -4966,6 +5044,10 @@ bool MasteringMetadata::Parse(IMkvReader* reader, long long mm_start, double value = 0; const long long value_parse_status = UnserializeFloat(reader, read_pos, child_size, value); + if (value < -FLT_MAX || value > FLT_MAX || + (value > 0.0 && value < FLT_MIN)) { + return false; + } mm_ptr->luminance_min = static_cast<float>(value); if (value_parse_status < 0 || mm_ptr->luminance_min < 0.0 || mm_ptr->luminance_min > 999.9999) { @@ -5018,7 +5100,9 @@ bool Colour::Parse(IMkvReader* reader, long long colour_start, if (!reader || *colour) return false; - my_auto_ptr<Colour> colour_ptr(new Colour()); + std::unique_ptr<Colour> colour_ptr(new Colour()); + if (!colour_ptr.get()) + return false; const long long colour_end = colour_start + colour_size; long long read_pos = colour_start; @@ -5109,11 +5193,94 @@ bool Colour::Parse(IMkvReader* reader, long long colour_start, return true; } +bool Projection::Parse(IMkvReader* reader, long long start, long long size, + Projection** projection) { + if (!reader || *projection) + return false; + + std::unique_ptr<Projection> projection_ptr(new Projection()); + if (!projection_ptr.get()) + return false; + + const long long end = start + size; + long long read_pos = start; + + while (read_pos < end) { + long long child_id = 0; + long long child_size = 0; + + const long long status = + ParseElementHeader(reader, read_pos, end, child_id, child_size); + if (status < 0) + return false; + + if (child_id == libwebm::kMkvProjectionType) { + long long projection_type = kTypeNotPresent; + projection_type = UnserializeUInt(reader, read_pos, child_size); + if (projection_type < 0) + return false; + + projection_ptr->type = static_cast<ProjectionType>(projection_type); + } else if (child_id == libwebm::kMkvProjectionPrivate) { + unsigned char* data = SafeArrayAlloc<unsigned char>(1, child_size); + + if (data == NULL) + return false; + + const int status = + reader->Read(read_pos, static_cast<long>(child_size), data); + + if (status) { + delete[] data; + return false; + } + + projection_ptr->private_data = data; + projection_ptr->private_data_length = static_cast<size_t>(child_size); + } else { + double value = 0; + const long long value_parse_status = + UnserializeFloat(reader, read_pos, child_size, value); + // Make sure value is representable as a float before casting. + if (value_parse_status < 0 || value < -FLT_MAX || value > FLT_MAX || + (value > 0.0 && value < FLT_MIN)) { + return false; + } + + switch (child_id) { + case libwebm::kMkvProjectionPoseYaw: + projection_ptr->pose_yaw = static_cast<float>(value); + break; + case libwebm::kMkvProjectionPosePitch: + projection_ptr->pose_pitch = static_cast<float>(value); + break; + case libwebm::kMkvProjectionPoseRoll: + projection_ptr->pose_roll = static_cast<float>(value); + break; + default: + return false; + } + } + + read_pos += child_size; + if (read_pos > end) + return false; + } + + *projection = projection_ptr.release(); + return true; +} + VideoTrack::VideoTrack(Segment* pSegment, long long element_start, long long element_size) - : Track(pSegment, element_start, element_size), m_colour(NULL) {} + : Track(pSegment, element_start, element_size), + m_colour(NULL), + m_projection(NULL) {} -VideoTrack::~VideoTrack() { delete m_colour; } +VideoTrack::~VideoTrack() { + delete m_colour; + delete m_projection; +} long VideoTrack::Parse(Segment* pSegment, const Info& info, long long element_start, long long element_size, @@ -5145,6 +5312,7 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info, const long long stop = pos + s.size; Colour* colour = NULL; + Projection* projection = NULL; while (pos < stop) { long long id, size; @@ -5195,6 +5363,9 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info, } else if (id == libwebm::kMkvColour) { if (!Colour::Parse(pReader, pos, size, &colour)) return E_FILE_FORMAT_INVALID; + } else if (id == libwebm::kMkvProjection) { + if (!Projection::Parse(pReader, pos, size, &projection)) + return E_FILE_FORMAT_INVALID; } pos += size; // consume payload @@ -5205,7 +5376,11 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info, if (pos != stop) return E_FILE_FORMAT_INVALID; - VideoTrack* const pTrack = new VideoTrack(pSegment, element_start, element_size); + VideoTrack* const pTrack = + new (std::nothrow) VideoTrack(pSegment, element_start, element_size); + + if (pTrack == NULL) + return -1; // generic error const int status = info.Copy(pTrack->m_info); @@ -5222,6 +5397,7 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info, pTrack->m_stereo_mode = stereo_mode; pTrack->m_rate = rate; pTrack->m_colour = colour; + pTrack->m_projection = projection; pResult = pTrack; return 0; // success @@ -5322,6 +5498,8 @@ long VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const { Colour* VideoTrack::GetColour() const { return m_colour; } +Projection* VideoTrack::GetProjection() const { return m_projection; } + long long VideoTrack::GetWidth() const { return m_width; } long long VideoTrack::GetHeight() const { return m_height; } @@ -5404,7 +5582,11 @@ long AudioTrack::Parse(Segment* pSegment, const Info& info, if (pos != stop) return E_FILE_FORMAT_INVALID; - AudioTrack* const pTrack = new AudioTrack(pSegment, element_start, element_size); + AudioTrack* const pTrack = + new (std::nothrow) AudioTrack(pSegment, element_start, element_size); + + if (pTrack == NULL) + return -1; // generic error const int status = info.Copy(pTrack->m_info); @@ -5472,7 +5654,11 @@ long Tracks::Parse() { if (count <= 0) return 0; // success - m_trackEntries = new Track*[count]; + m_trackEntries = new (std::nothrow) Track*[count]; + + if (m_trackEntries == NULL) + return -1; + m_trackEntriesEnd = m_trackEntries; pos = m_start; @@ -6575,7 +6761,10 @@ Cluster* Cluster::Create(Segment* pSegment, long idx, long long off) { const long long element_start = pSegment->m_start + off; - return new Cluster(pSegment, idx, element_start); + Cluster* const pCluster = + new (std::nothrow) Cluster(pSegment, idx, element_start); + + return pCluster; } Cluster::Cluster() @@ -6604,8 +6793,10 @@ Cluster::Cluster(Segment* pSegment, long idx, long long element_start {} Cluster::~Cluster() { - if (m_entries_count <= 0) + if (m_entries_count <= 0) { + delete[] m_entries; return; + } BlockEntry** i = m_entries; BlockEntry** const j = m_entries + m_entries_count; @@ -6918,7 +7109,9 @@ long Cluster::CreateBlock(long long id, assert(m_entries_size == 0); m_entries_size = 1024; - m_entries = new BlockEntry*[m_entries_size]; + m_entries = new (std::nothrow) BlockEntry*[m_entries_size]; + if (m_entries == NULL) + return -1; m_entries_count = 0; } else { @@ -6929,7 +7122,9 @@ long Cluster::CreateBlock(long long id, if (m_entries_count >= m_entries_size) { const long entries_size = 2 * m_entries_size; - BlockEntry** const entries = new BlockEntry*[entries_size]; + BlockEntry** const entries = new (std::nothrow) BlockEntry*[entries_size]; + if (entries == NULL) + return -1; BlockEntry** src = m_entries; BlockEntry** const src_end = src + m_entries_count; @@ -7038,7 +7233,11 @@ long Cluster::CreateBlockGroup(long long start_offset, long long size, BlockEntry** const ppEntry = m_entries + idx; BlockEntry*& pEntry = *ppEntry; - pEntry = new BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding); + pEntry = new (std::nothrow) + BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding); + + if (pEntry == NULL) + return -1; // generic error BlockGroup* const p = static_cast<BlockGroup*>(pEntry); @@ -7066,7 +7265,10 @@ long Cluster::CreateSimpleBlock(long long st, long long sz) { BlockEntry** const ppEntry = m_entries + idx; BlockEntry*& pEntry = *ppEntry; - pEntry = new SimpleBlock(this, idx, st, sz); + pEntry = new (std::nothrow) SimpleBlock(this, idx, st, sz); + + if (pEntry == NULL) + return -1; // generic error SimpleBlock* const p = static_cast<SimpleBlock*>(pEntry); @@ -7461,7 +7663,9 @@ long Block::Parse(const Cluster* pCluster) { return E_FILE_FORMAT_INVALID; m_frame_count = 1; - m_frames = new Frame[m_frame_count]; + m_frames = new (std::nothrow) Frame[m_frame_count]; + if (m_frames == NULL) + return -1; Frame& f = m_frames[0]; f.pos = pos; @@ -7492,7 +7696,9 @@ long Block::Parse(const Cluster* pCluster) { m_frame_count = int(biased_count) + 1; - m_frames = new Frame[m_frame_count]; + m_frames = new (std::nothrow) Frame[m_frame_count]; + if (m_frames == NULL) + return -1; if (!m_frames) return E_FILE_FORMAT_INVALID; @@ -7701,6 +7907,10 @@ long Block::Parse(const Cluster* pCluster) { return E_FILE_FORMAT_INVALID; curr.len = static_cast<long>(frame_size); + // Check if size + curr.len could overflow. + if (size > LLONG_MAX - curr.len) { + return E_FILE_FORMAT_INVALID; + } size += curr.len; // contribution of this frame --frame_count; @@ -7741,7 +7951,6 @@ long Block::Parse(const Cluster* pCluster) { pf = m_frames; while (pf != pf_end) { Frame& f = *pf++; - assert((pos + f.len) <= stop); if ((pos + f.len) > stop) return E_FILE_FORMAT_INVALID; @@ -7763,6 +7972,11 @@ long long Block::GetTimeCode(const Cluster* pCluster) const { const long long tc0 = pCluster->GetTimeCode(); assert(tc0 >= 0); + // Check if tc0 + m_timecode would overflow. + if (tc0 < 0 || LLONG_MAX - tc0 < m_timecode) { + return -1; + } + const long long tc = tc0 + m_timecode; return tc; // unscaled timecode units @@ -7780,6 +7994,10 @@ long long Block::GetTime(const Cluster* pCluster) const { const long long scale = pInfo->GetTimeCodeScale(); assert(scale >= 1); + // Check if tc * scale could overflow. + if (tc != 0 && scale > LLONG_MAX / tc) { + return -1; + } const long long ns = tc * scale; return ns; diff --git a/thirdparty/libsimplewebm/libwebm/mkvparser/mkvparser.h b/thirdparty/libsimplewebm/libwebm/mkvparser/mkvparser.h index 1ef274b162..6dce7e50ba 100644 --- a/thirdparty/libsimplewebm/libwebm/mkvparser/mkvparser.h +++ b/thirdparty/libsimplewebm/libwebm/mkvparser/mkvparser.h @@ -8,7 +8,7 @@ #ifndef MKVPARSER_MKVPARSER_H_ #define MKVPARSER_MKVPARSER_H_ -#include <stddef.h> +#include <cstddef> namespace mkvparser { @@ -21,6 +21,7 @@ class IMkvReader { virtual int Read(long long pos, long len, unsigned char* buf) = 0; virtual int Length(long long* total, long long* available) = 0; + public: virtual ~IMkvReader(); }; @@ -472,6 +473,34 @@ struct Colour { MasteringMetadata* mastering_metadata; }; +struct Projection { + enum ProjectionType { + kTypeNotPresent = -1, + kRectangular = 0, + kEquirectangular = 1, + kCubeMap = 2, + kMesh = 3, + }; + static const float kValueNotPresent; + Projection() + : type(kTypeNotPresent), + private_data(NULL), + private_data_length(0), + pose_yaw(kValueNotPresent), + pose_pitch(kValueNotPresent), + pose_roll(kValueNotPresent) {} + ~Projection() { delete[] private_data; } + static bool Parse(IMkvReader* reader, long long element_start, + long long element_size, Projection** projection); + + ProjectionType type; + unsigned char* private_data; + size_t private_data_length; + float pose_yaw; + float pose_pitch; + float pose_roll; +}; + class VideoTrack : public Track { VideoTrack(const VideoTrack&); VideoTrack& operator=(const VideoTrack&); @@ -496,6 +525,8 @@ class VideoTrack : public Track { Colour* GetColour() const; + Projection* GetProjection() const; + private: long long m_width; long long m_height; @@ -507,6 +538,7 @@ class VideoTrack : public Track { double m_rate; Colour* m_colour; + Projection* m_projection; }; class AudioTrack : public Track { @@ -812,6 +844,8 @@ class SeekHead { long Parse(); struct Entry { + Entry(); + // the SeekHead entry payload long long id; long long pos; diff --git a/thirdparty/lws/mbedtls_wrapper/include/platform/ssl_port.h b/thirdparty/lws/mbedtls_wrapper/include/platform/ssl_port.h index fd461e9819..2ffd7e7544 100644 --- a/thirdparty/lws/mbedtls_wrapper/include/platform/ssl_port.h +++ b/thirdparty/lws/mbedtls_wrapper/include/platform/ssl_port.h @@ -25,7 +25,7 @@ */ #include "string.h" -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__FreeBSD__) #include <stdlib.h> #else #include "malloc.h" diff --git a/thirdparty/lws/minilex.c b/thirdparty/lws/minilex.c deleted file mode 100644 index 3cb1e33696..0000000000 --- a/thirdparty/lws/minilex.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * minilex.c - * - * High efficiency lexical state parser - * - * Copyright (C)2011-2014 Andy Green <andy@warmcat.com> - * - * Licensed under LGPL2 - * - * Usage: gcc minilex.c -o minilex && ./minilex > lextable.h - * - * Run it twice to test parsing on the generated table on stderr - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "lextable-strings.h" - -/* - * b7 = 0 = 1-byte seq - * 0x08 = fail - * 2-byte seq - * 0x00 - 0x07, then terminal as given in 2nd byte - 3-byte seq - * no match: go fwd 3 byte, match: jump fwd by amt in +1/+2 bytes - * = 1 = 1-byte seq - * no match: die, match go fwd 1 byte - */ - -unsigned char lextable[] = { - #include "lextable.h" -}; - -#define PARALLEL 30 - -struct state { - char c[PARALLEL]; - int state[PARALLEL]; - int count; - int bytepos; - - int real_pos; -}; - -struct state state[1000]; -int next = 1; - -#define FAIL_CHAR 0x08 - -int lextable_decode(int pos, char c) -{ - while (1) { - if (lextable[pos] & (1 << 7)) { /* 1-byte, fail on mismatch */ - if ((lextable[pos] & 0x7f) != c) - return -1; - /* fall thru */ - pos++; - if (lextable[pos] == FAIL_CHAR) - return -1; - return pos; - } else { /* b7 = 0, end or 3-byte */ - if (lextable[pos] < FAIL_CHAR) /* terminal marker */ - return pos; - - if (lextable[pos] == c) /* goto */ - return pos + (lextable[pos + 1]) + - (lextable[pos + 2] << 8); - /* fall thru goto */ - pos += 3; - /* continue */ - } - } -} - -int main(void) -{ - int n = 0; - int m = 0; - int prev; - char c; - int walk; - int saw; - int y; - int j; - int pos = 0; - - while (n < sizeof(set) / sizeof(set[0])) { - - m = 0; - walk = 0; - prev = 0; - - if (set[n][0] == '\0') { - n++; - continue; - } - - while (set[n][m]) { - - saw = 0; - for (y = 0; y < state[walk].count; y++) - if (state[walk].c[y] == set[n][m]) { - /* exists -- go forward */ - walk = state[walk].state[y]; - saw = 1; - break; - } - - if (saw) - goto again; - - /* something we didn't see before */ - - state[walk].c[state[walk].count] = set[n][m]; - - state[walk].state[state[walk].count] = next; - state[walk].count++; - walk = next++; -again: - m++; - } - - state[walk].c[0] = n++; - state[walk].state[0] = 0; /* terminal marker */ - state[walk].count = 1; - } - - walk = 0; - for (n = 0; n < next; n++) { - state[n].bytepos = walk; - walk += (2 * state[n].count); - } - - /* compute everyone's position first */ - - pos = 0; - walk = 0; - for (n = 0; n < next; n++) { - - state[n].real_pos = pos; - - for (m = 0; m < state[n].count; m++) { - - if (state[n].state[m] == 0) - pos += 2; /* terminal marker */ - else { /* c is a character */ - if ((state[state[n].state[m]].bytepos - - walk) == 2) - pos++; - else { - pos += 3; - if (m == state[n].count - 1) - pos++; /* fail */ - } - } - walk += 2; - } - } - - walk = 0; - pos = 0; - for (n = 0; n < next; n++) { - for (m = 0; m < state[n].count; m++) { - - if (!m) - fprintf(stdout, "/* pos %04x: %3d */ ", - state[n].real_pos, n); - else - fprintf(stdout, " "); - - y = state[n].c[m]; - saw = state[n].state[m]; - - if (saw == 0) { // c is a terminal then - - if (y > 0x7ff) { - fprintf(stderr, "terminal too big\n"); - return 2; - } - - fprintf(stdout, " 0x%02X, 0x%02X " - " " - "/* - terminal marker %2d - */,\n", - y >> 8, y & 0xff, y & 0x7f); - pos += 2; - walk += 2; - continue; - } - - /* c is a character */ - - prev = y &0x7f; - if (prev < 32 || prev > 126) - prev = '.'; - - - if ((state[saw].bytepos - walk) == 2) { - fprintf(stdout, " 0x%02X /* '%c' -> */,\n", - y | 0x80, prev); - pos++; - walk += 2; - continue; - } - - j = state[saw].real_pos - pos; - - if (j > 0xffff) { - fprintf(stderr, - "Jump > 64K bytes ahead (%d to %d)\n", - state[n].real_pos, state[saw].real_pos); - return 1; - } - fprintf(stdout, " 0x%02X /* '%c' */, 0x%02X, 0x%02X " - "/* (to 0x%04X state %3d) */,\n", - y, prev, - j & 0xff, j >> 8, - state[saw].real_pos, saw); - pos += 3; - - if (m == state[n].count - 1) { - fprintf(stdout, - " 0x%02X, /* fail */\n", - FAIL_CHAR); - pos++; /* fail */ - } - - walk += 2; - } - } - - fprintf(stdout, "/* total size %d bytes */\n", pos); - - /* - * Try to parse every legal input string - */ - - for (n = 0; n < sizeof(set) / sizeof(set[0]); n++) { - walk = 0; - m = 0; - y = -1; - - if (set[n][0] == '\0') - continue; - - fprintf(stderr, " trying '%s'\n", set[n]); - - while (set[n][m]) { - walk = lextable_decode(walk, set[n][m]); - if (walk < 0) { - fprintf(stderr, "failed\n"); - return 3; - } - - if (lextable[walk] < FAIL_CHAR) { - y = (lextable[walk] << 8) + lextable[walk + 1]; - break; - } - m++; - } - - if (y != n) { - fprintf(stderr, "decode failed %d\n", y); - return 4; - } - } - - fprintf(stderr, "All decode OK\n"); - - return 0; -} diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c index a116e605d2..5e8a090b37 100644 --- a/thirdparty/mbedtls/library/entropy_poll.c +++ b/thirdparty/mbedtls/library/entropy_poll.c @@ -54,28 +54,41 @@ #define _WIN32_WINNT 0x0400 #endif #include <windows.h> -#include <wincrypt.h> +#include <bcrypt.h> +#if _MSC_VER <= 1600 +/* Visual Studio 2010 and earlier issue a warning when both <stdint.h> and <intsafe.h> are included, as they + * redefine a number of <TYPE>_MAX constants. These constants are guaranteed to be the same, though, so + * we suppress the warning when including intsafe.h. + */ +#pragma warning( push ) +#pragma warning( disable : 4005 ) +#endif +#include <intsafe.h> +#if _MSC_VER <= 1600 +#pragma warning( pop ) +#endif int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, size_t *olen ) { - HCRYPTPROV provider; + ULONG len_as_ulong = 0; ((void) data); *olen = 0; - if( CryptAcquireContext( &provider, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + /* + * BCryptGenRandom takes ULONG for size, which is smaller than size_t on 64-bit platforms. + * Ensure len's value can be safely converted into a ULONG. + */ + if ( FAILED( SizeTToULong( len, &len_as_ulong ) ) ) { return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); } - if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + if ( !BCRYPT_SUCCESS( BCryptGenRandom( NULL, output, len_as_ulong, BCRYPT_USE_SYSTEM_PREFERRED_RNG ) ) ) { - CryptReleaseContext( provider, 0 ); return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); } - CryptReleaseContext( provider, 0 ); *olen = len; return( 0 ); diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 345f10227b..754049005d 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -49,7 +49,7 @@ #undef _WIN32_WINNT #endif /* Enables getaddrinfo() & Co */ -#define _WIN32_WINNT 0x0501 +#define _WIN32_WINNT 0x0601 #include <ws2tcpip.h> #include <winsock2.h> diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c index c6209fb40d..6c592fdb5a 100644 --- a/thirdparty/mbedtls/library/x509_crt.c +++ b/thirdparty/mbedtls/library/x509_crt.c @@ -62,6 +62,18 @@ #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include <windows.h> +#if _MSC_VER <= 1600 +/* Visual Studio 2010 and earlier issue a warning when both <stdint.h> and <intsafe.h> are included, as they + * redefine a number of <TYPE>_MAX constants. These constants are guaranteed to be the same, though, so + * we suppress the warning when including intsafe.h. + */ +#pragma warning( push ) +#pragma warning( disable : 4005 ) +#endif +#include <intsafe.h> +#if _MSC_VER <= 1600 +#pragma warning( pop ) +#endif #else #include <time.h> #endif @@ -1110,6 +1122,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 lengthAsInt = 0; WIN32_FIND_DATAW file_data; HANDLE hFind; @@ -1124,7 +1137,10 @@ 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, &lengthAsInt ) ) ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir, MAX_PATH - 3 ); if( w_ret == 0 ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); @@ -1141,8 +1157,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 ), &lengthAsInt ) ) ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - lstrlenW( file_data.cFileName ), + lengthAsInt, p, (int) len - 1, NULL, NULL ); if( w_ret == 0 ) diff --git a/thirdparty/misc/clipper.cpp b/thirdparty/misc/clipper.cpp new file mode 100644 index 0000000000..d3143fe5ab --- /dev/null +++ b/thirdparty/misc/clipper.cpp @@ -0,0 +1,4629 @@ +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 6.4.2 * +* Date : 27 February 2017 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2017 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +/******************************************************************************* +* * +* This is a translation of the Delphi Clipper library and the naming style * +* used has retained a Delphi flavour. * +* * +*******************************************************************************/ + +#include "clipper.hpp" +#include <cmath> +#include <vector> +#include <algorithm> +#include <stdexcept> +#include <cstring> +#include <cstdlib> +#include <ostream> +#include <functional> + +namespace ClipperLib { + +static double const pi = 3.141592653589793238; +static double const two_pi = pi *2; +static double const def_arc_tolerance = 0.25; + +enum Direction { dRightToLeft, dLeftToRight }; + +static int const Unassigned = -1; //edge not currently 'owning' a solution +static int const Skip = -2; //edge that would otherwise close a path + +#define HORIZONTAL (-1.0E+40) +#define TOLERANCE (1.0e-20) +#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) + +struct TEdge { + IntPoint Bot; + IntPoint Curr; //current (updated for every new scanbeam) + IntPoint Top; + double Dx; + PolyType PolyTyp; + EdgeSide Side; //side only refers to current side of solution poly + int WindDelta; //1 or -1 depending on winding direction + int WindCnt; + int WindCnt2; //winding count of the opposite polytype + int OutIdx; + TEdge *Next; + TEdge *Prev; + TEdge *NextInLML; + TEdge *NextInAEL; + TEdge *PrevInAEL; + TEdge *NextInSEL; + TEdge *PrevInSEL; +}; + +struct IntersectNode { + TEdge *Edge1; + TEdge *Edge2; + IntPoint Pt; +}; + +struct LocalMinimum { + cInt Y; + TEdge *LeftBound; + TEdge *RightBound; +}; + +struct OutPt; + +//OutRec: contains a path in the clipping solution. Edges in the AEL will +//carry a pointer to an OutRec when they are part of the clipping solution. +struct OutRec { + int Idx; + bool IsHole; + bool IsOpen; + OutRec *FirstLeft; //see comments in clipper.pas + PolyNode *PolyNd; + OutPt *Pts; + OutPt *BottomPt; +}; + +struct OutPt { + int Idx; + IntPoint Pt; + OutPt *Next; + OutPt *Prev; +}; + +struct Join { + OutPt *OutPt1; + OutPt *OutPt2; + IntPoint OffPt; +}; + +struct LocMinSorter +{ + inline bool operator()(const LocalMinimum& locMin1, const LocalMinimum& locMin2) + { + return locMin2.Y < locMin1.Y; + } +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +inline cInt Round(double val) +{ + if ((val < 0)) return static_cast<cInt>(val - 0.5); + else return static_cast<cInt>(val + 0.5); +} +//------------------------------------------------------------------------------ + +inline cInt Abs(cInt val) +{ + return val < 0 ? -val : val; +} + +//------------------------------------------------------------------------------ +// PolyTree methods ... +//------------------------------------------------------------------------------ + +void PolyTree::Clear() +{ + for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i) + delete AllNodes[i]; + AllNodes.resize(0); + Childs.resize(0); +} +//------------------------------------------------------------------------------ + +PolyNode* PolyTree::GetFirst() const +{ + if (!Childs.empty()) + return Childs[0]; + else + return 0; +} +//------------------------------------------------------------------------------ + +int PolyTree::Total() const +{ + int result = (int)AllNodes.size(); + //with negative offsets, ignore the hidden outer polygon ... + if (result > 0 && Childs[0] != AllNodes[0]) result--; + return result; +} + +//------------------------------------------------------------------------------ +// PolyNode methods ... +//------------------------------------------------------------------------------ + +PolyNode::PolyNode(): Parent(0), Index(0), m_IsOpen(false) +{ +} +//------------------------------------------------------------------------------ + +int PolyNode::ChildCount() const +{ + return (int)Childs.size(); +} +//------------------------------------------------------------------------------ + +void PolyNode::AddChild(PolyNode& child) +{ + unsigned cnt = (unsigned)Childs.size(); + Childs.push_back(&child); + child.Parent = this; + child.Index = cnt; +} +//------------------------------------------------------------------------------ + +PolyNode* PolyNode::GetNext() const +{ + if (!Childs.empty()) + return Childs[0]; + else + return GetNextSiblingUp(); +} +//------------------------------------------------------------------------------ + +PolyNode* PolyNode::GetNextSiblingUp() const +{ + if (!Parent) //protects against PolyTree.GetNextSiblingUp() + return 0; + else if (Index == Parent->Childs.size() - 1) + return Parent->GetNextSiblingUp(); + else + return Parent->Childs[Index + 1]; +} +//------------------------------------------------------------------------------ + +bool PolyNode::IsHole() const +{ + bool result = true; + PolyNode* node = Parent; + while (node) + { + result = !result; + node = node->Parent; + } + return result; +} +//------------------------------------------------------------------------------ + +bool PolyNode::IsOpen() const +{ + return m_IsOpen; +} +//------------------------------------------------------------------------------ + +#ifndef use_int32 + +//------------------------------------------------------------------------------ +// Int128 class (enables safe math on signed 64bit integers) +// eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 +// Int128 val2((long64)9223372036854775807); +// Int128 val3 = val1 * val2; +// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) +//------------------------------------------------------------------------------ + +class Int128 +{ + public: + ulong64 lo; + long64 hi; + + Int128(long64 _lo = 0) + { + lo = (ulong64)_lo; + if (_lo < 0) hi = -1; else hi = 0; + } + + + Int128(const Int128 &val): lo(val.lo), hi(val.hi){} + + Int128(const long64& _hi, const ulong64& _lo): lo(_lo), hi(_hi){} + + Int128& operator = (const long64 &val) + { + lo = (ulong64)val; + if (val < 0) hi = -1; else hi = 0; + return *this; + } + + bool operator == (const Int128 &val) const + {return (hi == val.hi && lo == val.lo);} + + bool operator != (const Int128 &val) const + { return !(*this == val);} + + bool operator > (const Int128 &val) const + { + if (hi != val.hi) + return hi > val.hi; + else + return lo > val.lo; + } + + bool operator < (const Int128 &val) const + { + if (hi != val.hi) + return hi < val.hi; + else + return lo < val.lo; + } + + bool operator >= (const Int128 &val) const + { return !(*this < val);} + + bool operator <= (const Int128 &val) const + { return !(*this > val);} + + Int128& operator += (const Int128 &rhs) + { + hi += rhs.hi; + lo += rhs.lo; + if (lo < rhs.lo) hi++; + return *this; + } + + Int128 operator + (const Int128 &rhs) const + { + Int128 result(*this); + result+= rhs; + return result; + } + + Int128& operator -= (const Int128 &rhs) + { + *this += -rhs; + return *this; + } + + Int128 operator - (const Int128 &rhs) const + { + Int128 result(*this); + result -= rhs; + return result; + } + + Int128 operator-() const //unary negation + { + if (lo == 0) + return Int128(-hi, 0); + else + return Int128(~hi, ~lo + 1); + } + + operator double() const + { + const double shift64 = 18446744073709551616.0; //2^64 + if (hi < 0) + { + if (lo == 0) return (double)hi * shift64; + else return -(double)(~lo + ~hi * shift64); + } + else + return (double)(lo + hi * shift64); + } + +}; +//------------------------------------------------------------------------------ + +Int128 Int128Mul (long64 lhs, long64 rhs) +{ + bool negate = (lhs < 0) != (rhs < 0); + + if (lhs < 0) lhs = -lhs; + ulong64 int1Hi = ulong64(lhs) >> 32; + ulong64 int1Lo = ulong64(lhs & 0xFFFFFFFF); + + if (rhs < 0) rhs = -rhs; + ulong64 int2Hi = ulong64(rhs) >> 32; + ulong64 int2Lo = ulong64(rhs & 0xFFFFFFFF); + + //nb: see comments in clipper.pas + ulong64 a = int1Hi * int2Hi; + ulong64 b = int1Lo * int2Lo; + ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; + + Int128 tmp; + tmp.hi = long64(a + (c >> 32)); + tmp.lo = long64(c << 32); + tmp.lo += long64(b); + if (tmp.lo < b) tmp.hi++; + if (negate) tmp = -tmp; + return tmp; +}; +#endif + +//------------------------------------------------------------------------------ +// Miscellaneous global functions +//------------------------------------------------------------------------------ + +bool Orientation(const Path &poly) +{ + return Area(poly) >= 0; +} +//------------------------------------------------------------------------------ + +double Area(const Path &poly) +{ + int size = (int)poly.size(); + if (size < 3) return 0; + + double a = 0; + for (int i = 0, j = size -1; i < size; ++i) + { + a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); + j = i; + } + return -a * 0.5; +} +//------------------------------------------------------------------------------ + +double Area(const OutPt *op) +{ + const OutPt *startOp = op; + if (!op) return 0; + double a = 0; + do { + a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y); + op = op->Next; + } while (op != startOp); + return a * 0.5; +} +//------------------------------------------------------------------------------ + +double Area(const OutRec &outRec) +{ + return Area(outRec.Pts); +} +//------------------------------------------------------------------------------ + +bool PointIsVertex(const IntPoint &Pt, OutPt *pp) +{ + OutPt *pp2 = pp; + do + { + if (pp2->Pt == Pt) return true; + pp2 = pp2->Next; + } + while (pp2 != pp); + return false; +} +//------------------------------------------------------------------------------ + +//See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos +//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf +int PointInPolygon(const IntPoint &pt, const Path &path) +{ + //returns 0 if false, +1 if true, -1 if pt ON polygon boundary + int result = 0; + size_t cnt = path.size(); + if (cnt < 3) return 0; + IntPoint ip = path[0]; + for(size_t i = 1; i <= cnt; ++i) + { + IntPoint ipNext = (i == cnt ? path[0] : path[i]); + if (ipNext.Y == pt.Y) + { + if ((ipNext.X == pt.X) || (ip.Y == pt.Y && + ((ipNext.X > pt.X) == (ip.X < pt.X)))) return -1; + } + if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) + { + if (ip.X >= pt.X) + { + if (ipNext.X > pt.X) result = 1 - result; + else + { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - + (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; + } + } else + { + if (ipNext.X > pt.X) + { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - + (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; + } + } + } + ip = ipNext; + } + return result; +} +//------------------------------------------------------------------------------ + +int PointInPolygon (const IntPoint &pt, OutPt *op) +{ + //returns 0 if false, +1 if true, -1 if pt ON polygon boundary + int result = 0; + OutPt* startOp = op; + for(;;) + { + if (op->Next->Pt.Y == pt.Y) + { + if ((op->Next->Pt.X == pt.X) || (op->Pt.Y == pt.Y && + ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) return -1; + } + if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y)) + { + if (op->Pt.X >= pt.X) + { + if (op->Next->Pt.X > pt.X) result = 1 - result; + else + { + double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - + (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; + } + } else + { + if (op->Next->Pt.X > pt.X) + { + double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - + (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; + } + } + } + op = op->Next; + if (startOp == op) break; + } + return result; +} +//------------------------------------------------------------------------------ + +bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) +{ + OutPt* op = OutPt1; + do + { + //nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon + int res = PointInPolygon(op->Pt, OutPt2); + if (res >= 0) return res > 0; + op = op->Next; + } + while (op != OutPt1); + return true; +} +//---------------------------------------------------------------------- + +bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range) +{ +#ifndef use_int32 + if (UseFullInt64Range) + return Int128Mul(e1.Top.Y - e1.Bot.Y, e2.Top.X - e2.Bot.X) == + Int128Mul(e1.Top.X - e1.Bot.X, e2.Top.Y - e2.Bot.Y); + else +#endif + return (e1.Top.Y - e1.Bot.Y) * (e2.Top.X - e2.Bot.X) == + (e1.Top.X - e1.Bot.X) * (e2.Top.Y - e2.Bot.Y); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, bool UseFullInt64Range) +{ +#ifndef use_int32 + if (UseFullInt64Range) + return Int128Mul(pt1.Y-pt2.Y, pt2.X-pt3.X) == Int128Mul(pt1.X-pt2.X, pt2.Y-pt3.Y); + else +#endif + return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) +{ +#ifndef use_int32 + if (UseFullInt64Range) + return Int128Mul(pt1.Y-pt2.Y, pt3.X-pt4.X) == Int128Mul(pt1.X-pt2.X, pt3.Y-pt4.Y); + else +#endif + return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); +} +//------------------------------------------------------------------------------ + +inline bool IsHorizontal(TEdge &e) +{ + return e.Dx == HORIZONTAL; +} +//------------------------------------------------------------------------------ + +inline double GetDx(const IntPoint pt1, const IntPoint pt2) +{ + return (pt1.Y == pt2.Y) ? + HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); +} +//--------------------------------------------------------------------------- + +inline void SetDx(TEdge &e) +{ + cInt dy = (e.Top.Y - e.Bot.Y); + if (dy == 0) e.Dx = HORIZONTAL; + else e.Dx = (double)(e.Top.X - e.Bot.X) / dy; +} +//--------------------------------------------------------------------------- + +inline void SwapSides(TEdge &Edge1, TEdge &Edge2) +{ + EdgeSide Side = Edge1.Side; + Edge1.Side = Edge2.Side; + Edge2.Side = Side; +} +//------------------------------------------------------------------------------ + +inline void SwapPolyIndexes(TEdge &Edge1, TEdge &Edge2) +{ + int OutIdx = Edge1.OutIdx; + Edge1.OutIdx = Edge2.OutIdx; + Edge2.OutIdx = OutIdx; +} +//------------------------------------------------------------------------------ + +inline cInt TopX(TEdge &edge, const cInt currentY) +{ + return ( currentY == edge.Top.Y ) ? + edge.Top.X : edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y)); +} +//------------------------------------------------------------------------------ + +void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip) +{ +#ifdef use_xyz + ip.Z = 0; +#endif + + double b1, b2; + if (Edge1.Dx == Edge2.Dx) + { + ip.Y = Edge1.Curr.Y; + ip.X = TopX(Edge1, ip.Y); + return; + } + else if (Edge1.Dx == 0) + { + ip.X = Edge1.Bot.X; + if (IsHorizontal(Edge2)) + ip.Y = Edge2.Bot.Y; + else + { + b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx); + ip.Y = Round(ip.X / Edge2.Dx + b2); + } + } + else if (Edge2.Dx == 0) + { + ip.X = Edge2.Bot.X; + if (IsHorizontal(Edge1)) + ip.Y = Edge1.Bot.Y; + else + { + b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx); + ip.Y = Round(ip.X / Edge1.Dx + b1); + } + } + else + { + b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; + b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; + double q = (b2-b1) / (Edge1.Dx - Edge2.Dx); + ip.Y = Round(q); + if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) + ip.X = Round(Edge1.Dx * q + b1); + else + ip.X = Round(Edge2.Dx * q + b2); + } + + if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y) + { + if (Edge1.Top.Y > Edge2.Top.Y) + ip.Y = Edge1.Top.Y; + else + ip.Y = Edge2.Top.Y; + if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) + ip.X = TopX(Edge1, ip.Y); + else + ip.X = TopX(Edge2, ip.Y); + } + //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ... + if (ip.Y > Edge1.Curr.Y) + { + ip.Y = Edge1.Curr.Y; + //use the more vertical edge to derive X ... + if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx)) + ip.X = TopX(Edge2, ip.Y); else + ip.X = TopX(Edge1, ip.Y); + } +} +//------------------------------------------------------------------------------ + +void ReversePolyPtLinks(OutPt *pp) +{ + if (!pp) return; + OutPt *pp1, *pp2; + pp1 = pp; + do { + pp2 = pp1->Next; + pp1->Next = pp1->Prev; + pp1->Prev = pp2; + pp1 = pp2; + } while( pp1 != pp ); +} +//------------------------------------------------------------------------------ + +void DisposeOutPts(OutPt*& pp) +{ + if (pp == 0) return; + pp->Prev->Next = 0; + while( pp ) + { + OutPt *tmpPp = pp; + pp = pp->Next; + delete tmpPp; + } +} +//------------------------------------------------------------------------------ + +inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt) +{ + std::memset(e, 0, sizeof(TEdge)); + e->Next = eNext; + e->Prev = ePrev; + e->Curr = Pt; + e->OutIdx = Unassigned; +} +//------------------------------------------------------------------------------ + +void InitEdge2(TEdge& e, PolyType Pt) +{ + if (e.Curr.Y >= e.Next->Curr.Y) + { + e.Bot = e.Curr; + e.Top = e.Next->Curr; + } else + { + e.Top = e.Curr; + e.Bot = e.Next->Curr; + } + SetDx(e); + e.PolyTyp = Pt; +} +//------------------------------------------------------------------------------ + +TEdge* RemoveEdge(TEdge* e) +{ + //removes e from double_linked_list (but without removing from memory) + e->Prev->Next = e->Next; + e->Next->Prev = e->Prev; + TEdge* result = e->Next; + e->Prev = 0; //flag as removed (see ClipperBase.Clear) + return result; +} +//------------------------------------------------------------------------------ + +inline void ReverseHorizontal(TEdge &e) +{ + //swap horizontal edges' Top and Bottom x's so they follow the natural + //progression of the bounds - ie so their xbots will align with the + //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] + std::swap(e.Top.X, e.Bot.X); +#ifdef use_xyz + std::swap(e.Top.Z, e.Bot.Z); +#endif +} +//------------------------------------------------------------------------------ + +void SwapPoints(IntPoint &pt1, IntPoint &pt2) +{ + IntPoint tmp = pt1; + pt1 = pt2; + pt2 = tmp; +} +//------------------------------------------------------------------------------ + +bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, + IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) +{ + //precondition: segments are Collinear. + if (Abs(pt1a.X - pt1b.X) > Abs(pt1a.Y - pt1b.Y)) + { + if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); + if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); + if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; + return pt1.X < pt2.X; + } else + { + if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); + if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); + if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; + return pt1.Y > pt2.Y; + } +} +//------------------------------------------------------------------------------ + +bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) +{ + OutPt *p = btmPt1->Prev; + while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Prev; + double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt)); + p = btmPt1->Next; + while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Next; + double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt)); + + p = btmPt2->Prev; + while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Prev; + double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt)); + p = btmPt2->Next; + while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Next; + double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt)); + + if (std::max(dx1p, dx1n) == std::max(dx2p, dx2n) && + std::min(dx1p, dx1n) == std::min(dx2p, dx2n)) + return Area(btmPt1) > 0; //if otherwise identical use orientation + else + return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); +} +//------------------------------------------------------------------------------ + +OutPt* GetBottomPt(OutPt *pp) +{ + OutPt* dups = 0; + OutPt* p = pp->Next; + while (p != pp) + { + if (p->Pt.Y > pp->Pt.Y) + { + pp = p; + dups = 0; + } + else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X) + { + if (p->Pt.X < pp->Pt.X) + { + dups = 0; + pp = p; + } else + { + if (p->Next != pp && p->Prev != pp) dups = p; + } + } + p = p->Next; + } + if (dups) + { + //there appears to be at least 2 vertices at BottomPt so ... + while (dups != p) + { + if (!FirstIsBottomPt(p, dups)) pp = dups; + dups = dups->Next; + while (dups->Pt != pp->Pt) dups = dups->Next; + } + } + return pp; +} +//------------------------------------------------------------------------------ + +bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, + const IntPoint pt2, const IntPoint pt3) +{ + if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) + return false; + else if (pt1.X != pt3.X) + return (pt2.X > pt1.X) == (pt2.X < pt3.X); + else + return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); +} +//------------------------------------------------------------------------------ + +bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b) +{ + if (seg1a > seg1b) std::swap(seg1a, seg1b); + if (seg2a > seg2b) std::swap(seg2a, seg2b); + return (seg1a < seg2b) && (seg2a < seg1b); +} + +//------------------------------------------------------------------------------ +// ClipperBase class methods ... +//------------------------------------------------------------------------------ + +ClipperBase::ClipperBase() //constructor +{ + m_CurrentLM = m_MinimaList.begin(); //begin() == end() here + m_UseFullRange = false; +} +//------------------------------------------------------------------------------ + +ClipperBase::~ClipperBase() //destructor +{ + Clear(); +} +//------------------------------------------------------------------------------ + +void RangeTest(const IntPoint& Pt, bool& useFullRange) +{ + if (useFullRange) + { + if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) + throw clipperException("Coordinate outside allowed range"); + } + else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange) + { + useFullRange = true; + RangeTest(Pt, useFullRange); + } +} +//------------------------------------------------------------------------------ + +TEdge* FindNextLocMin(TEdge* E) +{ + for (;;) + { + while (E->Bot != E->Prev->Bot || E->Curr == E->Top) E = E->Next; + if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) break; + while (IsHorizontal(*E->Prev)) E = E->Prev; + TEdge* E2 = E; + while (IsHorizontal(*E)) E = E->Next; + if (E->Top.Y == E->Prev->Bot.Y) continue; //ie just an intermediate horz. + if (E2->Prev->Bot.X < E->Bot.X) E = E2; + break; + } + return E; +} +//------------------------------------------------------------------------------ + +TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward) +{ + TEdge *Result = E; + TEdge *Horz = 0; + + if (E->OutIdx == Skip) + { + //if edges still remain in the current bound beyond the skip edge then + //create another LocMin and call ProcessBound once more + if (NextIsForward) + { + while (E->Top.Y == E->Next->Bot.Y) E = E->Next; + //don't include top horizontals when parsing a bound a second time, + //they will be contained in the opposite bound ... + while (E != Result && IsHorizontal(*E)) E = E->Prev; + } + else + { + while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev; + while (E != Result && IsHorizontal(*E)) E = E->Next; + } + + if (E == Result) + { + if (NextIsForward) Result = E->Next; + else Result = E->Prev; + } + else + { + //there are more edges in the bound beyond result starting with E + if (NextIsForward) + E = Result->Next; + else + E = Result->Prev; + MinimaList::value_type locMin; + locMin.Y = E->Bot.Y; + locMin.LeftBound = 0; + locMin.RightBound = E; + E->WindDelta = 0; + Result = ProcessBound(E, NextIsForward); + m_MinimaList.push_back(locMin); + } + return Result; + } + + TEdge *EStart; + + if (IsHorizontal(*E)) + { + //We need to be careful with open paths because this may not be a + //true local minima (ie E may be following a skip edge). + //Also, consecutive horz. edges may start heading left before going right. + if (NextIsForward) + EStart = E->Prev; + else + EStart = E->Next; + if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge + { + if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X) + ReverseHorizontal(*E); + } + else if (EStart->Bot.X != E->Bot.X) + ReverseHorizontal(*E); + } + + EStart = E; + if (NextIsForward) + { + while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) + Result = Result->Next; + if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) + { + //nb: at the top of a bound, horizontals are added to the bound + //only when the preceding edge attaches to the horizontal's left vertex + //unless a Skip edge is encountered when that becomes the top divide + Horz = Result; + while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; + if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; + } + while (E != Result) + { + E->NextInLML = E->Next; + if (IsHorizontal(*E) && E != EStart && + E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); + E = E->Next; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) + ReverseHorizontal(*E); + Result = Result->Next; //move to the edge just beyond current bound + } else + { + while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) + Result = Result->Prev; + if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) + { + Horz = Result; + while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; + if (Horz->Next->Top.X == Result->Prev->Top.X || + Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; + } + + while (E != Result) + { + E->NextInLML = E->Prev; + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) + ReverseHorizontal(*E); + E = E->Prev; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) + ReverseHorizontal(*E); + Result = Result->Prev; //move to the edge just beyond current bound + } + + return Result; +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) +{ +#ifdef use_lines + if (!Closed && PolyTyp == ptClip) + throw clipperException("AddPath: Open paths must be subject."); +#else + if (!Closed) + throw clipperException("AddPath: Open paths have been disabled."); +#endif + + int highI = (int)pg.size() -1; + if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI; + while (highI > 0 && (pg[highI] == pg[highI -1])) --highI; + if ((Closed && highI < 2) || (!Closed && highI < 1)) return false; + + //create a new edge array ... + TEdge *edges = new TEdge [highI +1]; + + bool IsFlat = true; + //1. Basic (first) edge initialization ... + try + { + edges[1].Curr = pg[1]; + RangeTest(pg[0], m_UseFullRange); + RangeTest(pg[highI], m_UseFullRange); + InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); + InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]); + for (int i = highI - 1; i >= 1; --i) + { + RangeTest(pg[i], m_UseFullRange); + InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]); + } + } + catch(...) + { + delete [] edges; + throw; //range test fails + } + TEdge *eStart = &edges[0]; + + //2. Remove duplicate vertices, and (when closed) collinear edges ... + TEdge *E = eStart, *eLoopStop = eStart; + for (;;) + { + //nb: allows matching start and end points when not Closed ... + if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart)) + { + if (E == E->Next) break; + if (E == eStart) eStart = E->Next; + E = RemoveEdge(E); + eLoopStop = E; + continue; + } + if (E->Prev == E->Next) + break; //only two vertices + else if (Closed && + SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, m_UseFullRange) && + (!m_PreserveCollinear || + !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr))) + { + //Collinear edges are allowed for open paths but in closed paths + //the default is to merge adjacent collinear edges into a single edge. + //However, if the PreserveCollinear property is enabled, only overlapping + //collinear edges (ie spikes) will be removed from closed paths. + if (E == eStart) eStart = E->Next; + E = RemoveEdge(E); + E = E->Prev; + eLoopStop = E; + continue; + } + E = E->Next; + if ((E == eLoopStop) || (!Closed && E->Next == eStart)) break; + } + + if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) + { + delete [] edges; + return false; + } + + if (!Closed) + { + m_HasOpenPaths = true; + eStart->Prev->OutIdx = Skip; + } + + //3. Do second stage of edge initialization ... + E = eStart; + do + { + InitEdge2(*E, PolyTyp); + E = E->Next; + if (IsFlat && E->Curr.Y != eStart->Curr.Y) IsFlat = false; + } + while (E != eStart); + + //4. Finally, add edge bounds to LocalMinima list ... + + //Totally flat paths must be handled differently when adding them + //to LocalMinima list to avoid endless loops etc ... + if (IsFlat) + { + if (Closed) + { + delete [] edges; + return false; + } + E->Prev->OutIdx = Skip; + MinimaList::value_type locMin; + locMin.Y = E->Bot.Y; + locMin.LeftBound = 0; + locMin.RightBound = E; + locMin.RightBound->Side = esRight; + locMin.RightBound->WindDelta = 0; + for (;;) + { + if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); + if (E->Next->OutIdx == Skip) break; + E->NextInLML = E->Next; + E = E->Next; + } + m_MinimaList.push_back(locMin); + m_edges.push_back(edges); + return true; + } + + m_edges.push_back(edges); + bool leftBoundIsForward; + TEdge* EMin = 0; + + //workaround to avoid an endless loop in the while loop below when + //open paths have matching start and end points ... + if (E->Prev->Bot == E->Prev->Top) E = E->Next; + + for (;;) + { + E = FindNextLocMin(E); + if (E == EMin) break; + else if (!EMin) EMin = E; + + //E and E.Prev now share a local minima (left aligned if horizontal). + //Compare their slopes to find which starts which bound ... + MinimaList::value_type locMin; + locMin.Y = E->Bot.Y; + if (E->Dx < E->Prev->Dx) + { + locMin.LeftBound = E->Prev; + locMin.RightBound = E; + leftBoundIsForward = false; //Q.nextInLML = Q.prev + } else + { + locMin.LeftBound = E; + locMin.RightBound = E->Prev; + leftBoundIsForward = true; //Q.nextInLML = Q.next + } + + if (!Closed) locMin.LeftBound->WindDelta = 0; + else if (locMin.LeftBound->Next == locMin.RightBound) + locMin.LeftBound->WindDelta = -1; + else locMin.LeftBound->WindDelta = 1; + locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta; + + E = ProcessBound(locMin.LeftBound, leftBoundIsForward); + if (E->OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward); + + TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward); + if (E2->OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward); + + if (locMin.LeftBound->OutIdx == Skip) + locMin.LeftBound = 0; + else if (locMin.RightBound->OutIdx == Skip) + locMin.RightBound = 0; + m_MinimaList.push_back(locMin); + if (!leftBoundIsForward) E = E2; + } + return true; +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) +{ + bool result = false; + for (Paths::size_type i = 0; i < ppg.size(); ++i) + if (AddPath(ppg[i], PolyTyp, Closed)) result = true; + return result; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Clear() +{ + DisposeLocalMinimaList(); + for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) + { + TEdge* edges = m_edges[i]; + delete [] edges; + } + m_edges.clear(); + m_UseFullRange = false; + m_HasOpenPaths = false; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Reset() +{ + m_CurrentLM = m_MinimaList.begin(); + if (m_CurrentLM == m_MinimaList.end()) return; //ie nothing to process + std::sort(m_MinimaList.begin(), m_MinimaList.end(), LocMinSorter()); + + m_Scanbeam = ScanbeamList(); //clears/resets priority_queue + //reset all edges ... + for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm) + { + InsertScanbeam(lm->Y); + TEdge* e = lm->LeftBound; + if (e) + { + e->Curr = e->Bot; + e->Side = esLeft; + e->OutIdx = Unassigned; + } + + e = lm->RightBound; + if (e) + { + e->Curr = e->Bot; + e->Side = esRight; + e->OutIdx = Unassigned; + } + } + m_ActiveEdges = 0; + m_CurrentLM = m_MinimaList.begin(); +} +//------------------------------------------------------------------------------ + +void ClipperBase::DisposeLocalMinimaList() +{ + m_MinimaList.clear(); + m_CurrentLM = m_MinimaList.begin(); +} +//------------------------------------------------------------------------------ + +bool ClipperBase::PopLocalMinima(cInt Y, const LocalMinimum *&locMin) +{ + if (m_CurrentLM == m_MinimaList.end() || (*m_CurrentLM).Y != Y) return false; + locMin = &(*m_CurrentLM); + ++m_CurrentLM; + return true; +} +//------------------------------------------------------------------------------ + +IntRect ClipperBase::GetBounds() +{ + IntRect result; + MinimaList::iterator lm = m_MinimaList.begin(); + if (lm == m_MinimaList.end()) + { + result.left = result.top = result.right = result.bottom = 0; + return result; + } + result.left = lm->LeftBound->Bot.X; + result.top = lm->LeftBound->Bot.Y; + result.right = lm->LeftBound->Bot.X; + result.bottom = lm->LeftBound->Bot.Y; + while (lm != m_MinimaList.end()) + { + //todo - needs fixing for open paths + result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y); + TEdge* e = lm->LeftBound; + for (;;) { + TEdge* bottomE = e; + while (e->NextInLML) + { + if (e->Bot.X < result.left) result.left = e->Bot.X; + if (e->Bot.X > result.right) result.right = e->Bot.X; + e = e->NextInLML; + } + result.left = std::min(result.left, e->Bot.X); + result.right = std::max(result.right, e->Bot.X); + result.left = std::min(result.left, e->Top.X); + result.right = std::max(result.right, e->Top.X); + result.top = std::min(result.top, e->Top.Y); + if (bottomE == lm->LeftBound) e = lm->RightBound; + else break; + } + ++lm; + } + return result; +} +//------------------------------------------------------------------------------ + +void ClipperBase::InsertScanbeam(const cInt Y) +{ + m_Scanbeam.push(Y); +} +//------------------------------------------------------------------------------ + +bool ClipperBase::PopScanbeam(cInt &Y) +{ + if (m_Scanbeam.empty()) return false; + Y = m_Scanbeam.top(); + m_Scanbeam.pop(); + while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { m_Scanbeam.pop(); } // Pop duplicates. + return true; +} +//------------------------------------------------------------------------------ + +void ClipperBase::DisposeAllOutRecs(){ + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + DisposeOutRec(i); + m_PolyOuts.clear(); +} +//------------------------------------------------------------------------------ + +void ClipperBase::DisposeOutRec(PolyOutList::size_type index) +{ + OutRec *outRec = m_PolyOuts[index]; + if (outRec->Pts) DisposeOutPts(outRec->Pts); + delete outRec; + m_PolyOuts[index] = 0; +} +//------------------------------------------------------------------------------ + +void ClipperBase::DeleteFromAEL(TEdge *e) +{ + TEdge* AelPrev = e->PrevInAEL; + TEdge* AelNext = e->NextInAEL; + if (!AelPrev && !AelNext && (e != m_ActiveEdges)) return; //already deleted + if (AelPrev) AelPrev->NextInAEL = AelNext; + else m_ActiveEdges = AelNext; + if (AelNext) AelNext->PrevInAEL = AelPrev; + e->NextInAEL = 0; + e->PrevInAEL = 0; +} +//------------------------------------------------------------------------------ + +OutRec* ClipperBase::CreateOutRec() +{ + OutRec* result = new OutRec; + result->IsHole = false; + result->IsOpen = false; + result->FirstLeft = 0; + result->Pts = 0; + result->BottomPt = 0; + result->PolyNd = 0; + m_PolyOuts.push_back(result); + result->Idx = (int)m_PolyOuts.size() - 1; + return result; +} +//------------------------------------------------------------------------------ + +void ClipperBase::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2) +{ + //check that one or other edge hasn't already been removed from AEL ... + if (Edge1->NextInAEL == Edge1->PrevInAEL || + Edge2->NextInAEL == Edge2->PrevInAEL) return; + + if (Edge1->NextInAEL == Edge2) + { + TEdge* Next = Edge2->NextInAEL; + if (Next) Next->PrevInAEL = Edge1; + TEdge* Prev = Edge1->PrevInAEL; + if (Prev) Prev->NextInAEL = Edge2; + Edge2->PrevInAEL = Prev; + Edge2->NextInAEL = Edge1; + Edge1->PrevInAEL = Edge2; + Edge1->NextInAEL = Next; + } + else if (Edge2->NextInAEL == Edge1) + { + TEdge* Next = Edge1->NextInAEL; + if (Next) Next->PrevInAEL = Edge2; + TEdge* Prev = Edge2->PrevInAEL; + if (Prev) Prev->NextInAEL = Edge1; + Edge1->PrevInAEL = Prev; + Edge1->NextInAEL = Edge2; + Edge2->PrevInAEL = Edge1; + Edge2->NextInAEL = Next; + } + else + { + TEdge* Next = Edge1->NextInAEL; + TEdge* Prev = Edge1->PrevInAEL; + Edge1->NextInAEL = Edge2->NextInAEL; + if (Edge1->NextInAEL) Edge1->NextInAEL->PrevInAEL = Edge1; + Edge1->PrevInAEL = Edge2->PrevInAEL; + if (Edge1->PrevInAEL) Edge1->PrevInAEL->NextInAEL = Edge1; + Edge2->NextInAEL = Next; + if (Edge2->NextInAEL) Edge2->NextInAEL->PrevInAEL = Edge2; + Edge2->PrevInAEL = Prev; + if (Edge2->PrevInAEL) Edge2->PrevInAEL->NextInAEL = Edge2; + } + + if (!Edge1->PrevInAEL) m_ActiveEdges = Edge1; + else if (!Edge2->PrevInAEL) m_ActiveEdges = Edge2; +} +//------------------------------------------------------------------------------ + +void ClipperBase::UpdateEdgeIntoAEL(TEdge *&e) +{ + if (!e->NextInLML) + throw clipperException("UpdateEdgeIntoAEL: invalid call"); + + e->NextInLML->OutIdx = e->OutIdx; + TEdge* AelPrev = e->PrevInAEL; + TEdge* AelNext = e->NextInAEL; + if (AelPrev) AelPrev->NextInAEL = e->NextInLML; + else m_ActiveEdges = e->NextInLML; + if (AelNext) AelNext->PrevInAEL = e->NextInLML; + e->NextInLML->Side = e->Side; + e->NextInLML->WindDelta = e->WindDelta; + e->NextInLML->WindCnt = e->WindCnt; + e->NextInLML->WindCnt2 = e->WindCnt2; + e = e->NextInLML; + e->Curr = e->Bot; + e->PrevInAEL = AelPrev; + e->NextInAEL = AelNext; + if (!IsHorizontal(*e)) InsertScanbeam(e->Top.Y); +} +//------------------------------------------------------------------------------ + +bool ClipperBase::LocalMinimaPending() +{ + return (m_CurrentLM != m_MinimaList.end()); +} + +//------------------------------------------------------------------------------ +// TClipper methods ... +//------------------------------------------------------------------------------ + +Clipper::Clipper(int initOptions) : ClipperBase() //constructor +{ + m_ExecuteLocked = false; + m_UseFullRange = false; + m_ReverseOutput = ((initOptions & ioReverseSolution) != 0); + m_StrictSimple = ((initOptions & ioStrictlySimple) != 0); + m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0); + m_HasOpenPaths = false; +#ifdef use_xyz + m_ZFill = 0; +#endif +} +//------------------------------------------------------------------------------ + +#ifdef use_xyz +void Clipper::ZFillFunction(ZFillCallback zFillFunc) +{ + m_ZFill = zFillFunc; +} +//------------------------------------------------------------------------------ +#endif + +bool Clipper::Execute(ClipType clipType, Paths &solution, PolyFillType fillType) +{ + return Execute(clipType, solution, fillType, fillType); +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, PolyTree &polytree, PolyFillType fillType) +{ + return Execute(clipType, polytree, fillType, fillType); +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, Paths &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + if (m_HasOpenPaths) + throw clipperException("Error: PolyTree struct is needed for open path clipping."); + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = false; + bool succeeded = ExecuteInternal(); + if (succeeded) BuildResult(solution); + DisposeAllOutRecs(); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, PolyTree& polytree, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + m_ExecuteLocked = true; + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = true; + bool succeeded = ExecuteInternal(); + if (succeeded) BuildResult2(polytree); + DisposeAllOutRecs(); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +void Clipper::FixHoleLinkage(OutRec &outrec) +{ + //skip OutRecs that (a) contain outermost polygons or + //(b) already have the correct owner/child linkage ... + if (!outrec.FirstLeft || + (outrec.IsHole != outrec.FirstLeft->IsHole && + outrec.FirstLeft->Pts)) return; + + OutRec* orfl = outrec.FirstLeft; + while (orfl && ((orfl->IsHole == outrec.IsHole) || !orfl->Pts)) + orfl = orfl->FirstLeft; + outrec.FirstLeft = orfl; +} +//------------------------------------------------------------------------------ + +bool Clipper::ExecuteInternal() +{ + bool succeeded = true; + try { + Reset(); + m_Maxima = MaximaList(); + m_SortedEdges = 0; + + succeeded = true; + cInt botY, topY; + if (!PopScanbeam(botY)) return false; + InsertLocalMinimaIntoAEL(botY); + while (PopScanbeam(topY) || LocalMinimaPending()) + { + ProcessHorizontals(); + ClearGhostJoins(); + if (!ProcessIntersections(topY)) + { + succeeded = false; + break; + } + ProcessEdgesAtTopOfScanbeam(topY); + botY = topY; + InsertLocalMinimaIntoAEL(botY); + } + } + catch(...) + { + succeeded = false; + } + + if (succeeded) + { + //fix orientations ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *outRec = m_PolyOuts[i]; + if (!outRec->Pts || outRec->IsOpen) continue; + if ((outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) + ReversePolyPtLinks(outRec->Pts); + } + + if (!m_Joins.empty()) JoinCommonEdges(); + + //unfortunately FixupOutPolygon() must be done after JoinCommonEdges() + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *outRec = m_PolyOuts[i]; + if (!outRec->Pts) continue; + if (outRec->IsOpen) + FixupOutPolyline(*outRec); + else + FixupOutPolygon(*outRec); + } + + if (m_StrictSimple) DoSimplePolygons(); + } + + ClearJoins(); + ClearGhostJoins(); + return succeeded; +} +//------------------------------------------------------------------------------ + +void Clipper::SetWindingCount(TEdge &edge) +{ + TEdge *e = edge.PrevInAEL; + //find the edge of the same polytype that immediately preceeds 'edge' in AEL + while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) e = e->PrevInAEL; + if (!e) + { + if (edge.WindDelta == 0) + { + PolyFillType pft = (edge.PolyTyp == ptSubject ? m_SubjFillType : m_ClipFillType); + edge.WindCnt = (pft == pftNegative ? -1 : 1); + } + else + edge.WindCnt = edge.WindDelta; + edge.WindCnt2 = 0; + e = m_ActiveEdges; //ie get ready to calc WindCnt2 + } + else if (edge.WindDelta == 0 && m_ClipType != ctUnion) + { + edge.WindCnt = 1; + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + else if (IsEvenOddFillType(edge)) + { + //EvenOdd filling ... + if (edge.WindDelta == 0) + { + //are we inside a subj polygon ... + bool Inside = true; + TEdge *e2 = e->PrevInAEL; + while (e2) + { + if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0) + Inside = !Inside; + e2 = e2->PrevInAEL; + } + edge.WindCnt = (Inside ? 0 : 1); + } + else + { + edge.WindCnt = edge.WindDelta; + } + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + else + { + //nonZero, Positive or Negative filling ... + if (e->WindCnt * e->WindDelta < 0) + { + //prev edge is 'decreasing' WindCount (WC) toward zero + //so we're outside the previous polygon ... + if (Abs(e->WindCnt) > 1) + { + //outside prev poly but still inside another. + //when reversing direction of prev poly use the same WC + if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; + //otherwise continue to 'decrease' WC ... + else edge.WindCnt = e->WindCnt + edge.WindDelta; + } + else + //now outside all polys of same polytype so set own WC ... + edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); + } else + { + //prev edge is 'increasing' WindCount (WC) away from zero + //so we're inside the previous polygon ... + if (edge.WindDelta == 0) + edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1); + //if wind direction is reversing prev then use same WC + else if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; + //otherwise add to WC ... + else edge.WindCnt = e->WindCnt + edge.WindDelta; + } + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + + //update WindCnt2 ... + if (IsEvenOddAltFillType(edge)) + { + //EvenOdd filling ... + while (e != &edge) + { + if (e->WindDelta != 0) + edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); + e = e->NextInAEL; + } + } else + { + //nonZero, Positive or Negative filling ... + while ( e != &edge ) + { + edge.WindCnt2 += e->WindDelta; + e = e->NextInAEL; + } + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddFillType(const TEdge& edge) const +{ + if (edge.PolyTyp == ptSubject) + return m_SubjFillType == pftEvenOdd; else + return m_ClipFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const +{ + if (edge.PolyTyp == ptSubject) + return m_ClipFillType == pftEvenOdd; else + return m_SubjFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsContributing(const TEdge& edge) const +{ + PolyFillType pft, pft2; + if (edge.PolyTyp == ptSubject) + { + pft = m_SubjFillType; + pft2 = m_ClipFillType; + } else + { + pft = m_ClipFillType; + pft2 = m_SubjFillType; + } + + switch(pft) + { + case pftEvenOdd: + //return false if a subj line has been flagged as inside a subj polygon + if (edge.WindDelta == 0 && edge.WindCnt != 1) return false; + break; + case pftNonZero: + if (Abs(edge.WindCnt) != 1) return false; + break; + case pftPositive: + if (edge.WindCnt != 1) return false; + break; + default: //pftNegative + if (edge.WindCnt != -1) return false; + } + + switch(m_ClipType) + { + case ctIntersection: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 != 0); + case pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + break; + case ctUnion: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + break; + case ctDifference: + if (edge.PolyTyp == ptSubject) + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + else + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 != 0); + case pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + break; + case ctXor: + if (edge.WindDelta == 0) //XOr always contributing unless open + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + else + return true; + break; + default: + return true; + } +} +//------------------------------------------------------------------------------ + +OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) +{ + OutPt* result; + TEdge *e, *prevE; + if (IsHorizontal(*e2) || ( e1->Dx > e2->Dx )) + { + result = AddOutPt(e1, Pt); + e2->OutIdx = e1->OutIdx; + e1->Side = esLeft; + e2->Side = esRight; + e = e1; + if (e->PrevInAEL == e2) + prevE = e2->PrevInAEL; + else + prevE = e->PrevInAEL; + } else + { + result = AddOutPt(e2, Pt); + e1->OutIdx = e2->OutIdx; + e1->Side = esRight; + e2->Side = esLeft; + e = e2; + if (e->PrevInAEL == e1) + prevE = e1->PrevInAEL; + else + prevE = e->PrevInAEL; + } + + if (prevE && prevE->OutIdx >= 0 && prevE->Top.Y < Pt.Y && e->Top.Y < Pt.Y) + { + cInt xPrev = TopX(*prevE, Pt.Y); + cInt xE = TopX(*e, Pt.Y); + if (xPrev == xE && (e->WindDelta != 0) && (prevE->WindDelta != 0) && + SlopesEqual(IntPoint(xPrev, Pt.Y), prevE->Top, IntPoint(xE, Pt.Y), e->Top, m_UseFullRange)) + { + OutPt* outPt = AddOutPt(prevE, Pt); + AddJoin(result, outPt, e->Top); + } + } + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) +{ + AddOutPt( e1, Pt ); + if (e2->WindDelta == 0) AddOutPt(e2, Pt); + if( e1->OutIdx == e2->OutIdx ) + { + e1->OutIdx = Unassigned; + e2->OutIdx = Unassigned; + } + else if (e1->OutIdx < e2->OutIdx) + AppendPolygon(e1, e2); + else + AppendPolygon(e2, e1); +} +//------------------------------------------------------------------------------ + +void Clipper::AddEdgeToSEL(TEdge *edge) +{ + //SEL pointers in PEdge are reused to build a list of horizontal edges. + //However, we don't need to worry about order with horizontal edge processing. + if( !m_SortedEdges ) + { + m_SortedEdges = edge; + edge->PrevInSEL = 0; + edge->NextInSEL = 0; + } + else + { + edge->NextInSEL = m_SortedEdges; + edge->PrevInSEL = 0; + m_SortedEdges->PrevInSEL = edge; + m_SortedEdges = edge; + } +} +//------------------------------------------------------------------------------ + +bool Clipper::PopEdgeFromSEL(TEdge *&edge) +{ + if (!m_SortedEdges) return false; + edge = m_SortedEdges; + DeleteFromSEL(m_SortedEdges); + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::CopyAELToSEL() +{ + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + while ( e ) + { + e->PrevInSEL = e->PrevInAEL; + e->NextInSEL = e->NextInAEL; + e = e->NextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddJoin(OutPt *op1, OutPt *op2, const IntPoint OffPt) +{ + Join* j = new Join; + j->OutPt1 = op1; + j->OutPt2 = op2; + j->OffPt = OffPt; + m_Joins.push_back(j); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearJoins() +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + delete m_Joins[i]; + m_Joins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearGhostJoins() +{ + for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++) + delete m_GhostJoins[i]; + m_GhostJoins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt) +{ + Join* j = new Join; + j->OutPt1 = op; + j->OutPt2 = 0; + j->OffPt = OffPt; + m_GhostJoins.push_back(j); +} +//------------------------------------------------------------------------------ + +void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) +{ + const LocalMinimum *lm; + while (PopLocalMinima(botY, lm)) + { + TEdge* lb = lm->LeftBound; + TEdge* rb = lm->RightBound; + + OutPt *Op1 = 0; + if (!lb) + { + //nb: don't insert LB into either AEL or SEL + InsertEdgeIntoAEL(rb, 0); + SetWindingCount(*rb); + if (IsContributing(*rb)) + Op1 = AddOutPt(rb, rb->Bot); + } + else if (!rb) + { + InsertEdgeIntoAEL(lb, 0); + SetWindingCount(*lb); + if (IsContributing(*lb)) + Op1 = AddOutPt(lb, lb->Bot); + InsertScanbeam(lb->Top.Y); + } + else + { + InsertEdgeIntoAEL(lb, 0); + InsertEdgeIntoAEL(rb, lb); + SetWindingCount( *lb ); + rb->WindCnt = lb->WindCnt; + rb->WindCnt2 = lb->WindCnt2; + if (IsContributing(*lb)) + Op1 = AddLocalMinPoly(lb, rb, lb->Bot); + InsertScanbeam(lb->Top.Y); + } + + if (rb) + { + if (IsHorizontal(*rb)) + { + AddEdgeToSEL(rb); + if (rb->NextInLML) + InsertScanbeam(rb->NextInLML->Top.Y); + } + else InsertScanbeam( rb->Top.Y ); + } + + if (!lb || !rb) continue; + + //if any output polygons share an edge, they'll need joining later ... + if (Op1 && IsHorizontal(*rb) && + m_GhostJoins.size() > 0 && (rb->WindDelta != 0)) + { + for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i) + { + Join* jr = m_GhostJoins[i]; + //if the horizontal Rb and a 'ghost' horizontal overlap, then convert + //the 'ghost' join to a real join ready for later ... + if (HorzSegmentsOverlap(jr->OutPt1->Pt.X, jr->OffPt.X, rb->Bot.X, rb->Top.X)) + AddJoin(jr->OutPt1, Op1, jr->OffPt); + } + } + + if (lb->OutIdx >= 0 && lb->PrevInAEL && + lb->PrevInAEL->Curr.X == lb->Bot.X && + lb->PrevInAEL->OutIdx >= 0 && + SlopesEqual(lb->PrevInAEL->Bot, lb->PrevInAEL->Top, lb->Curr, lb->Top, m_UseFullRange) && + (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0)) + { + OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot); + AddJoin(Op1, Op2, lb->Top); + } + + if(lb->NextInAEL != rb) + { + + if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 && + SlopesEqual(rb->PrevInAEL->Curr, rb->PrevInAEL->Top, rb->Curr, rb->Top, m_UseFullRange) && + (rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0)) + { + OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot); + AddJoin(Op1, Op2, rb->Top); + } + + TEdge* e = lb->NextInAEL; + if (e) + { + while( e != rb ) + { + //nb: For calculating winding counts etc, IntersectEdges() assumes + //that param1 will be to the Right of param2 ABOVE the intersection ... + IntersectEdges(rb , e , lb->Curr); //order important here + e = e->NextInAEL; + } + } + } + + } +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromSEL(TEdge *e) +{ + TEdge* SelPrev = e->PrevInSEL; + TEdge* SelNext = e->NextInSEL; + if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted + if( SelPrev ) SelPrev->NextInSEL = SelNext; + else m_SortedEdges = SelNext; + if( SelNext ) SelNext->PrevInSEL = SelPrev; + e->NextInSEL = 0; + e->PrevInSEL = 0; +} +//------------------------------------------------------------------------------ + +#ifdef use_xyz +void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2) +{ + if (pt.Z != 0 || !m_ZFill) return; + else if (pt == e1.Bot) pt.Z = e1.Bot.Z; + else if (pt == e1.Top) pt.Z = e1.Top.Z; + else if (pt == e2.Bot) pt.Z = e2.Bot.Z; + else if (pt == e2.Top) pt.Z = e2.Top.Z; + else (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt); +} +//------------------------------------------------------------------------------ +#endif + +void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt) +{ + bool e1Contributing = ( e1->OutIdx >= 0 ); + bool e2Contributing = ( e2->OutIdx >= 0 ); + +#ifdef use_xyz + SetZ(Pt, *e1, *e2); +#endif + +#ifdef use_lines + //if either edge is on an OPEN path ... + if (e1->WindDelta == 0 || e2->WindDelta == 0) + { + //ignore subject-subject open path intersections UNLESS they + //are both open paths, AND they are both 'contributing maximas' ... + if (e1->WindDelta == 0 && e2->WindDelta == 0) return; + + //if intersecting a subj line with a subj poly ... + else if (e1->PolyTyp == e2->PolyTyp && + e1->WindDelta != e2->WindDelta && m_ClipType == ctUnion) + { + if (e1->WindDelta == 0) + { + if (e2Contributing) + { + AddOutPt(e1, Pt); + if (e1Contributing) e1->OutIdx = Unassigned; + } + } + else + { + if (e1Contributing) + { + AddOutPt(e2, Pt); + if (e2Contributing) e2->OutIdx = Unassigned; + } + } + } + else if (e1->PolyTyp != e2->PolyTyp) + { + //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... + if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 && + (m_ClipType != ctUnion || e2->WindCnt2 == 0)) + { + AddOutPt(e1, Pt); + if (e1Contributing) e1->OutIdx = Unassigned; + } + else if ((e2->WindDelta == 0) && (abs(e1->WindCnt) == 1) && + (m_ClipType != ctUnion || e1->WindCnt2 == 0)) + { + AddOutPt(e2, Pt); + if (e2Contributing) e2->OutIdx = Unassigned; + } + } + return; + } +#endif + + //update winding counts... + //assumes that e1 will be to the Right of e2 ABOVE the intersection + if ( e1->PolyTyp == e2->PolyTyp ) + { + if ( IsEvenOddFillType( *e1) ) + { + int oldE1WindCnt = e1->WindCnt; + e1->WindCnt = e2->WindCnt; + e2->WindCnt = oldE1WindCnt; + } else + { + if (e1->WindCnt + e2->WindDelta == 0 ) e1->WindCnt = -e1->WindCnt; + else e1->WindCnt += e2->WindDelta; + if ( e2->WindCnt - e1->WindDelta == 0 ) e2->WindCnt = -e2->WindCnt; + else e2->WindCnt -= e1->WindDelta; + } + } else + { + if (!IsEvenOddFillType(*e2)) e1->WindCnt2 += e2->WindDelta; + else e1->WindCnt2 = ( e1->WindCnt2 == 0 ) ? 1 : 0; + if (!IsEvenOddFillType(*e1)) e2->WindCnt2 -= e1->WindDelta; + else e2->WindCnt2 = ( e2->WindCnt2 == 0 ) ? 1 : 0; + } + + PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; + if (e1->PolyTyp == ptSubject) + { + e1FillType = m_SubjFillType; + e1FillType2 = m_ClipFillType; + } else + { + e1FillType = m_ClipFillType; + e1FillType2 = m_SubjFillType; + } + if (e2->PolyTyp == ptSubject) + { + e2FillType = m_SubjFillType; + e2FillType2 = m_ClipFillType; + } else + { + e2FillType = m_ClipFillType; + e2FillType2 = m_SubjFillType; + } + + cInt e1Wc, e2Wc; + switch (e1FillType) + { + case pftPositive: e1Wc = e1->WindCnt; break; + case pftNegative: e1Wc = -e1->WindCnt; break; + default: e1Wc = Abs(e1->WindCnt); + } + switch(e2FillType) + { + case pftPositive: e2Wc = e2->WindCnt; break; + case pftNegative: e2Wc = -e2->WindCnt; break; + default: e2Wc = Abs(e2->WindCnt); + } + + if ( e1Contributing && e2Contributing ) + { + if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || + (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) ) + { + AddLocalMaxPoly(e1, e2, Pt); + } + else + { + AddOutPt(e1, Pt); + AddOutPt(e2, Pt); + SwapSides( *e1 , *e2 ); + SwapPolyIndexes( *e1 , *e2 ); + } + } + else if ( e1Contributing ) + { + if (e2Wc == 0 || e2Wc == 1) + { + AddOutPt(e1, Pt); + SwapSides(*e1, *e2); + SwapPolyIndexes(*e1, *e2); + } + } + else if ( e2Contributing ) + { + if (e1Wc == 0 || e1Wc == 1) + { + AddOutPt(e2, Pt); + SwapSides(*e1, *e2); + SwapPolyIndexes(*e1, *e2); + } + } + else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1)) + { + //neither edge is currently contributing ... + + cInt e1Wc2, e2Wc2; + switch (e1FillType2) + { + case pftPositive: e1Wc2 = e1->WindCnt2; break; + case pftNegative : e1Wc2 = -e1->WindCnt2; break; + default: e1Wc2 = Abs(e1->WindCnt2); + } + switch (e2FillType2) + { + case pftPositive: e2Wc2 = e2->WindCnt2; break; + case pftNegative: e2Wc2 = -e2->WindCnt2; break; + default: e2Wc2 = Abs(e2->WindCnt2); + } + + if (e1->PolyTyp != e2->PolyTyp) + { + AddLocalMinPoly(e1, e2, Pt); + } + else if (e1Wc == 1 && e2Wc == 1) + switch( m_ClipType ) { + case ctIntersection: + if (e1Wc2 > 0 && e2Wc2 > 0) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctUnion: + if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctDifference: + if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || + ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctXor: + AddLocalMinPoly(e1, e2, Pt); + } + else + SwapSides( *e1, *e2 ); + } +} +//------------------------------------------------------------------------------ + +void Clipper::SetHoleState(TEdge *e, OutRec *outrec) +{ + TEdge *e2 = e->PrevInAEL; + TEdge *eTmp = 0; + while (e2) + { + if (e2->OutIdx >= 0 && e2->WindDelta != 0) + { + if (!eTmp) eTmp = e2; + else if (eTmp->OutIdx == e2->OutIdx) eTmp = 0; + } + e2 = e2->PrevInAEL; + } + if (!eTmp) + { + outrec->FirstLeft = 0; + outrec->IsHole = false; + } + else + { + outrec->FirstLeft = m_PolyOuts[eTmp->OutIdx]; + outrec->IsHole = !outrec->FirstLeft->IsHole; + } +} +//------------------------------------------------------------------------------ + +OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) +{ + //work out which polygon fragment has the correct hole state ... + if (!outRec1->BottomPt) + outRec1->BottomPt = GetBottomPt(outRec1->Pts); + if (!outRec2->BottomPt) + outRec2->BottomPt = GetBottomPt(outRec2->Pts); + OutPt *OutPt1 = outRec1->BottomPt; + OutPt *OutPt2 = outRec2->BottomPt; + if (OutPt1->Pt.Y > OutPt2->Pt.Y) return outRec1; + else if (OutPt1->Pt.Y < OutPt2->Pt.Y) return outRec2; + else if (OutPt1->Pt.X < OutPt2->Pt.X) return outRec1; + else if (OutPt1->Pt.X > OutPt2->Pt.X) return outRec2; + else if (OutPt1->Next == OutPt1) return outRec2; + else if (OutPt2->Next == OutPt2) return outRec1; + else if (FirstIsBottomPt(OutPt1, OutPt2)) return outRec1; + else return outRec2; +} +//------------------------------------------------------------------------------ + +bool OutRec1RightOfOutRec2(OutRec* outRec1, OutRec* outRec2) +{ + do + { + outRec1 = outRec1->FirstLeft; + if (outRec1 == outRec2) return true; + } while (outRec1); + return false; +} +//------------------------------------------------------------------------------ + +OutRec* Clipper::GetOutRec(int Idx) +{ + OutRec* outrec = m_PolyOuts[Idx]; + while (outrec != m_PolyOuts[outrec->Idx]) + outrec = m_PolyOuts[outrec->Idx]; + return outrec; +} +//------------------------------------------------------------------------------ + +void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) +{ + //get the start and ends of both output polygons ... + OutRec *outRec1 = m_PolyOuts[e1->OutIdx]; + OutRec *outRec2 = m_PolyOuts[e2->OutIdx]; + + OutRec *holeStateRec; + if (OutRec1RightOfOutRec2(outRec1, outRec2)) + holeStateRec = outRec2; + else if (OutRec1RightOfOutRec2(outRec2, outRec1)) + holeStateRec = outRec1; + else + holeStateRec = GetLowermostRec(outRec1, outRec2); + + //get the start and ends of both output polygons and + //join e2 poly onto e1 poly and delete pointers to e2 ... + + OutPt* p1_lft = outRec1->Pts; + OutPt* p1_rt = p1_lft->Prev; + OutPt* p2_lft = outRec2->Pts; + OutPt* p2_rt = p2_lft->Prev; + + //join e2 poly onto e1 poly and delete pointers to e2 ... + if( e1->Side == esLeft ) + { + if( e2->Side == esLeft ) + { + //z y x a b c + ReversePolyPtLinks(p2_lft); + p2_lft->Next = p1_lft; + p1_lft->Prev = p2_lft; + p1_rt->Next = p2_rt; + p2_rt->Prev = p1_rt; + outRec1->Pts = p2_rt; + } else + { + //x y z a b c + p2_rt->Next = p1_lft; + p1_lft->Prev = p2_rt; + p2_lft->Prev = p1_rt; + p1_rt->Next = p2_lft; + outRec1->Pts = p2_lft; + } + } else + { + if( e2->Side == esRight ) + { + //a b c z y x + ReversePolyPtLinks(p2_lft); + p1_rt->Next = p2_rt; + p2_rt->Prev = p1_rt; + p2_lft->Next = p1_lft; + p1_lft->Prev = p2_lft; + } else + { + //a b c x y z + p1_rt->Next = p2_lft; + p2_lft->Prev = p1_rt; + p1_lft->Prev = p2_rt; + p2_rt->Next = p1_lft; + } + } + + outRec1->BottomPt = 0; + if (holeStateRec == outRec2) + { + if (outRec2->FirstLeft != outRec1) + outRec1->FirstLeft = outRec2->FirstLeft; + outRec1->IsHole = outRec2->IsHole; + } + outRec2->Pts = 0; + outRec2->BottomPt = 0; + outRec2->FirstLeft = outRec1; + + int OKIdx = e1->OutIdx; + int ObsoleteIdx = e2->OutIdx; + + e1->OutIdx = Unassigned; //nb: safe because we only get here via AddLocalMaxPoly + e2->OutIdx = Unassigned; + + TEdge* e = m_ActiveEdges; + while( e ) + { + if( e->OutIdx == ObsoleteIdx ) + { + e->OutIdx = OKIdx; + e->Side = e1->Side; + break; + } + e = e->NextInAEL; + } + + outRec2->Idx = outRec1->Idx; +} +//------------------------------------------------------------------------------ + +OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt) +{ + if( e->OutIdx < 0 ) + { + OutRec *outRec = CreateOutRec(); + outRec->IsOpen = (e->WindDelta == 0); + OutPt* newOp = new OutPt; + outRec->Pts = newOp; + newOp->Idx = outRec->Idx; + newOp->Pt = pt; + newOp->Next = newOp; + newOp->Prev = newOp; + if (!outRec->IsOpen) + SetHoleState(e, outRec); + e->OutIdx = outRec->Idx; + return newOp; + } else + { + OutRec *outRec = m_PolyOuts[e->OutIdx]; + //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' + OutPt* op = outRec->Pts; + + bool ToFront = (e->Side == esLeft); + if (ToFront && (pt == op->Pt)) return op; + else if (!ToFront && (pt == op->Prev->Pt)) return op->Prev; + + OutPt* newOp = new OutPt; + newOp->Idx = outRec->Idx; + newOp->Pt = pt; + newOp->Next = op; + newOp->Prev = op->Prev; + newOp->Prev->Next = newOp; + op->Prev = newOp; + if (ToFront) outRec->Pts = newOp; + return newOp; + } +} +//------------------------------------------------------------------------------ + +OutPt* Clipper::GetLastOutPt(TEdge *e) +{ + OutRec *outRec = m_PolyOuts[e->OutIdx]; + if (e->Side == esLeft) + return outRec->Pts; + else + return outRec->Pts->Prev; +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontals() +{ + TEdge* horzEdge; + while (PopEdgeFromSEL(horzEdge)) + ProcessHorizontal(horzEdge); +} +//------------------------------------------------------------------------------ + +inline bool IsMinima(TEdge *e) +{ + return e && (e->Prev->NextInLML != e) && (e->Next->NextInLML != e); +} +//------------------------------------------------------------------------------ + +inline bool IsMaxima(TEdge *e, const cInt Y) +{ + return e && e->Top.Y == Y && !e->NextInLML; +} +//------------------------------------------------------------------------------ + +inline bool IsIntermediate(TEdge *e, const cInt Y) +{ + return e->Top.Y == Y && e->NextInLML; +} +//------------------------------------------------------------------------------ + +TEdge *GetMaximaPair(TEdge *e) +{ + if ((e->Next->Top == e->Top) && !e->Next->NextInLML) + return e->Next; + else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML) + return e->Prev; + else return 0; +} +//------------------------------------------------------------------------------ + +TEdge *GetMaximaPairEx(TEdge *e) +{ + //as GetMaximaPair() but returns 0 if MaxPair isn't in AEL (unless it's horizontal) + TEdge* result = GetMaximaPair(e); + if (result && (result->OutIdx == Skip || + (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) return 0; + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2) +{ + if( !( Edge1->NextInSEL ) && !( Edge1->PrevInSEL ) ) return; + if( !( Edge2->NextInSEL ) && !( Edge2->PrevInSEL ) ) return; + + if( Edge1->NextInSEL == Edge2 ) + { + TEdge* Next = Edge2->NextInSEL; + if( Next ) Next->PrevInSEL = Edge1; + TEdge* Prev = Edge1->PrevInSEL; + if( Prev ) Prev->NextInSEL = Edge2; + Edge2->PrevInSEL = Prev; + Edge2->NextInSEL = Edge1; + Edge1->PrevInSEL = Edge2; + Edge1->NextInSEL = Next; + } + else if( Edge2->NextInSEL == Edge1 ) + { + TEdge* Next = Edge1->NextInSEL; + if( Next ) Next->PrevInSEL = Edge2; + TEdge* Prev = Edge2->PrevInSEL; + if( Prev ) Prev->NextInSEL = Edge1; + Edge1->PrevInSEL = Prev; + Edge1->NextInSEL = Edge2; + Edge2->PrevInSEL = Edge1; + Edge2->NextInSEL = Next; + } + else + { + TEdge* Next = Edge1->NextInSEL; + TEdge* Prev = Edge1->PrevInSEL; + Edge1->NextInSEL = Edge2->NextInSEL; + if( Edge1->NextInSEL ) Edge1->NextInSEL->PrevInSEL = Edge1; + Edge1->PrevInSEL = Edge2->PrevInSEL; + if( Edge1->PrevInSEL ) Edge1->PrevInSEL->NextInSEL = Edge1; + Edge2->NextInSEL = Next; + if( Edge2->NextInSEL ) Edge2->NextInSEL->PrevInSEL = Edge2; + Edge2->PrevInSEL = Prev; + if( Edge2->PrevInSEL ) Edge2->PrevInSEL->NextInSEL = Edge2; + } + + if( !Edge1->PrevInSEL ) m_SortedEdges = Edge1; + else if( !Edge2->PrevInSEL ) m_SortedEdges = Edge2; +} +//------------------------------------------------------------------------------ + +TEdge* GetNextInAEL(TEdge *e, Direction dir) +{ + return dir == dLeftToRight ? e->NextInAEL : e->PrevInAEL; +} +//------------------------------------------------------------------------------ + +void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right) +{ + if (HorzEdge.Bot.X < HorzEdge.Top.X) + { + Left = HorzEdge.Bot.X; + Right = HorzEdge.Top.X; + Dir = dLeftToRight; + } else + { + Left = HorzEdge.Top.X; + Right = HorzEdge.Bot.X; + Dir = dRightToLeft; + } +} +//------------------------------------------------------------------------ + +/******************************************************************************* +* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * +* Bottom of a scanbeam) are processed as if layered. The order in which HEs * +* are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] * +* (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), * +* and with other non-horizontal edges [*]. Once these intersections are * +* processed, intermediate HEs then 'promote' the Edge above (NextInLML) into * +* the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. * +*******************************************************************************/ + +void Clipper::ProcessHorizontal(TEdge *horzEdge) +{ + Direction dir; + cInt horzLeft, horzRight; + bool IsOpen = (horzEdge->WindDelta == 0); + + GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); + + TEdge* eLastHorz = horzEdge, *eMaxPair = 0; + while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML)) + eLastHorz = eLastHorz->NextInLML; + if (!eLastHorz->NextInLML) + eMaxPair = GetMaximaPair(eLastHorz); + + MaximaList::const_iterator maxIt; + MaximaList::const_reverse_iterator maxRit; + if (m_Maxima.size() > 0) + { + //get the first maxima in range (X) ... + if (dir == dLeftToRight) + { + maxIt = m_Maxima.begin(); + while (maxIt != m_Maxima.end() && *maxIt <= horzEdge->Bot.X) maxIt++; + if (maxIt != m_Maxima.end() && *maxIt >= eLastHorz->Top.X) + maxIt = m_Maxima.end(); + } + else + { + maxRit = m_Maxima.rbegin(); + while (maxRit != m_Maxima.rend() && *maxRit > horzEdge->Bot.X) maxRit++; + if (maxRit != m_Maxima.rend() && *maxRit <= eLastHorz->Top.X) + maxRit = m_Maxima.rend(); + } + } + + OutPt* op1 = 0; + + for (;;) //loop through consec. horizontal edges + { + + bool IsLastHorz = (horzEdge == eLastHorz); + TEdge* e = GetNextInAEL(horzEdge, dir); + while(e) + { + + //this code block inserts extra coords into horizontal edges (in output + //polygons) whereever maxima touch these horizontal edges. This helps + //'simplifying' polygons (ie if the Simplify property is set). + if (m_Maxima.size() > 0) + { + if (dir == dLeftToRight) + { + while (maxIt != m_Maxima.end() && *maxIt < e->Curr.X) + { + if (horzEdge->OutIdx >= 0 && !IsOpen) + AddOutPt(horzEdge, IntPoint(*maxIt, horzEdge->Bot.Y)); + maxIt++; + } + } + else + { + while (maxRit != m_Maxima.rend() && *maxRit > e->Curr.X) + { + if (horzEdge->OutIdx >= 0 && !IsOpen) + AddOutPt(horzEdge, IntPoint(*maxRit, horzEdge->Bot.Y)); + maxRit++; + } + } + }; + + if ((dir == dLeftToRight && e->Curr.X > horzRight) || + (dir == dRightToLeft && e->Curr.X < horzLeft)) break; + + //Also break if we've got to the end of an intermediate horizontal edge ... + //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. + if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML && + e->Dx < horzEdge->NextInLML->Dx) break; + + if (horzEdge->OutIdx >= 0 && !IsOpen) //note: may be done multiple times + { +#ifdef use_xyz + if (dir == dLeftToRight) SetZ(e->Curr, *horzEdge, *e); + else SetZ(e->Curr, *e, *horzEdge); +#endif + op1 = AddOutPt(horzEdge, e->Curr); + TEdge* eNextHorz = m_SortedEdges; + while (eNextHorz) + { + if (eNextHorz->OutIdx >= 0 && + HorzSegmentsOverlap(horzEdge->Bot.X, + horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X)) + { + OutPt* op2 = GetLastOutPt(eNextHorz); + AddJoin(op2, op1, eNextHorz->Top); + } + eNextHorz = eNextHorz->NextInSEL; + } + AddGhostJoin(op1, horzEdge->Bot); + } + + //OK, so far we're still in range of the horizontal Edge but make sure + //we're at the last of consec. horizontals when matching with eMaxPair + if(e == eMaxPair && IsLastHorz) + { + if (horzEdge->OutIdx >= 0) + AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top); + DeleteFromAEL(horzEdge); + DeleteFromAEL(eMaxPair); + return; + } + + if(dir == dLeftToRight) + { + IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); + IntersectEdges(horzEdge, e, Pt); + } + else + { + IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); + IntersectEdges( e, horzEdge, Pt); + } + TEdge* eNext = GetNextInAEL(e, dir); + SwapPositionsInAEL( horzEdge, e ); + e = eNext; + } //end while(e) + + //Break out of loop if HorzEdge.NextInLML is not also horizontal ... + if (!horzEdge->NextInLML || !IsHorizontal(*horzEdge->NextInLML)) break; + + UpdateEdgeIntoAEL(horzEdge); + if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot); + GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); + + } //end for (;;) + + if (horzEdge->OutIdx >= 0 && !op1) + { + op1 = GetLastOutPt(horzEdge); + TEdge* eNextHorz = m_SortedEdges; + while (eNextHorz) + { + if (eNextHorz->OutIdx >= 0 && + HorzSegmentsOverlap(horzEdge->Bot.X, + horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X)) + { + OutPt* op2 = GetLastOutPt(eNextHorz); + AddJoin(op2, op1, eNextHorz->Top); + } + eNextHorz = eNextHorz->NextInSEL; + } + AddGhostJoin(op1, horzEdge->Top); + } + + if (horzEdge->NextInLML) + { + if(horzEdge->OutIdx >= 0) + { + op1 = AddOutPt( horzEdge, horzEdge->Top); + UpdateEdgeIntoAEL(horzEdge); + if (horzEdge->WindDelta == 0) return; + //nb: HorzEdge is no longer horizontal here + TEdge* ePrev = horzEdge->PrevInAEL; + TEdge* eNext = horzEdge->NextInAEL; + if (ePrev && ePrev->Curr.X == horzEdge->Bot.X && + ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 && + (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && + SlopesEqual(*horzEdge, *ePrev, m_UseFullRange))) + { + OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot); + AddJoin(op1, op2, horzEdge->Top); + } + else if (eNext && eNext->Curr.X == horzEdge->Bot.X && + eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 && + eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && + SlopesEqual(*horzEdge, *eNext, m_UseFullRange)) + { + OutPt* op2 = AddOutPt(eNext, horzEdge->Bot); + AddJoin(op1, op2, horzEdge->Top); + } + } + else + UpdateEdgeIntoAEL(horzEdge); + } + else + { + if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top); + DeleteFromAEL(horzEdge); + } +} +//------------------------------------------------------------------------------ + +bool Clipper::ProcessIntersections(const cInt topY) +{ + if( !m_ActiveEdges ) return true; + try { + BuildIntersectList(topY); + size_t IlSize = m_IntersectList.size(); + if (IlSize == 0) return true; + if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList(); + else return false; + } + catch(...) + { + m_SortedEdges = 0; + DisposeIntersectNodes(); + throw clipperException("ProcessIntersections error"); + } + m_SortedEdges = 0; + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeIntersectNodes() +{ + for (size_t i = 0; i < m_IntersectList.size(); ++i ) + delete m_IntersectList[i]; + m_IntersectList.clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::BuildIntersectList(const cInt topY) +{ + if ( !m_ActiveEdges ) return; + + //prepare for sorting ... + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + while( e ) + { + e->PrevInSEL = e->PrevInAEL; + e->NextInSEL = e->NextInAEL; + e->Curr.X = TopX( *e, topY ); + e = e->NextInAEL; + } + + //bubblesort ... + bool isModified; + do + { + isModified = false; + e = m_SortedEdges; + while( e->NextInSEL ) + { + TEdge *eNext = e->NextInSEL; + IntPoint Pt; + if(e->Curr.X > eNext->Curr.X) + { + IntersectPoint(*e, *eNext, Pt); + if (Pt.Y < topY) Pt = IntPoint(TopX(*e, topY), topY); + IntersectNode * newNode = new IntersectNode; + newNode->Edge1 = e; + newNode->Edge2 = eNext; + newNode->Pt = Pt; + m_IntersectList.push_back(newNode); + + SwapPositionsInSEL(e, eNext); + isModified = true; + } + else + e = eNext; + } + if( e->PrevInSEL ) e->PrevInSEL->NextInSEL = 0; + else break; + } + while ( isModified ); + m_SortedEdges = 0; //important +} +//------------------------------------------------------------------------------ + + +void Clipper::ProcessIntersectList() +{ + for (size_t i = 0; i < m_IntersectList.size(); ++i) + { + IntersectNode* iNode = m_IntersectList[i]; + { + IntersectEdges( iNode->Edge1, iNode->Edge2, iNode->Pt); + SwapPositionsInAEL( iNode->Edge1 , iNode->Edge2 ); + } + delete iNode; + } + m_IntersectList.clear(); +} +//------------------------------------------------------------------------------ + +bool IntersectListSort(IntersectNode* node1, IntersectNode* node2) +{ + return node2->Pt.Y < node1->Pt.Y; +} +//------------------------------------------------------------------------------ + +inline bool EdgesAdjacent(const IntersectNode &inode) +{ + return (inode.Edge1->NextInSEL == inode.Edge2) || + (inode.Edge1->PrevInSEL == inode.Edge2); +} +//------------------------------------------------------------------------------ + +bool Clipper::FixupIntersectionOrder() +{ + //pre-condition: intersections are sorted Bottom-most first. + //Now it's crucial that intersections are made only between adjacent edges, + //so to ensure this the order of intersections may need adjusting ... + CopyAELToSEL(); + std::sort(m_IntersectList.begin(), m_IntersectList.end(), IntersectListSort); + size_t cnt = m_IntersectList.size(); + for (size_t i = 0; i < cnt; ++i) + { + if (!EdgesAdjacent(*m_IntersectList[i])) + { + size_t j = i + 1; + while (j < cnt && !EdgesAdjacent(*m_IntersectList[j])) j++; + if (j == cnt) return false; + std::swap(m_IntersectList[i], m_IntersectList[j]); + } + SwapPositionsInSEL(m_IntersectList[i]->Edge1, m_IntersectList[i]->Edge2); + } + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::DoMaxima(TEdge *e) +{ + TEdge* eMaxPair = GetMaximaPairEx(e); + if (!eMaxPair) + { + if (e->OutIdx >= 0) + AddOutPt(e, e->Top); + DeleteFromAEL(e); + return; + } + + TEdge* eNext = e->NextInAEL; + while(eNext && eNext != eMaxPair) + { + IntersectEdges(e, eNext, e->Top); + SwapPositionsInAEL(e, eNext); + eNext = e->NextInAEL; + } + + if(e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned) + { + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } + else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 ) + { + if (e->OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e->Top); + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } +#ifdef use_lines + else if (e->WindDelta == 0) + { + if (e->OutIdx >= 0) + { + AddOutPt(e, e->Top); + e->OutIdx = Unassigned; + } + DeleteFromAEL(e); + + if (eMaxPair->OutIdx >= 0) + { + AddOutPt(eMaxPair, e->Top); + eMaxPair->OutIdx = Unassigned; + } + DeleteFromAEL(eMaxPair); + } +#endif + else throw clipperException("DoMaxima error"); +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) +{ + TEdge* e = m_ActiveEdges; + while( e ) + { + //1. process maxima, treating them as if they're 'bent' horizontal edges, + // but exclude maxima with horizontal edges. nb: e can't be a horizontal. + bool IsMaximaEdge = IsMaxima(e, topY); + + if(IsMaximaEdge) + { + TEdge* eMaxPair = GetMaximaPairEx(e); + IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair)); + } + + if(IsMaximaEdge) + { + if (m_StrictSimple) m_Maxima.push_back(e->Top.X); + TEdge* ePrev = e->PrevInAEL; + DoMaxima(e); + if( !ePrev ) e = m_ActiveEdges; + else e = ePrev->NextInAEL; + } + else + { + //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... + if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML)) + { + UpdateEdgeIntoAEL(e); + if (e->OutIdx >= 0) + AddOutPt(e, e->Bot); + AddEdgeToSEL(e); + } + else + { + e->Curr.X = TopX( *e, topY ); + e->Curr.Y = topY; +#ifdef use_xyz + e->Curr.Z = topY == e->Top.Y ? e->Top.Z : (topY == e->Bot.Y ? e->Bot.Z : 0); +#endif + } + + //When StrictlySimple and 'e' is being touched by another edge, then + //make sure both edges have a vertex here ... + if (m_StrictSimple) + { + TEdge* ePrev = e->PrevInAEL; + if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) && + (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0)) + { + IntPoint pt = e->Curr; +#ifdef use_xyz + SetZ(pt, *ePrev, *e); +#endif + OutPt* op = AddOutPt(ePrev, pt); + OutPt* op2 = AddOutPt(e, pt); + AddJoin(op, op2, pt); //StrictlySimple (type-3) join + } + } + + e = e->NextInAEL; + } + } + + //3. Process horizontals at the Top of the scanbeam ... + m_Maxima.sort(); + ProcessHorizontals(); + m_Maxima.clear(); + + //4. Promote intermediate vertices ... + e = m_ActiveEdges; + while(e) + { + if(IsIntermediate(e, topY)) + { + OutPt* op = 0; + if( e->OutIdx >= 0 ) + op = AddOutPt(e, e->Top); + UpdateEdgeIntoAEL(e); + + //if output polygons share an edge, they'll need joining later ... + TEdge* ePrev = e->PrevInAEL; + TEdge* eNext = e->NextInAEL; + if (ePrev && ePrev->Curr.X == e->Bot.X && + ePrev->Curr.Y == e->Bot.Y && op && + ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && + SlopesEqual(e->Curr, e->Top, ePrev->Curr, ePrev->Top, m_UseFullRange) && + (e->WindDelta != 0) && (ePrev->WindDelta != 0)) + { + OutPt* op2 = AddOutPt(ePrev, e->Bot); + AddJoin(op, op2, e->Top); + } + else if (eNext && eNext->Curr.X == e->Bot.X && + eNext->Curr.Y == e->Bot.Y && op && + eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && + SlopesEqual(e->Curr, e->Top, eNext->Curr, eNext->Top, m_UseFullRange) && + (e->WindDelta != 0) && (eNext->WindDelta != 0)) + { + OutPt* op2 = AddOutPt(eNext, e->Bot); + AddJoin(op, op2, e->Top); + } + } + e = e->NextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::FixupOutPolyline(OutRec &outrec) +{ + OutPt *pp = outrec.Pts; + OutPt *lastPP = pp->Prev; + while (pp != lastPP) + { + pp = pp->Next; + if (pp->Pt == pp->Prev->Pt) + { + if (pp == lastPP) lastPP = pp->Prev; + OutPt *tmpPP = pp->Prev; + tmpPP->Next = pp->Next; + pp->Next->Prev = tmpPP; + delete pp; + pp = tmpPP; + } + } + + if (pp == pp->Prev) + { + DisposeOutPts(pp); + outrec.Pts = 0; + return; + } +} +//------------------------------------------------------------------------------ + +void Clipper::FixupOutPolygon(OutRec &outrec) +{ + //FixupOutPolygon() - removes duplicate points and simplifies consecutive + //parallel edges by removing the middle vertex. + OutPt *lastOK = 0; + outrec.BottomPt = 0; + OutPt *pp = outrec.Pts; + bool preserveCol = m_PreserveCollinear || m_StrictSimple; + + for (;;) + { + if (pp->Prev == pp || pp->Prev == pp->Next) + { + DisposeOutPts(pp); + outrec.Pts = 0; + return; + } + + //test for duplicate points and collinear edges ... + if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) || + (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) && + (!preserveCol || !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt)))) + { + lastOK = 0; + OutPt *tmp = pp; + pp->Prev->Next = pp->Next; + pp->Next->Prev = pp->Prev; + pp = pp->Prev; + delete tmp; + } + else if (pp == lastOK) break; + else + { + if (!lastOK) lastOK = pp; + pp = pp->Next; + } + } + outrec.Pts = pp; +} +//------------------------------------------------------------------------------ + +int PointCount(OutPt *Pts) +{ + if (!Pts) return 0; + int result = 0; + OutPt* p = Pts; + do + { + result++; + p = p->Next; + } + while (p != Pts); + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult(Paths &polys) +{ + polys.reserve(m_PolyOuts.size()); + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + if (!m_PolyOuts[i]->Pts) continue; + Path pg; + OutPt* p = m_PolyOuts[i]->Pts->Prev; + int cnt = PointCount(p); + if (cnt < 2) continue; + pg.reserve(cnt); + for (int i = 0; i < cnt; ++i) + { + pg.push_back(p->Pt); + p = p->Prev; + } + polys.push_back(pg); + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult2(PolyTree& polytree) +{ + polytree.Clear(); + polytree.AllNodes.reserve(m_PolyOuts.size()); + //add each output polygon/contour to polytree ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) + { + OutRec* outRec = m_PolyOuts[i]; + int cnt = PointCount(outRec->Pts); + if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) continue; + FixHoleLinkage(*outRec); + PolyNode* pn = new PolyNode(); + //nb: polytree takes ownership of all the PolyNodes + polytree.AllNodes.push_back(pn); + outRec->PolyNd = pn; + pn->Parent = 0; + pn->Index = 0; + pn->Contour.reserve(cnt); + OutPt *op = outRec->Pts->Prev; + for (int j = 0; j < cnt; j++) + { + pn->Contour.push_back(op->Pt); + op = op->Prev; + } + } + + //fixup PolyNode links etc ... + polytree.Childs.reserve(m_PolyOuts.size()); + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) + { + OutRec* outRec = m_PolyOuts[i]; + if (!outRec->PolyNd) continue; + if (outRec->IsOpen) + { + outRec->PolyNd->m_IsOpen = true; + polytree.AddChild(*outRec->PolyNd); + } + else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) + outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); + else + polytree.AddChild(*outRec->PolyNd); + } +} +//------------------------------------------------------------------------------ + +void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) +{ + //just swap the contents (because fIntersectNodes is a single-linked-list) + IntersectNode inode = int1; //gets a copy of Int1 + int1.Edge1 = int2.Edge1; + int1.Edge2 = int2.Edge2; + int1.Pt = int2.Pt; + int2.Edge1 = inode.Edge1; + int2.Edge2 = inode.Edge2; + int2.Pt = inode.Pt; +} +//------------------------------------------------------------------------------ + +inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) +{ + if (e2.Curr.X == e1.Curr.X) + { + if (e2.Top.Y > e1.Top.Y) + return e2.Top.X < TopX(e1, e2.Top.Y); + else return e1.Top.X > TopX(e2, e1.Top.Y); + } + else return e2.Curr.X < e1.Curr.X; +} +//------------------------------------------------------------------------------ + +bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, + cInt& Left, cInt& Right) +{ + if (a1 < a2) + { + if (b1 < b2) {Left = std::max(a1,b1); Right = std::min(a2,b2);} + else {Left = std::max(a1,b2); Right = std::min(a2,b1);} + } + else + { + if (b1 < b2) {Left = std::max(a2,b1); Right = std::min(a1,b2);} + else {Left = std::max(a2,b2); Right = std::min(a1,b1);} + } + return Left < Right; +} +//------------------------------------------------------------------------------ + +inline void UpdateOutPtIdxs(OutRec& outrec) +{ + OutPt* op = outrec.Pts; + do + { + op->Idx = outrec.Idx; + op = op->Prev; + } + while(op != outrec.Pts); +} +//------------------------------------------------------------------------------ + +void Clipper::InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge) +{ + if(!m_ActiveEdges) + { + edge->PrevInAEL = 0; + edge->NextInAEL = 0; + m_ActiveEdges = edge; + } + else if(!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge)) + { + edge->PrevInAEL = 0; + edge->NextInAEL = m_ActiveEdges; + m_ActiveEdges->PrevInAEL = edge; + m_ActiveEdges = edge; + } + else + { + if(!startEdge) startEdge = m_ActiveEdges; + while(startEdge->NextInAEL && + !E2InsertsBeforeE1(*startEdge->NextInAEL , *edge)) + startEdge = startEdge->NextInAEL; + edge->NextInAEL = startEdge->NextInAEL; + if(startEdge->NextInAEL) startEdge->NextInAEL->PrevInAEL = edge; + edge->PrevInAEL = startEdge; + startEdge->NextInAEL = edge; + } +} +//---------------------------------------------------------------------- + +OutPt* DupOutPt(OutPt* outPt, bool InsertAfter) +{ + OutPt* result = new OutPt; + result->Pt = outPt->Pt; + result->Idx = outPt->Idx; + if (InsertAfter) + { + result->Next = outPt->Next; + result->Prev = outPt; + outPt->Next->Prev = result; + outPt->Next = result; + } + else + { + result->Prev = outPt->Prev; + result->Next = outPt; + outPt->Prev->Next = result; + outPt->Prev = result; + } + return result; +} +//------------------------------------------------------------------------------ + +bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, + const IntPoint Pt, bool DiscardLeft) +{ + Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight); + Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight); + if (Dir1 == Dir2) return false; + + //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we + //want Op1b to be on the Right. (And likewise with Op2 and Op2b.) + //So, to facilitate this while inserting Op1b and Op2b ... + //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b, + //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.) + if (Dir1 == dLeftToRight) + { + while (op1->Next->Pt.X <= Pt.X && + op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) + op1 = op1->Next; + if (DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; + op1b = DupOutPt(op1, !DiscardLeft); + if (op1b->Pt != Pt) + { + op1 = op1b; + op1->Pt = Pt; + op1b = DupOutPt(op1, !DiscardLeft); + } + } + else + { + while (op1->Next->Pt.X >= Pt.X && + op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) + op1 = op1->Next; + if (!DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; + op1b = DupOutPt(op1, DiscardLeft); + if (op1b->Pt != Pt) + { + op1 = op1b; + op1->Pt = Pt; + op1b = DupOutPt(op1, DiscardLeft); + } + } + + if (Dir2 == dLeftToRight) + { + while (op2->Next->Pt.X <= Pt.X && + op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) + op2 = op2->Next; + if (DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; + op2b = DupOutPt(op2, !DiscardLeft); + if (op2b->Pt != Pt) + { + op2 = op2b; + op2->Pt = Pt; + op2b = DupOutPt(op2, !DiscardLeft); + }; + } else + { + while (op2->Next->Pt.X >= Pt.X && + op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) + op2 = op2->Next; + if (!DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; + op2b = DupOutPt(op2, DiscardLeft); + if (op2b->Pt != Pt) + { + op2 = op2b; + op2->Pt = Pt; + op2b = DupOutPt(op2, DiscardLeft); + }; + }; + + if ((Dir1 == dLeftToRight) == DiscardLeft) + { + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + } + else + { + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + } + return true; +} +//------------------------------------------------------------------------------ + +bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2) +{ + OutPt *op1 = j->OutPt1, *op1b; + OutPt *op2 = j->OutPt2, *op2b; + + //There are 3 kinds of joins for output polygons ... + //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are vertices anywhere + //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal). + //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same + //location at the Bottom of the overlapping segment (& Join.OffPt is above). + //3. StrictSimple joins where edges touch but are not collinear and where + //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. + bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y); + + if (isHorizontal && (j->OffPt == j->OutPt1->Pt) && + (j->OffPt == j->OutPt2->Pt)) + { + //Strictly Simple join ... + if (outRec1 != outRec2) return false; + op1b = j->OutPt1->Next; + while (op1b != op1 && (op1b->Pt == j->OffPt)) + op1b = op1b->Next; + bool reverse1 = (op1b->Pt.Y > j->OffPt.Y); + op2b = j->OutPt2->Next; + while (op2b != op2 && (op2b->Pt == j->OffPt)) + op2b = op2b->Next; + bool reverse2 = (op2b->Pt.Y > j->OffPt.Y); + if (reverse1 == reverse2) return false; + if (reverse1) + { + op1b = DupOutPt(op1, false); + op2b = DupOutPt(op2, true); + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } else + { + op1b = DupOutPt(op1, true); + op2b = DupOutPt(op2, false); + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } + } + else if (isHorizontal) + { + //treat horizontal joins differently to non-horizontal joins since with + //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt + //may be anywhere along the horizontal edge. + op1b = op1; + while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2) + op1 = op1->Prev; + while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2) + op1b = op1b->Next; + if (op1b->Next == op1 || op1b->Next == op2) return false; //a flat 'polygon' + + op2b = op2; + while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b) + op2 = op2->Prev; + while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1) + op2b = op2b->Next; + if (op2b->Next == op2 || op2b->Next == op1) return false; //a flat 'polygon' + + cInt Left, Right; + //Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges + if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right)) + return false; + + //DiscardLeftSide: when overlapping edges are joined, a spike will created + //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up + //on the discard Side as either may still be needed for other joins ... + IntPoint Pt; + bool DiscardLeftSide; + if (op1->Pt.X >= Left && op1->Pt.X <= Right) + { + Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X); + } + else if (op2->Pt.X >= Left&& op2->Pt.X <= Right) + { + Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X); + } + else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right) + { + Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X; + } + else + { + Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X); + } + j->OutPt1 = op1; j->OutPt2 = op2; + return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); + } else + { + //nb: For non-horizontal joins ... + // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y + // 2. Jr.OutPt1.Pt > Jr.OffPt.Y + + //make sure the polygons are correctly oriented ... + op1b = op1->Next; + while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next; + bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) || + !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)); + if (Reverse1) + { + op1b = op1->Prev; + while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev; + if ((op1b->Pt.Y > op1->Pt.Y) || + !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false; + }; + op2b = op2->Next; + while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next; + bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) || + !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)); + if (Reverse2) + { + op2b = op2->Prev; + while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev; + if ((op2b->Pt.Y > op2->Pt.Y) || + !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false; + } + + if ((op1b == op1) || (op2b == op2) || (op1b == op2b) || + ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false; + + if (Reverse1) + { + op1b = DupOutPt(op1, false); + op2b = DupOutPt(op2, true); + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } else + { + op1b = DupOutPt(op1, true); + op2b = DupOutPt(op2, false); + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } + } +} +//---------------------------------------------------------------------- + +static OutRec* ParseFirstLeft(OutRec* FirstLeft) +{ + while (FirstLeft && !FirstLeft->Pts) + FirstLeft = FirstLeft->FirstLeft; + return FirstLeft; +} +//------------------------------------------------------------------------------ + +void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) +{ + //tests if NewOutRec contains the polygon before reassigning FirstLeft + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec* outRec = m_PolyOuts[i]; + OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft); + if (outRec->Pts && firstLeft == OldOutRec) + { + if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) + outRec->FirstLeft = NewOutRec; + } + } +} +//---------------------------------------------------------------------- + +void Clipper::FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec) +{ + //A polygon has split into two such that one is now the inner of the other. + //It's possible that these polygons now wrap around other polygons, so check + //every polygon that's also contained by OuterOutRec's FirstLeft container + //(including 0) to see if they've become inner to the new inner polygon ... + OutRec* orfl = OuterOutRec->FirstLeft; + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec* outRec = m_PolyOuts[i]; + + if (!outRec->Pts || outRec == OuterOutRec || outRec == InnerOutRec) + continue; + OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft); + if (firstLeft != orfl && firstLeft != InnerOutRec && firstLeft != OuterOutRec) + continue; + if (Poly2ContainsPoly1(outRec->Pts, InnerOutRec->Pts)) + outRec->FirstLeft = InnerOutRec; + else if (Poly2ContainsPoly1(outRec->Pts, OuterOutRec->Pts)) + outRec->FirstLeft = OuterOutRec; + else if (outRec->FirstLeft == InnerOutRec || outRec->FirstLeft == OuterOutRec) + outRec->FirstLeft = orfl; + } +} +//---------------------------------------------------------------------- +void Clipper::FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec) +{ + //reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec* outRec = m_PolyOuts[i]; + OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft); + if (outRec->Pts && firstLeft == OldOutRec) + outRec->FirstLeft = NewOutRec; + } +} +//---------------------------------------------------------------------- + +void Clipper::JoinCommonEdges() +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + { + Join* join = m_Joins[i]; + + OutRec *outRec1 = GetOutRec(join->OutPt1->Idx); + OutRec *outRec2 = GetOutRec(join->OutPt2->Idx); + + if (!outRec1->Pts || !outRec2->Pts) continue; + if (outRec1->IsOpen || outRec2->IsOpen) continue; + + //get the polygon fragment with the correct hole state (FirstLeft) + //before calling JoinPoints() ... + OutRec *holeStateRec; + if (outRec1 == outRec2) holeStateRec = outRec1; + else if (OutRec1RightOfOutRec2(outRec1, outRec2)) holeStateRec = outRec2; + else if (OutRec1RightOfOutRec2(outRec2, outRec1)) holeStateRec = outRec1; + else holeStateRec = GetLowermostRec(outRec1, outRec2); + + if (!JoinPoints(join, outRec1, outRec2)) continue; + + if (outRec1 == outRec2) + { + //instead of joining two polygons, we've just created a new one by + //splitting one polygon into two. + outRec1->Pts = join->OutPt1; + outRec1->BottomPt = 0; + outRec2 = CreateOutRec(); + outRec2->Pts = join->OutPt2; + + //update all OutRec2.Pts Idx's ... + UpdateOutPtIdxs(*outRec2); + + if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) + { + //outRec1 contains outRec2 ... + outRec2->IsHole = !outRec1->IsHole; + outRec2->FirstLeft = outRec1; + + if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); + + if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0)) + ReversePolyPtLinks(outRec2->Pts); + + } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts)) + { + //outRec2 contains outRec1 ... + outRec2->IsHole = outRec1->IsHole; + outRec1->IsHole = !outRec2->IsHole; + outRec2->FirstLeft = outRec1->FirstLeft; + outRec1->FirstLeft = outRec2; + + if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2); + + if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0)) + ReversePolyPtLinks(outRec1->Pts); + } + else + { + //the 2 polygons are completely separate ... + outRec2->IsHole = outRec1->IsHole; + outRec2->FirstLeft = outRec1->FirstLeft; + + //fixup FirstLeft pointers that may need reassigning to OutRec2 + if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2); + } + + } else + { + //joined 2 polygons together ... + + outRec2->Pts = 0; + outRec2->BottomPt = 0; + outRec2->Idx = outRec1->Idx; + + outRec1->IsHole = holeStateRec->IsHole; + if (holeStateRec == outRec2) + outRec1->FirstLeft = outRec2->FirstLeft; + outRec2->FirstLeft = outRec1; + + if (m_UsingPolyTree) FixupFirstLefts3(outRec2, outRec1); + } + } +} + +//------------------------------------------------------------------------------ +// ClipperOffset support functions ... +//------------------------------------------------------------------------------ + +DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) +{ + if(pt2.X == pt1.X && pt2.Y == pt1.Y) + return DoublePoint(0, 0); + + double Dx = (double)(pt2.X - pt1.X); + double dy = (double)(pt2.Y - pt1.Y); + double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy ); + Dx *= f; + dy *= f; + return DoublePoint(dy, -Dx); +} + +//------------------------------------------------------------------------------ +// ClipperOffset class +//------------------------------------------------------------------------------ + +ClipperOffset::ClipperOffset(double miterLimit, double arcTolerance) +{ + this->MiterLimit = miterLimit; + this->ArcTolerance = arcTolerance; + m_lowest.X = -1; +} +//------------------------------------------------------------------------------ + +ClipperOffset::~ClipperOffset() +{ + Clear(); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::Clear() +{ + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + delete m_polyNodes.Childs[i]; + m_polyNodes.Childs.clear(); + m_lowest.X = -1; +} +//------------------------------------------------------------------------------ + +void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType) +{ + int highI = (int)path.size() - 1; + if (highI < 0) return; + PolyNode* newNode = new PolyNode(); + newNode->m_jointype = joinType; + newNode->m_endtype = endType; + + //strip duplicate points from path and also get index to the lowest point ... + if (endType == etClosedLine || endType == etClosedPolygon) + while (highI > 0 && path[0] == path[highI]) highI--; + newNode->Contour.reserve(highI + 1); + newNode->Contour.push_back(path[0]); + int j = 0, k = 0; + for (int i = 1; i <= highI; i++) + if (newNode->Contour[j] != path[i]) + { + j++; + newNode->Contour.push_back(path[i]); + if (path[i].Y > newNode->Contour[k].Y || + (path[i].Y == newNode->Contour[k].Y && + path[i].X < newNode->Contour[k].X)) k = j; + } + if (endType == etClosedPolygon && j < 2) + { + delete newNode; + return; + } + m_polyNodes.AddChild(*newNode); + + //if this path's lowest pt is lower than all the others then update m_lowest + if (endType != etClosedPolygon) return; + if (m_lowest.X < 0) + m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); + else + { + IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; + if (newNode->Contour[k].Y > ip.Y || + (newNode->Contour[k].Y == ip.Y && + newNode->Contour[k].X < ip.X)) + m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType) +{ + for (Paths::size_type i = 0; i < paths.size(); ++i) + AddPath(paths[i], joinType, endType); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::FixOrientations() +{ + //fixup orientations of all closed paths if the orientation of the + //closed path with the lowermost vertex is wrong ... + if (m_lowest.X >= 0 && + !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour)) + { + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedPolygon || + (node.m_endtype == etClosedLine && Orientation(node.Contour))) + ReversePath(node.Contour); + } + } else + { + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedLine && !Orientation(node.Contour)) + ReversePath(node.Contour); + } + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::Execute(Paths& solution, double delta) +{ + solution.clear(); + FixOrientations(); + DoOffset(delta); + + //now clean up 'corners' ... + Clipper clpr; + clpr.AddPaths(m_destPolys, ptSubject, true); + if (delta > 0) + { + clpr.Execute(ctUnion, solution, pftPositive, pftPositive); + } + else + { + IntRect r = clpr.GetBounds(); + Path outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPath(outer, ptSubject, true); + clpr.ReverseSolution(true); + clpr.Execute(ctUnion, solution, pftNegative, pftNegative); + if (solution.size() > 0) solution.erase(solution.begin()); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::Execute(PolyTree& solution, double delta) +{ + solution.Clear(); + FixOrientations(); + DoOffset(delta); + + //now clean up 'corners' ... + Clipper clpr; + clpr.AddPaths(m_destPolys, ptSubject, true); + if (delta > 0) + { + clpr.Execute(ctUnion, solution, pftPositive, pftPositive); + } + else + { + IntRect r = clpr.GetBounds(); + Path outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPath(outer, ptSubject, true); + clpr.ReverseSolution(true); + clpr.Execute(ctUnion, solution, pftNegative, pftNegative); + //remove the outer PolyNode rectangle ... + if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0) + { + PolyNode* outerNode = solution.Childs[0]; + solution.Childs.reserve(outerNode->ChildCount()); + solution.Childs[0] = outerNode->Childs[0]; + solution.Childs[0]->Parent = outerNode->Parent; + for (int i = 1; i < outerNode->ChildCount(); ++i) + solution.AddChild(*outerNode->Childs[i]); + } + else + solution.Clear(); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoOffset(double delta) +{ + m_destPolys.clear(); + m_delta = delta; + + //if Zero offset, just copy any CLOSED polygons to m_p and return ... + if (NEAR_ZERO(delta)) + { + m_destPolys.reserve(m_polyNodes.ChildCount()); + for (int i = 0; i < m_polyNodes.ChildCount(); i++) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedPolygon) + m_destPolys.push_back(node.Contour); + } + return; + } + + //see offset_triginometry3.svg in the documentation folder ... + if (MiterLimit > 2) m_miterLim = 2/(MiterLimit * MiterLimit); + else m_miterLim = 0.5; + + double y; + if (ArcTolerance <= 0.0) y = def_arc_tolerance; + else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance) + y = std::fabs(delta) * def_arc_tolerance; + else y = ArcTolerance; + //see offset_triginometry2.svg in the documentation folder ... + double steps = pi / std::acos(1 - y / std::fabs(delta)); + if (steps > std::fabs(delta) * pi) + steps = std::fabs(delta) * pi; //ie excessive precision check + m_sin = std::sin(two_pi / steps); + m_cos = std::cos(two_pi / steps); + m_StepsPerRad = steps / two_pi; + if (delta < 0.0) m_sin = -m_sin; + + m_destPolys.reserve(m_polyNodes.ChildCount() * 2); + for (int i = 0; i < m_polyNodes.ChildCount(); i++) + { + PolyNode& node = *m_polyNodes.Childs[i]; + m_srcPoly = node.Contour; + + int len = (int)m_srcPoly.size(); + if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon))) + continue; + + m_destPoly.clear(); + if (len == 1) + { + if (node.m_jointype == jtRound) + { + double X = 1.0, Y = 0.0; + for (cInt j = 1; j <= steps; j++) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + double X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + } + else + { + double X = -1.0, Y = -1.0; + for (int j = 0; j < 4; ++j) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + if (X < 0) X = 1; + else if (Y < 0) Y = 1; + else X = -1; + } + } + m_destPolys.push_back(m_destPoly); + continue; + } + //build m_normals ... + m_normals.clear(); + m_normals.reserve(len); + for (int j = 0; j < len - 1; ++j) + m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); + if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) + m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); + else + m_normals.push_back(DoublePoint(m_normals[len - 2])); + + if (node.m_endtype == etClosedPolygon) + { + int k = len - 1; + for (int j = 0; j < len; ++j) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + } + else if (node.m_endtype == etClosedLine) + { + int k = len - 1; + for (int j = 0; j < len; ++j) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + m_destPoly.clear(); + //re-build m_normals ... + DoublePoint n = m_normals[len -1]; + for (int j = len - 1; j > 0; j--) + m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + m_normals[0] = DoublePoint(-n.X, -n.Y); + k = 0; + for (int j = len - 1; j >= 0; j--) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + } + else + { + int k = 0; + for (int j = 1; j < len - 1; ++j) + OffsetPoint(j, k, node.m_jointype); + + IntPoint pt1; + if (node.m_endtype == etOpenButt) + { + int j = len - 1; + pt1 = IntPoint((cInt)Round(m_srcPoly[j].X + m_normals[j].X * + delta), (cInt)Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); + m_destPoly.push_back(pt1); + pt1 = IntPoint((cInt)Round(m_srcPoly[j].X - m_normals[j].X * + delta), (cInt)Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); + m_destPoly.push_back(pt1); + } + else + { + int j = len - 1; + k = len - 2; + m_sinA = 0; + m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y); + if (node.m_endtype == etOpenSquare) + DoSquare(j, k); + else + DoRound(j, k); + } + + //re-build m_normals ... + for (int j = len - 1; j > 0; j--) + m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y); + + k = len - 1; + for (int j = k - 1; j > 0; --j) OffsetPoint(j, k, node.m_jointype); + + if (node.m_endtype == etOpenButt) + { + pt1 = IntPoint((cInt)Round(m_srcPoly[0].X - m_normals[0].X * delta), + (cInt)Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); + m_destPoly.push_back(pt1); + pt1 = IntPoint((cInt)Round(m_srcPoly[0].X + m_normals[0].X * delta), + (cInt)Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); + m_destPoly.push_back(pt1); + } + else + { + k = 1; + m_sinA = 0; + if (node.m_endtype == etOpenSquare) + DoSquare(0, 1); + else + DoRound(0, 1); + } + m_destPolys.push_back(m_destPoly); + } + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype) +{ + //cross product ... + m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); + if (std::fabs(m_sinA * m_delta) < 1.0) + { + //dot product ... + double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y ); + if (cosA > 0) // angle => 0 degrees + { + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + return; + } + //else angle => 180 degrees + } + else if (m_sinA > 1.0) m_sinA = 1.0; + else if (m_sinA < -1.0) m_sinA = -1.0; + + if (m_sinA * m_delta < 0) + { + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + m_destPoly.push_back(m_srcPoly[j]); + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); + } + else + switch (jointype) + { + case jtMiter: + { + double r = 1 + (m_normals[j].X * m_normals[k].X + + m_normals[j].Y * m_normals[k].Y); + if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k); + break; + } + case jtSquare: DoSquare(j, k); break; + case jtRound: DoRound(j, k); break; + } + k = j; +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoSquare(int j, int k) +{ + double dx = std::tan(std::atan2(m_sinA, + m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4); + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoMiter(int j, int k, double r) +{ + double q = m_delta / r; + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), + Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoRound(int j, int k) +{ + double a = std::atan2(m_sinA, + m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); + int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1); + + double X = m_normals[k].X, Y = m_normals[k].Y, X2; + for (int i = 0; i < steps; ++i) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + X * m_delta), + Round(m_srcPoly[j].Y + Y * m_delta))); + X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); +} + +//------------------------------------------------------------------------------ +// Miscellaneous public functions +//------------------------------------------------------------------------------ + +void Clipper::DoSimplePolygons() +{ + PolyOutList::size_type i = 0; + while (i < m_PolyOuts.size()) + { + OutRec* outrec = m_PolyOuts[i++]; + OutPt* op = outrec->Pts; + if (!op || outrec->IsOpen) continue; + do //for each Pt in Polygon until duplicate found do ... + { + OutPt* op2 = op->Next; + while (op2 != outrec->Pts) + { + if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) + { + //split the polygon into two ... + OutPt* op3 = op->Prev; + OutPt* op4 = op2->Prev; + op->Prev = op4; + op4->Next = op; + op2->Prev = op3; + op3->Next = op2; + + outrec->Pts = op; + OutRec* outrec2 = CreateOutRec(); + outrec2->Pts = op2; + UpdateOutPtIdxs(*outrec2); + if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) + { + //OutRec2 is contained by OutRec1 ... + outrec2->IsHole = !outrec->IsHole; + outrec2->FirstLeft = outrec; + if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec); + } + else + if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) + { + //OutRec1 is contained by OutRec2 ... + outrec2->IsHole = outrec->IsHole; + outrec->IsHole = !outrec2->IsHole; + outrec2->FirstLeft = outrec->FirstLeft; + outrec->FirstLeft = outrec2; + if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2); + } + else + { + //the 2 polygons are separate ... + outrec2->IsHole = outrec->IsHole; + outrec2->FirstLeft = outrec->FirstLeft; + if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2); + } + op2 = op; //ie get ready for the Next iteration + } + op2 = op2->Next; + } + op = op->Next; + } + while (op != outrec->Pts); + } +} +//------------------------------------------------------------------------------ + +void ReversePath(Path& p) +{ + std::reverse(p.begin(), p.end()); +} +//------------------------------------------------------------------------------ + +void ReversePaths(Paths& p) +{ + for (Paths::size_type i = 0; i < p.size(); ++i) + ReversePath(p[i]); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType) +{ + Clipper c; + c.StrictlySimple(true); + c.AddPath(in_poly, ptSubject, true); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType) +{ + Clipper c; + c.StrictlySimple(true); + c.AddPaths(in_polys, ptSubject, true); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(Paths &polys, PolyFillType fillType) +{ + SimplifyPolygons(polys, polys, fillType); +} +//------------------------------------------------------------------------------ + +inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2) +{ + double Dx = ((double)pt1.X - pt2.X); + double dy = ((double)pt1.Y - pt2.Y); + return (Dx*Dx + dy*dy); +} +//------------------------------------------------------------------------------ + +double DistanceFromLineSqrd( + const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) +{ + //The equation of a line in general form (Ax + By + C = 0) + //given 2 points (x¹,y¹) & (x²,y²) is ... + //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0 + //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹ + //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²) + //see http://en.wikipedia.org/wiki/Perpendicular_distance + double A = double(ln1.Y - ln2.Y); + double B = double(ln2.X - ln1.X); + double C = A * ln1.X + B * ln1.Y; + C = A * pt.X + B * pt.Y - C; + return (C * C) / (A * A + B * B); +} +//--------------------------------------------------------------------------- + +bool SlopesNearCollinear(const IntPoint& pt1, + const IntPoint& pt2, const IntPoint& pt3, double distSqrd) +{ + //this function is more accurate when the point that's geometrically + //between the other 2 points is the one that's tested for distance. + //ie makes it more likely to pick up 'spikes' ... + if (Abs(pt1.X - pt2.X) > Abs(pt1.Y - pt2.Y)) + { + if ((pt1.X > pt2.X) == (pt1.X < pt3.X)) + return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; + else if ((pt2.X > pt1.X) == (pt2.X < pt3.X)) + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; + else + return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; + } + else + { + if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y)) + return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; + else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y)) + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; + else + return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; + } +} +//------------------------------------------------------------------------------ + +bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) +{ + double Dx = (double)pt1.X - pt2.X; + double dy = (double)pt1.Y - pt2.Y; + return ((Dx * Dx) + (dy * dy) <= distSqrd); +} +//------------------------------------------------------------------------------ + +OutPt* ExcludeOp(OutPt* op) +{ + OutPt* result = op->Prev; + result->Next = op->Next; + op->Next->Prev = result; + result->Idx = 0; + return result; +} +//------------------------------------------------------------------------------ + +void CleanPolygon(const Path& in_poly, Path& out_poly, double distance) +{ + //distance = proximity in units/pixels below which vertices + //will be stripped. Default ~= sqrt(2). + + size_t size = in_poly.size(); + + if (size == 0) + { + out_poly.clear(); + return; + } + + OutPt* outPts = new OutPt[size]; + for (size_t i = 0; i < size; ++i) + { + outPts[i].Pt = in_poly[i]; + outPts[i].Next = &outPts[(i + 1) % size]; + outPts[i].Next->Prev = &outPts[i]; + outPts[i].Idx = 0; + } + + double distSqrd = distance * distance; + OutPt* op = &outPts[0]; + while (op->Idx == 0 && op->Next != op->Prev) + { + if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd)) + { + op = ExcludeOp(op); + size--; + } + else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd)) + { + ExcludeOp(op->Next); + op = ExcludeOp(op); + size -= 2; + } + else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, distSqrd)) + { + op = ExcludeOp(op); + size--; + } + else + { + op->Idx = 1; + op = op->Next; + } + } + + if (size < 3) size = 0; + out_poly.resize(size); + for (size_t i = 0; i < size; ++i) + { + out_poly[i] = op->Pt; + op = op->Next; + } + delete [] outPts; +} +//------------------------------------------------------------------------------ + +void CleanPolygon(Path& poly, double distance) +{ + CleanPolygon(poly, poly, distance); +} +//------------------------------------------------------------------------------ + +void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance) +{ + out_polys.resize(in_polys.size()); + for (Paths::size_type i = 0; i < in_polys.size(); ++i) + CleanPolygon(in_polys[i], out_polys[i], distance); +} +//------------------------------------------------------------------------------ + +void CleanPolygons(Paths& polys, double distance) +{ + CleanPolygons(polys, polys, distance); +} +//------------------------------------------------------------------------------ + +void Minkowski(const Path& poly, const Path& path, + Paths& solution, bool isSum, bool isClosed) +{ + int delta = (isClosed ? 1 : 0); + size_t polyCnt = poly.size(); + size_t pathCnt = path.size(); + Paths pp; + pp.reserve(pathCnt); + if (isSum) + for (size_t i = 0; i < pathCnt; ++i) + { + Path p; + p.reserve(polyCnt); + for (size_t j = 0; j < poly.size(); ++j) + p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y)); + pp.push_back(p); + } + else + for (size_t i = 0; i < pathCnt; ++i) + { + Path p; + p.reserve(polyCnt); + for (size_t j = 0; j < poly.size(); ++j) + p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y)); + pp.push_back(p); + } + + solution.clear(); + solution.reserve((pathCnt + delta) * (polyCnt + 1)); + for (size_t i = 0; i < pathCnt - 1 + delta; ++i) + for (size_t j = 0; j < polyCnt; ++j) + { + Path quad; + quad.reserve(4); + quad.push_back(pp[i % pathCnt][j % polyCnt]); + quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); + quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); + quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); + if (!Orientation(quad)) ReversePath(quad); + solution.push_back(quad); + } +} +//------------------------------------------------------------------------------ + +void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed) +{ + Minkowski(pattern, path, solution, true, pathIsClosed); + Clipper c; + c.AddPaths(solution, ptSubject, true); + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); +} +//------------------------------------------------------------------------------ + +void TranslatePath(const Path& input, Path& output, const IntPoint delta) +{ + //precondition: input != output + output.resize(input.size()); + for (size_t i = 0; i < input.size(); ++i) + output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y); +} +//------------------------------------------------------------------------------ + +void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed) +{ + Clipper c; + for (size_t i = 0; i < paths.size(); ++i) + { + Paths tmp; + Minkowski(pattern, paths[i], tmp, true, pathIsClosed); + c.AddPaths(tmp, ptSubject, true); + if (pathIsClosed) + { + Path tmp2; + TranslatePath(paths[i], tmp2, pattern[0]); + c.AddPath(tmp2, ptClip, true); + } + } + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); +} +//------------------------------------------------------------------------------ + +void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution) +{ + Minkowski(poly1, poly2, solution, false, true); + Clipper c; + c.AddPaths(solution, ptSubject, true); + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); +} +//------------------------------------------------------------------------------ + +enum NodeType {ntAny, ntOpen, ntClosed}; + +void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& paths) +{ + bool match = true; + if (nodetype == ntClosed) match = !polynode.IsOpen(); + else if (nodetype == ntOpen) return; + + if (!polynode.Contour.empty() && match) + paths.push_back(polynode.Contour); + for (int i = 0; i < polynode.ChildCount(); ++i) + AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths); +} +//------------------------------------------------------------------------------ + +void PolyTreeToPaths(const PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + AddPolyNodeToPaths(polytree, ntAny, paths); +} +//------------------------------------------------------------------------------ + +void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + AddPolyNodeToPaths(polytree, ntClosed, paths); +} +//------------------------------------------------------------------------------ + +void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + //Open paths are top level only, so ... + for (int i = 0; i < polytree.ChildCount(); ++i) + if (polytree.Childs[i]->IsOpen()) + paths.push_back(polytree.Childs[i]->Contour); +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const IntPoint &p) +{ + s << "(" << p.X << "," << p.Y << ")"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const Path &p) +{ + if (p.empty()) return s; + Path::size_type last = p.size() -1; + for (Path::size_type i = 0; i < last; i++) + s << "(" << p[i].X << "," << p[i].Y << "), "; + s << "(" << p[last].X << "," << p[last].Y << ")\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const Paths &p) +{ + for (Paths::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +} //ClipperLib namespace diff --git a/thirdparty/misc/clipper.hpp b/thirdparty/misc/clipper.hpp new file mode 100644 index 0000000000..5a19617bb4 --- /dev/null +++ b/thirdparty/misc/clipper.hpp @@ -0,0 +1,406 @@ +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 6.4.2 * +* Date : 27 February 2017 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2017 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +#ifndef clipper_hpp +#define clipper_hpp + +#define CLIPPER_VERSION "6.4.2" + +//use_int32: When enabled 32bit ints are used instead of 64bit ints. This +//improve performance but coordinate values are limited to the range +/- 46340 +//#define use_int32 + +//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance. +//#define use_xyz + +//use_lines: Enables line clipping. Adds a very minor cost to performance. +#define use_lines + +//use_deprecated: Enables temporary support for the obsolete functions +//#define use_deprecated + +#include <vector> +#include <list> +#include <set> +#include <stdexcept> +#include <cstring> +#include <cstdlib> +#include <ostream> +#include <functional> +#include <queue> + +namespace ClipperLib { + +enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; +enum PolyType { ptSubject, ptClip }; +//By far the most widely used winding rules for polygon filling are +//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) +//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) +//see http://glprogramming.com/red/chapter11.html +enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; + +#ifdef use_int32 + typedef int cInt; + static cInt const loRange = 0x7FFF; + static cInt const hiRange = 0x7FFF; +#else + typedef signed long long cInt; + static cInt const loRange = 0x3FFFFFFF; + static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; + typedef signed long long long64; //used by Int128 class + typedef unsigned long long ulong64; + +#endif + +struct IntPoint { + cInt X; + cInt Y; +#ifdef use_xyz + cInt Z; + IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {}; +#else + IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {}; +#endif + + friend inline bool operator== (const IntPoint& a, const IntPoint& b) + { + return a.X == b.X && a.Y == b.Y; + } + friend inline bool operator!= (const IntPoint& a, const IntPoint& b) + { + return a.X != b.X || a.Y != b.Y; + } +}; +//------------------------------------------------------------------------------ + +typedef std::vector< IntPoint > Path; +typedef std::vector< Path > Paths; + +inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;} +inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;} + +std::ostream& operator <<(std::ostream &s, const IntPoint &p); +std::ostream& operator <<(std::ostream &s, const Path &p); +std::ostream& operator <<(std::ostream &s, const Paths &p); + +struct DoublePoint +{ + double X; + double Y; + DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} + DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {} +}; +//------------------------------------------------------------------------------ + +#ifdef use_xyz +typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt); +#endif + +enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4}; +enum JoinType {jtSquare, jtRound, jtMiter}; +enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; + +class PolyNode; +typedef std::vector< PolyNode* > PolyNodes; + +class PolyNode +{ +public: + PolyNode(); + virtual ~PolyNode(){}; + Path Contour; + PolyNodes Childs; + PolyNode* Parent; + PolyNode* GetNext() const; + bool IsHole() const; + bool IsOpen() const; + int ChildCount() const; +private: + //PolyNode& operator =(PolyNode& other); + unsigned Index; //node index in Parent.Childs + bool m_IsOpen; + JoinType m_jointype; + EndType m_endtype; + PolyNode* GetNextSiblingUp() const; + void AddChild(PolyNode& child); + friend class Clipper; //to access Index + friend class ClipperOffset; +}; + +class PolyTree: public PolyNode +{ +public: + ~PolyTree(){ Clear(); }; + PolyNode* GetFirst() const; + void Clear(); + int Total() const; +private: + //PolyTree& operator =(PolyTree& other); + PolyNodes AllNodes; + friend class Clipper; //to access AllNodes +}; + +bool Orientation(const Path &poly); +double Area(const Path &poly); +int PointInPolygon(const IntPoint &pt, const Path &path); + +void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); + +void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415); +void CleanPolygon(Path& poly, double distance = 1.415); +void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415); +void CleanPolygons(Paths& polys, double distance = 1.415); + +void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed); +void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed); +void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution); + +void PolyTreeToPaths(const PolyTree& polytree, Paths& paths); +void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths); +void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths); + +void ReversePath(Path& p); +void ReversePaths(Paths& p); + +struct IntRect { cInt left; cInt top; cInt right; cInt bottom; }; + +//enums that are used internally ... +enum EdgeSide { esLeft = 1, esRight = 2}; + +//forward declarations (for stuff used internally) ... +struct TEdge; +struct IntersectNode; +struct LocalMinimum; +struct OutPt; +struct OutRec; +struct Join; + +typedef std::vector < OutRec* > PolyOutList; +typedef std::vector < TEdge* > EdgeList; +typedef std::vector < Join* > JoinList; +typedef std::vector < IntersectNode* > IntersectList; + +//------------------------------------------------------------------------------ + +//ClipperBase is the ancestor to the Clipper class. It should not be +//instantiated directly. This class simply abstracts the conversion of sets of +//polygon coordinates into edge objects that are stored in a LocalMinima list. +class ClipperBase +{ +public: + ClipperBase(); + virtual ~ClipperBase(); + virtual bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); + bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); + virtual void Clear(); + IntRect GetBounds(); + bool PreserveCollinear() {return m_PreserveCollinear;}; + void PreserveCollinear(bool value) {m_PreserveCollinear = value;}; +protected: + void DisposeLocalMinimaList(); + TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); + virtual void Reset(); + TEdge* ProcessBound(TEdge* E, bool IsClockwise); + void InsertScanbeam(const cInt Y); + bool PopScanbeam(cInt &Y); + bool LocalMinimaPending(); + bool PopLocalMinima(cInt Y, const LocalMinimum *&locMin); + OutRec* CreateOutRec(); + void DisposeAllOutRecs(); + void DisposeOutRec(PolyOutList::size_type index); + void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); + void DeleteFromAEL(TEdge *e); + void UpdateEdgeIntoAEL(TEdge *&e); + + typedef std::vector<LocalMinimum> MinimaList; + MinimaList::iterator m_CurrentLM; + MinimaList m_MinimaList; + + bool m_UseFullRange; + EdgeList m_edges; + bool m_PreserveCollinear; + bool m_HasOpenPaths; + PolyOutList m_PolyOuts; + TEdge *m_ActiveEdges; + + typedef std::priority_queue<cInt> ScanbeamList; + ScanbeamList m_Scanbeam; +}; +//------------------------------------------------------------------------------ + +class Clipper : public virtual ClipperBase +{ +public: + Clipper(int initOptions = 0); + bool Execute(ClipType clipType, + Paths &solution, + PolyFillType fillType = pftEvenOdd); + bool Execute(ClipType clipType, + Paths &solution, + PolyFillType subjFillType, + PolyFillType clipFillType); + bool Execute(ClipType clipType, + PolyTree &polytree, + PolyFillType fillType = pftEvenOdd); + bool Execute(ClipType clipType, + PolyTree &polytree, + PolyFillType subjFillType, + PolyFillType clipFillType); + bool ReverseSolution() { return m_ReverseOutput; }; + void ReverseSolution(bool value) {m_ReverseOutput = value;}; + bool StrictlySimple() {return m_StrictSimple;}; + void StrictlySimple(bool value) {m_StrictSimple = value;}; + //set the callback function for z value filling on intersections (otherwise Z is 0) +#ifdef use_xyz + void ZFillFunction(ZFillCallback zFillFunc); +#endif +protected: + virtual bool ExecuteInternal(); +private: + JoinList m_Joins; + JoinList m_GhostJoins; + IntersectList m_IntersectList; + ClipType m_ClipType; + typedef std::list<cInt> MaximaList; + MaximaList m_Maxima; + TEdge *m_SortedEdges; + bool m_ExecuteLocked; + PolyFillType m_ClipFillType; + PolyFillType m_SubjFillType; + bool m_ReverseOutput; + bool m_UsingPolyTree; + bool m_StrictSimple; +#ifdef use_xyz + ZFillCallback m_ZFill; //custom callback +#endif + void SetWindingCount(TEdge& edge); + bool IsEvenOddFillType(const TEdge& edge) const; + bool IsEvenOddAltFillType(const TEdge& edge) const; + void InsertLocalMinimaIntoAEL(const cInt botY); + void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge); + void AddEdgeToSEL(TEdge *edge); + bool PopEdgeFromSEL(TEdge *&edge); + void CopyAELToSEL(); + void DeleteFromSEL(TEdge *e); + void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); + bool IsContributing(const TEdge& edge) const; + bool IsTopHorz(const cInt XPos); + void DoMaxima(TEdge *e); + void ProcessHorizontals(); + void ProcessHorizontal(TEdge *horzEdge); + void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + OutRec* GetOutRec(int idx); + void AppendPolygon(TEdge *e1, TEdge *e2); + void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt); + OutPt* AddOutPt(TEdge *e, const IntPoint &pt); + OutPt* GetLastOutPt(TEdge *e); + bool ProcessIntersections(const cInt topY); + void BuildIntersectList(const cInt topY); + void ProcessIntersectList(); + void ProcessEdgesAtTopOfScanbeam(const cInt topY); + void BuildResult(Paths& polys); + void BuildResult2(PolyTree& polytree); + void SetHoleState(TEdge *e, OutRec *outrec); + void DisposeIntersectNodes(); + bool FixupIntersectionOrder(); + void FixupOutPolygon(OutRec &outrec); + void FixupOutPolyline(OutRec &outrec); + bool IsHole(TEdge *e); + bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl); + void FixHoleLinkage(OutRec &outrec); + void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt); + void ClearJoins(); + void ClearGhostJoins(); + void AddGhostJoin(OutPt *op, const IntPoint offPt); + bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2); + void JoinCommonEdges(); + void DoSimplePolygons(); + void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec); + void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec); + void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec); +#ifdef use_xyz + void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2); +#endif +}; +//------------------------------------------------------------------------------ + +class ClipperOffset +{ +public: + ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25); + ~ClipperOffset(); + void AddPath(const Path& path, JoinType joinType, EndType endType); + void AddPaths(const Paths& paths, JoinType joinType, EndType endType); + void Execute(Paths& solution, double delta); + void Execute(PolyTree& solution, double delta); + void Clear(); + double MiterLimit; + double ArcTolerance; +private: + Paths m_destPolys; + Path m_srcPoly; + Path m_destPoly; + std::vector<DoublePoint> m_normals; + double m_delta, m_sinA, m_sin, m_cos; + double m_miterLim, m_StepsPerRad; + IntPoint m_lowest; + PolyNode m_polyNodes; + + void FixOrientations(); + void DoOffset(double delta); + void OffsetPoint(int j, int& k, JoinType jointype); + void DoSquare(int j, int k); + void DoMiter(int j, int k, double r); + void DoRound(int j, int k); +}; +//------------------------------------------------------------------------------ + +class clipperException : public std::exception +{ + public: + clipperException(const char* description): m_descr(description) {} + virtual ~clipperException() throw() {} + virtual const char* what() const throw() {return m_descr.c_str();} + private: + std::string m_descr; +}; +//------------------------------------------------------------------------------ + +} //ClipperLib namespace + +#endif //clipper_hpp + + diff --git a/thirdparty/thekla_atlas/nvcore/Debug.h b/thirdparty/thekla_atlas/nvcore/Debug.h index f37a05c453..3804ed4763 100644 --- a/thirdparty/thekla_atlas/nvcore/Debug.h +++ b/thirdparty/thekla_atlas/nvcore/Debug.h @@ -200,10 +200,10 @@ namespace nv if (reinterpret_cast<uint64>(ptr) < 0x10000ULL) return false; if (reinterpret_cast<uint64>(ptr) >= 0x000007FFFFFEFFFFULL) return false; #else - if (reinterpret_cast<uint32>(ptr) == 0xcccccccc) return false; - if (reinterpret_cast<uint32>(ptr) == 0xcdcdcdcd) return false; - if (reinterpret_cast<uint32>(ptr) == 0xdddddddd) return false; - if (reinterpret_cast<uint32>(ptr) == 0xffffffff) return false; + if (reinterpret_cast<uintptr_t>(ptr) == 0xcccccccc) return false; + if (reinterpret_cast<uintptr_t>(ptr) == 0xcdcdcdcd) return false; + if (reinterpret_cast<uintptr_t>(ptr) == 0xdddddddd) return false; + if (reinterpret_cast<uintptr_t>(ptr) == 0xffffffff) return false; #endif return true; } diff --git a/thirdparty/thekla_atlas/poshlib/posh.h b/thirdparty/thekla_atlas/poshlib/posh.h index c3efe26a2d..3038297b39 100644 --- a/thirdparty/thekla_atlas/poshlib/posh.h +++ b/thirdparty/thekla_atlas/poshlib/posh.h @@ -498,6 +498,11 @@ Metrowerks: # define POSH_CPU_STRING "ARM" #endif +#if defined AARCH64 || defined __aarch64__ || defined _AARCH64 +# define POSH_CPU_STRONGARM 1 +# define POSH_CPU_STRING "AARCH64" +#endif + #if defined mips || defined __mips__ || defined __MIPS__ || defined _MIPS # define POSH_CPU_MIPS 1 # if defined _R5900 |