Browse Source

Merge branch 'master' into 3.2

Rémi Verschelde 5 years ago
parent
commit
152d763640
100 changed files with 1907 additions and 747 deletions
  1. 1 1
      Makefile
  2. 13 0
      README.md
  3. 48 5
      _static/css/custom.css
  4. 1 1
      _static/js/custom.js
  5. 2 5
      about/faq.rst
  6. 139 0
      community/contributing/best_practices_for_engine_contributors.rst
  7. 4 4
      community/contributing/code_style_guidelines.rst
  8. 41 15
      community/contributing/docs_writing_guidelines.rst
  9. BIN
      community/contributing/img/best_practices1.png
  10. BIN
      community/contributing/img/best_practices2.png
  11. BIN
      community/contributing/img/best_practices3.png
  12. BIN
      community/contributing/img/best_practices4.png
  13. BIN
      community/contributing/img/best_practices5.png
  14. BIN
      community/contributing/img/best_practices6.png
  15. BIN
      community/contributing/img/best_practices7.png
  16. BIN
      community/contributing/img/best_practices8.png
  17. 1 0
      community/contributing/index.rst
  18. 3 3
      community/contributing/updating_the_class_reference.rst
  19. 16 15
      community/tutorials.rst
  20. 60 50
      conf.py
  21. 1 1
      development/compiling/compiling_for_android.rst
  22. 32 48
      development/compiling/compiling_for_osx.rst
  23. 2 2
      development/compiling/compiling_for_uwp.rst
  24. 23 0
      development/compiling/compiling_for_x11.rst
  25. 6 1
      development/compiling/optimizing_for_size.rst
  26. 5 5
      development/cpp/configuring_an_ide.rst
  27. 76 0
      development/cpp/custom_modules_in_cpp.rst
  28. 251 138
      development/cpp/custom_resource_format_loaders.rst
  29. 295 124
      extensions/gdscript.py
  30. 1 1
      getting_started/editor/unity_to_godot.rst
  31. 11 7
      getting_started/scripting/c_sharp/c_sharp_basics.rst
  32. 67 0
      getting_started/scripting/c_sharp/c_sharp_features.rst
  33. 53 53
      getting_started/scripting/gdscript/gdscript_advanced.rst
  34. 62 43
      getting_started/scripting/gdscript/gdscript_basics.rst
  35. 8 6
      getting_started/scripting/gdscript/gdscript_styleguide.rst
  36. 29 13
      getting_started/scripting/gdscript/static_typing.rst
  37. 3 3
      getting_started/scripting/visual_script/nodes_purposes.rst
  38. 1 1
      getting_started/step_by_step/animations.rst
  39. 119 0
      getting_started/step_by_step/exporting.rst
  40. BIN
      getting_started/step_by_step/img/export_touchsettings.png
  41. BIN
      getting_started/step_by_step/img/export_web_export_with_debug_disabled.png
  42. BIN
      getting_started/step_by_step/img/instancing.png
  43. BIN
      getting_started/step_by_step/img/instancingpre.png
  44. BIN
      getting_started/step_by_step/img/signals_connect_dialog_timer.png
  45. 4 3
      getting_started/step_by_step/instancing.rst
  46. 12 11
      getting_started/step_by_step/intro_to_the_editor_interface.rst
  47. 3 4
      getting_started/step_by_step/scenes_and_nodes.rst
  48. 2 2
      getting_started/step_by_step/scripting.rst
  49. 55 1
      getting_started/step_by_step/signals.rst
  50. 1 1
      getting_started/step_by_step/ui_code_a_life_bar.rst
  51. 4 4
      getting_started/step_by_step/ui_game_user_interface.rst
  52. 1 1
      getting_started/step_by_step/ui_introduction_to_the_ui_system.rst
  53. 5 5
      getting_started/step_by_step/ui_main_menu.rst
  54. 9 10
      getting_started/step_by_step/your_first_game.rst
  55. 3 2
      getting_started/workflow/assets/escn_exporter/material.rst
  56. 46 9
      getting_started/workflow/assets/importing_images.rst
  57. 19 9
      getting_started/workflow/assets/importing_translations.rst
  58. 1 1
      getting_started/workflow/best_practices/autoloads_versus_internal_nodes.rst
  59. 1 1
      getting_started/workflow/export/android_custom_build.rst
  60. 19 10
      getting_started/workflow/export/exporting_for_android.rst
  61. 1 1
      getting_started/workflow/export/exporting_for_web.rst
  62. 5 0
      getting_started/workflow/export/exporting_pcks.rst
  63. 0 1
      make.bat
  64. 1 0
      robots.txt
  65. 2 2
      tutorials/2d/2d_lights_and_shadows.rst
  66. 48 15
      tutorials/2d/2d_sprite_animation.rst
  67. BIN
      tutorials/2d/img/2d_animation_add_from_spritesheet.png
  68. BIN
      tutorials/2d/img/2d_animation_frog_spritesheet.png
  69. BIN
      tutorials/2d/img/2d_animation_play_spritesheet_animation.png
  70. BIN
      tutorials/2d/img/2d_animation_spritesheet_animation.png
  71. BIN
      tutorials/2d/img/2d_animation_spritesheet_select_rows.png
  72. BIN
      tutorials/2d/img/2d_animation_spritesheet_selectframes.png
  73. BIN
      tutorials/2d/img/viewport_transforms2.png
  74. 1 1
      tutorials/2d/using_tilemaps.rst
  75. 4 4
      tutorials/3d/fps_tutorial/part_one.rst
  76. 5 3
      tutorials/3d/fps_tutorial/part_three.rst
  77. 7 7
      tutorials/3d/fps_tutorial/part_two.rst
  78. 32 34
      tutorials/3d/high_dynamic_range.rst
  79. 2 2
      tutorials/3d/introduction_to_3d.rst
  80. 4 4
      tutorials/3d/using_gridmaps.rst
  81. 3 3
      tutorials/animation/cutout_animation.rst
  82. 2 2
      tutorials/animation/introduction_2d.rst
  83. 61 5
      tutorials/assetlib/uploading_to_assetlib.rst
  84. 13 0
      tutorials/assetlib/what_is_assetlib.rst
  85. 1 9
      tutorials/audio/sync_with_audio.rst
  86. 1 1
      tutorials/content/procedural_geometry/immediategeometry.rst
  87. 128 7
      tutorials/inputs/input_examples.rst
  88. 24 24
      tutorials/io/files/resource_queue.gd
  89. 3 3
      tutorials/legal/complying_with_licenses.rst
  90. BIN
      tutorials/math/img/bezier_cubic_handles.png
  91. BIN
      tutorials/math/img/bezier_cubic_points.png
  92. BIN
      tutorials/math/img/bezier_path_2d.png
  93. BIN
      tutorials/math/img/bezier_point_amount.png
  94. BIN
      tutorials/math/img/bezier_quadratic_points.png
  95. BIN
      tutorials/math/img/empty_grid.png
  96. BIN
      tutorials/math/img/matrices_and_transforms/3d-identity.png
  97. BIN
      tutorials/math/img/matrices_and_transforms/3d-identity.xcf
  98. BIN
      tutorials/math/img/matrices_and_transforms/apply.png
  99. BIN
      tutorials/math/img/matrices_and_transforms/apply.xcf
  100. BIN
      tutorials/math/img/matrices_and_transforms/identity-godot.png

+ 1 - 1
Makefile

@@ -2,7 +2,7 @@
 #
 
 # You can set these variables from the command line.
-SPHINXOPTS    = -j auto
+SPHINXOPTS    =
 SPHINXBUILD   = sphinx-build
 PAPER         =
 BUILDDIR      = _build

+ 13 - 0
README.md

@@ -63,7 +63,20 @@ or:
 make SPHINXBUILD=~/.local/bin/sphinx-build html
 ```
 
+Building the documentation requires at least 8 GB of RAM to be done without swapping. If you have at least 16 GB of RAM, you can speed up compilation by using:
+
+```bash
+# On Linux/macOS
+make html SPHINXOPTS=-j2
+
+# On Windows
+set SPHINXOPTS=-j2 && make html
+```
+
 The compilation might take some time as the `classes/` folder contains many files to parse.
+
+In case of a `MemoryError` or `EOFError`, you can remove the `classes/` folder and run `make` again. This will drop the class references from the final HTML documentation but will keep the rest intact. Make sure to avoid using `git add .` in this case when working on a pull request, or the whole `classes/` folder will be removed when you make a commit. See [#3157](https://github.com/godotengine/godot-docs/issues/3157) for more details.
+
 You can then test the changes live by opening `_build/html/index.html` in your favorite browser.
 
 ### Building with Sphinx on Windows

+ 48 - 5
_static/css/custom.css

@@ -55,11 +55,20 @@
     --admonition-attention-color: #404040;
     --admonition-attention-title-background-color: #f0b37e;
     --admonition-attention-title-color: #fff;
+    --admonition-danger-background-color: #fcf3f2;
+    --admonition-danger-color: #404040;
+    --admonition-danger-title-background-color: #e9a499;
+    --admonition-danger-title-color: #fff;
     --admonition-tip-background-color: #dbfaf4;
     --admonition-tip-color: #404040;
     --admonition-tip-title-background-color: #1abc9c;
     --admonition-tip-title-color: #fff;
 
+    --kbd-background-color: #fafbfc;
+    --kbd-outline-color: #d1d5da;
+    --kbd-shadow-color: #b0b7bf;
+    --kbd-text-color: #444d56;
+
     --btn-neutral-background-color: #f3f6f6;
     --btn-neutral-hover-background-color: #e5ebeb;
     --footer-color: #808080;
@@ -118,11 +127,20 @@
         --admonition-attention-color: #ffeeaf;
         --admonition-attention-title-background-color: #665022;
         --admonition-attention-title-color: #ffeeaf;
+        --admonition-danger-background-color: #433;
+        --admonition-danger-color: #fcc;
+        --admonition-danger-title-background-color: #633;
+        --admonition-danger-title-color: #fcc;
         --admonition-tip-background-color: #28382d;
         --admonition-tip-color: #dfd;
         --admonition-tip-title-background-color: #336648;
         --admonition-tip-title-color: #dfd;
 
+        --kbd-background-color: #595b5d;
+        --kbd-outline-color: #3d4144;
+        --kbd-shadow-color: #1e2023;
+        --kbd-text-color: #e2f2ff;
+
         --btn-neutral-background-color: #404040;
         --btn-neutral-hover-background-color: #505050;
         --footer-color: #aaa;
@@ -238,7 +256,7 @@ footer,
     background-color: var(--content-wrap-background-color);
 }
 
-@media only screen and (min-width: 768px) {
+@media only screen and (min-width: 769px) {
     .wy-body-for-nav {
         /* Center the page on wide displays for better readability */
         max-width: 1100px;
@@ -341,7 +359,8 @@ code,
     color: var(--highlight-type2-color);
 }
 
-.highlight .nf {
+.highlight .nf,
+.highlight .nt {
     color: var(--highlight-function-color);
 }
 
@@ -385,6 +404,16 @@ code,
     color: var(--admonition-attention-title-color);
 }
 
+.rst-content .admonition.danger {
+    background-color: var(--admonition-danger-background-color);
+    color: var(--admonition-danger-color);
+}
+
+.rst-content .admonition.danger .admonition-title {
+    background-color: var(--admonition-danger-title-background-color);
+    color: var(--admonition-danger-title-color);
+}
+
 .rst-content .admonition.tip,
 .rst-content .admonition.important {
     background-color: var(--admonition-tip-background-color);
@@ -397,6 +426,20 @@ code,
     color: var(--admonition-tip-title-color);
 }
 
+/* Keyboard shortcuts tweaks */
+kbd, .kbd {
+    background-color: var(--kbd-background-color);
+    border: 1px solid var(--kbd-outline-color);
+    border-radius: 3px;
+    box-shadow: inset 0 -1px 0 var(--kbd-shadow-color);
+    color: var(--kbd-text-color);
+    display: inline-block;
+    font-size: 12px;
+    line-height: 11px;
+    padding: 4px 5px;
+    vertical-align: middle;
+}
+
 /* Buttons */
 
 .btn-neutral {
@@ -426,7 +469,7 @@ code,
     position: fixed;
 }
 
-@media only screen and (min-width: 768px) {
+@media only screen and (min-width: 769px) {
     /* Simulate a drop shadow that only affects the bottom edge */
     /* This is used to indicate the search bar is fixed */
     .wy-side-nav-search.fixed::after {
@@ -477,7 +520,7 @@ code,
     background-color: var(--navbar-background-color);
 }
 
-@media only screen and (min-width: 768px) {
+@media only screen and (min-width: 769px) {
     .wy-nav-side {
         /* Required to center the page on wide displays */
         left: inherit;
@@ -586,7 +629,7 @@ code,
     background-color: var(--navbar-current-background-color);
 }
 
-@media only screen and (min-width: 768px) {
+@media only screen and (min-width: 769px) {
     .rst-versions {
         /* Required to center the page on wide displays */
         left: inherit;

+ 1 - 1
_static/js/custom.js

@@ -42,7 +42,7 @@ function registerOnScrollEvent(mediaQuery) {
 }
 
 $(document).ready(() => {
-  const mediaQuery = window.matchMedia('only screen and (min-width: 768px)');
+  const mediaQuery = window.matchMedia('only screen and (min-width: 769px)');
   registerOnScrollEvent(mediaQuery);
   mediaQuery.addListener(registerOnScrollEvent);
 });

+ 2 - 5
about/faq.rst

@@ -148,15 +148,12 @@ What type of 3D model formats does Godot support?
 -------------------------------------------------
 
 Godot supports Collada via the `OpenCollada <https://github.com/KhronosGroup/OpenCOLLADA/wiki/OpenCOLLADA-Tools>`_ exporter (Maya, 3DSMax).
-
 If you are using Blender, take a look at our own `Better Collada Exporter <https://godotengine.org/download>`_.
 
 As of Godot 3.0, glTF is supported.
 
-FBX SDK has a `restrictive license <https://www.blender.org/bf/Autodesk_FBX_License.rtf>`_,
-that is incompatible with the `open license <https://opensource.org/licenses/MIT>`_
-provided by Godot. That being said, FBX support could still be provided by third parties
-as a plugin. (See Plugins question below.)
+FBX is supported via the Open Asset Import library. However, FBX is proprietary
+so we recommend using other formats listed above, if suitable for your workflow.
 
 Will [insert closed SDK such as FMOD, GameWorks, etc.] be supported in Godot?
 -----------------------------------------------------------------------------

+ 139 - 0
community/contributing/best_practices_for_engine_contributors.rst

@@ -0,0 +1,139 @@
+.. _doc_best_practices_for_engine_contributors:
+
+Best practices for engine contributors
+======================================
+
+Introduction
+------------
+
+Godot has a large amount of users who have the ability to contribute, given the project itself is aimed mainly at users with the ability to do programming. Despite this, not all of them have the same level of experience working in large projects or in software engineering, which can lead to common misunderstandings and bad practices during the process of contributing code to the project.
+
+Language
+--------
+
+The scope of this document is to be a list of best practices for contributors to follow, as well as to creating a language they can use to refer to common situations that arise in the process of submitting their contributions.
+
+While some may find it useful to extend this to general software development, our intention is to just restrict to situations that are most common in our project.
+
+Contributions are most of the time categorized as bug fixes, enhancements or new features. To abstract this idea, we will call them *Solutions*, because they always seek to solve something that can be described as a *Problem*.
+
+Best Practices
+--------------
+
+#1: The problem always comes first
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many contributors are extremely creative and just enjoy the process of designing abstract data structures, creating nice user interfaces,or simply love programming. Whatever the case may be, they come up with cool ideas, which may not be actually solving any actual problems.
+
+.. image:: img/best_practices1.png
+
+These are usually called *Solutions in search of a problem*. In an ideal world, they would not be harmful but, in reality, code takes time to write, takes space as source and binary and requires maintenance once it exists. Avoiding the addition of anything unnecessary is always considered a good practice in software development.
+
+#2: The problem has to exist
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is a variation of the previous practice. I believe most developers agree that adding anything unnecessary is not a good idea, but what constitutes what is necessary and what isn't?
+
+.. image:: img/best_practices2.png
+
+The answer to this question is that the problem needs to *exist*. It must not be speculation or a belief. The user must be using the software as intended to create something they *need*. In this process, the user may stumble into a problem that requires a solution in order to continue, or in order to achieve greater productivity. In this case, *a solution is needed*.
+
+Believing that problems may arise in the future and that the software needs to be ready to solve them by the time they appear is called *"Future proofing"* and its characterized by lines of thought such as: 
+
+- I think it would be useful for users to...
+- I think users will eventually need to...
+
+This is generally considered a bad habit, because trying to solve problems that *don't actually exist* in the present will very often lead to code that will be written but never used, or to code that is considerably more complex to use and maintain than it needs to be.
+
+#3: The problem has to be complex or frequent
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Software is designed to solve problems, but we can't expect it to solve *every problem that exists under the sun*. As a game engine, Godot will solve problems for you, so it helps you to make games better and faster, but it won't make the *entire game* for you. A line must be drawn somewhere.
+
+.. image:: img/best_practices3.png
+
+Whether a problem is worth solving is determined by the difficulty the user has to work around it. This difficulty can be expressed as:
+
+- The complexity of the problem
+- The frequency the problem
+
+If the problem is *too complex* for most users to solve, the software must offer a ready made solution for it. Likewise, if the problem is easy for the user to workaround, offering such a solution is unnecessary and it's up to the user to do it.
+
+The exception, however, is when the user stumbles into this problem *frequently enough* that having to do the simple solution every time becomes an annoyance. In this case, the software must offer a solution to simplify this use case.
+
+In our experience, in most cases it's usually obvious to tell when a problem is complex or frequent, but cases may arise where drawing this line is difficult. This is why discussing with other developers (next point) is always advised.
+
+#4: The solution must be discussed with others
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is often the case that, when users stumble upon problems, they are only immersed in their own project, so they will naturally try to solve the problem from their own perspective, thinking only about their use case.
+
+Because of this, user proposed solutions don't always contemplate other use cases that developers are often aware of, so they are often biased towards their own requirements.
+
+.. image:: img/best_practices4.png
+
+For developers, the perspective is different. They may find the user's problem too unique to justify a solution (instead of an user workaround), or maybe they will suggest a partial (usually simpler or lower level) solution that applies to a wider range of known problems, and leave the rest of the solution up to the user. 
+
+In any case, before attempting a contribution, it is important to discuss the actual problems with the other developers or contributors, so a better agreement on implementation can be reached. 
+
+The only exception, in this case, is when an area of code has a clear owner (agreed by the other contributors), who talks to users directly and has the most knowledge to implement a solution directly.
+
+#5: To each problem, its own solution
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For programmers, it is always a most enjoyable challenge to find the most optimal solutions to problems. Things, however, may go overboard sometimes and programmers will try to come up with solutions that solve as many problems as possible. 
+
+The situation will often take a turn for the worse when, in order to make this solution appear even more fantastic and flexible, the pure speculation-based problems (as described in #2) also make their appearance on stage.
+
+.. image:: img/best_practices5.png
+
+The main problem is that, in reality, it rarely works this way. Most of the time, just writing an individual solution to each problem results in code that is simpler and more maintainable.
+
+Additionally, solutions that target individual problems are better for the users, as they find something that does exactly what they need, without having to learn and remember a more complex system they will only need for simple tasks.
+
+Big and flexible solutions also have an additional drawback which is that, over time, they rarely are flexible enough for all users, which keep requesting more functions added (and making the API and codebase more and more complex).
+
+#6: Cater to common use cases, leave the door open for the rare ones
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is a continuation of the previous point, which further explains why this way of thinking and designing software is preferred.
+
+As mentioned before (in point #2), it is very difficult for us (as human beings who design software) to actually understand all future user needs. Trying to write very flexible structures that cater to many use cases at once is often a mistake. 
+
+We may come up with something we believe is brilliant, but when it's actually used, we will find that users will never even use half of it, or that they will require features that don't quite accommodate our original design, forcing us to either throw it away or make it even more complex.
+
+The question is then, how to design software that gives users what *we know they need*, but that is flexible enough to allow them to do *what we don't know they might need* in the future?
+
+.. image:: img/best_practices6.png
+
+The answer to this question is that, to ensure users still can do what they want to do, we need to give them access to a *low level API* that they can use to achieve what they want, even if it's more work for them because it means reimplementing some of the logic that already exists.
+
+In real-life scenarios, these use cases will be at most rare and uncommon anyway, so it makes sense a custom solution needs to be written. This is why it's important to still provide users the basic building blocks to do it.
+
+#7: Solutions must be local
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When looking for a solution to a problem, be it implementing a new feature or fixing a bug, sometimes the easiest path is to add data or a new function in the core layers of code.
+
+The main problem here is, adding something to the core layers that will only be used from a single location far away will not only make the code more difficult to follow (split in two), but also make the core API larger, more complex, more difficult to understand in general. 
+
+This is bad, because readability and cleanness of core APIs is always of extreme importance given how much code relies from it, and because it's key for new contributors as a starting point to learning the codebase.
+
+
+.. image:: img/best_practices7.png
+
+
+The common reasoning for wanting to do this is that it's usually less code to simply add a hack in the core layers.
+
+Despite this, this practice is not advised. Generally, the code for a solution should be closer to where the problem originates, even if it involves more code, duplicated, more complex or is less efficient. More creativity might be needed, but this path is always the advised one.
+
+#8: Don't use complex canned solutions for simple problems
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Not every problem has a simple solution and, many times, the right choice is to use a third party library to solve the problem.
+
+As Godot requires to be shipped in a large amount of platforms, we just can't link libraries dynamically. Instead, we bundle them in our source tree.
+
+.. image:: img/best_practices8.png
+
+As a result, we are very picky with what goes in, and we tend to prefer smaller libraries (in fact, single header ones are our favorite). Only in cases where there is no other choice we end up bundling something larger.

+ 4 - 4
community/contributing/code_style_guidelines.rst

@@ -158,8 +158,8 @@ Example:
     /*                           GODOT ENGINE                                */
     /*                      https://godotengine.org                          */
     /*************************************************************************/
-    /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
-    /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
+    /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+    /* Copyright (c) 2014-2020 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       */
@@ -203,8 +203,8 @@ Example:
     /*                           GODOT ENGINE                                */
     /*                      https://godotengine.org                          */
     /*************************************************************************/
-    /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
-    /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
+    /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+    /* Copyright (c) 2014-2020 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       */

+ 41 - 15
community/contributing/docs_writing_guidelines.rst

@@ -32,8 +32,8 @@ There are 3 rules to describe classes:
     the smallest and clearest sentences possible. These guidelines will help
     you work towards that goal.
 
-7 rules for a clear english
----------------------------
+7 rules for clear English
+-------------------------
 
 Use the direct voice
 ~~~~~~~~~~~~~~~~~~~~
@@ -438,11 +438,14 @@ Also surround boolean values, variable names and methods with ``[code][/code]``.
 Use ``[code]`` around arguments
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-In the class reference, always surround arguments with ``[code][/code]``. In the documentation and in Godot, it will display like ``this``. When you edit XML files in the Godot repository, replace existing arguments written like 'this' or \`this\` with ``[code]this[/code]``.
+In the class reference, always surround arguments with ``[code][/code]``. In the
+documentation and in Godot, it will display like ``this``. When you edit XML
+files in the Godot repository, replace existing arguments written like 'this' or
+\`this\` with ``[code]this[/code]``.
 
 
-Common vocabulary to use in godot's docs
-----------------------------------------
+Common vocabulary to use in Godot's documentation
+-------------------------------------------------
 
 The developers chose some specific words to refer to areas of the
 interface. They're used in the sources, in the documentation, and you
@@ -475,23 +478,46 @@ class names, which you can't fold, are ``Classes`` e.g. the
 ``properties``. E.g. ``position`` or ``modulate color`` are both
 ``properties``.
 
+Keyboard shortcut guidelines
+----------------------------
+
+Keyboard and mouse shortcuts should make use of the ``:kbd:`` tag, which allows
+shortcuts to stand out from the rest of the text and inline code. Use the
+compact form for modifier keys (:kbd:`Ctrl`/:kbd:`Cmd`) instead of their spelled
+out form (:kbd:`Control`/:kbd:`Command`). For combinations, use the ``+`` symbol
+with a space on either side of the symbol.
+
+Make sure to mention shortcuts that differ on macOS compared to other platforms.
+On macOS, ``Cmd`` often replaces ``Ctrl`` in keyboard shortcuts.
+
+Try to integrate the shortcut into sentences the best you can. Here are some
+examples with the ``:kbd:`` tag left as-is for better visibility:
+
+- Press ``:kbd:`Ctrl + Alt + T``` to toggle the panel (``:kbd:`Cmd + Alt + T``` on macOS).
+- Press ``:kbd:`Space``` and hold the left mouse button to pan in the 2D editor.
+- Press ``:kbd:`Shift + Up Arrow``` to move the node upwards by 8 pixels.
+
 Image contribution guidelines
 -----------------------------
 
-A significant part of the documentation is images, and there are several important
-guidelines to follow.
+A significant part of the documentation is images, and there are several
+important guidelines to follow.
 
-First, you should always be using the default editor theme and text when taking screenshots.
+First, you should always be using the default editor theme and text when taking
+screenshots.
 
-For 3D screenshots use 4xMSAA, enable anisotropic filtering on the projects textures,
-and set the anisotropic filter quality to 16x in Project Settings
+To improve the apperance of 3D screenshots, use 4× MSAA, enable anisotropic
+filtering on the project's textures, and set the anisotropic filter quality to
+16× in Project Settings.
 
-Screenshot size should not exceed 1920x1080.
+Screenshot sizes should not exceed 1920×1080 to ensure fast loading on slower
+connections.
 
 When you need to highlight an area of the editor to show something, like a
 button or option, use a 2 pixel thick outline without a bevel.
 
-Before you add or replace any images in the documentation, they should be run through
-a png compressor to save size. The built in lossless compressor in programs like Krita
-or Photoshop should be done. However you should also use a lossy one, such as `pngquant <https://pngquant.org/>`_
-where almost no image quality is lost during compression.
+Before you add or replace any images in the documentation, they should be run
+through a PNG compressor to save size. The built in lossless compressor in
+programs like Krita or Photoshop should be enough. For heavier images, also look
+into using a lossy compressor, such as `pngquant <https://pngquant.org/>`_ where
+almost no image quality is lost during compression.

BIN
community/contributing/img/best_practices1.png


BIN
community/contributing/img/best_practices2.png


BIN
community/contributing/img/best_practices3.png


BIN
community/contributing/img/best_practices4.png


BIN
community/contributing/img/best_practices5.png


BIN
community/contributing/img/best_practices6.png


BIN
community/contributing/img/best_practices7.png


BIN
community/contributing/img/best_practices8.png


+ 1 - 0
community/contributing/index.rst

@@ -6,6 +6,7 @@ Contributing
    :name: toc-community-contributing
 
    ways_to_contribute
+   best_practices_for_engine_contributors
    pr_workflow
    code_style_guidelines
    bug_triage_guidelines

+ 3 - 3
community/contributing/updating_the_class_reference.rst

@@ -186,17 +186,17 @@ Here's how a class looks like in XML:
 
     <class name="Node2D" inherits="CanvasItem" category="Core">
         <brief_description>
-        Base node for 2D system.
+            Base node for 2D system.
         </brief_description>
         <description>
-        Base node for 2D system. Node2D contains a position, rotation and scale, which is used to position and animate. It can alternatively be used with a custom 2D transform ([Matrix32]). A tree of Node2Ds allows complex hierarchies for animation and positioning.
+            Base node for 2D system. Node2D contains a position, rotation and scale, which is used to position and animate. It can alternatively be used with a custom 2D transform ([Matrix32]). A tree of Node2Ds allows complex hierarchies for animation and positioning.
         </description>
         <methods>
             <method name="set_pos">
                 <argument index="0" name="pos" type="Vector2">
                 </argument>
                 <description>
-                Set the position of the 2d node.
+                    Sets the position of the 2D node.
                 </description>
             </method>
             [...]

+ 16 - 15
community/tutorials.rst

@@ -5,7 +5,7 @@ Tutorials and resources
 
 This is a list of third-party tutorials and resources created by the Godot community. For resources, remember that there is the official `Godot Asset Library <https://godotengine.org/asset-library/asset>`_ full of official and community resources too! Also have a look at this `huge list over at Reddit <https://www.reddit.com/r/godot/comments/an0iq5/godot_tutorials_list_of_video_and_written/>`_.
 
-Think there is something missing here? Feel free to submit a `Pull Request <https://github.com/godotengine/godot-docs/blob/master/community/resources.rst>`_ as always.
+Think there is something missing here? Feel free to submit a `Pull Request <https://github.com/godotengine/godot-docs/blob/master/community/tutorials.rst>`_ as always.
 
 Where to start
 --------------
@@ -19,20 +19,21 @@ Some of the others mentioned below provide more advanced tutorials, e.g. on 3D o
 Video tutorials
 ---------------
 
-- `Emilio <https://www.youtube.com/channel/UC9DR22-qohBDtZ74R3FxOZg>`_
-- `GDQuest <https://www.youtube.com/channel/UCxboW7x0jZqFdvMdCFKTMsQ/playlists>`_
-- `Game Endeavor <https://www.youtube.com/channel/UCLweX1UtQjRjj7rs_0XQ2Eg/videos>`_
-- `Game from Scratch <https://www.youtube.com/watch?v=iDEcP8Mc-7s&list=PLS9MbmO_ssyDk79j9ewONxV88fD5e_o5d>`_
-- `HeartBeast <https://www.youtube.com/watch?v=wETY5_9kFtA&list=PL9FzW-m48fn2jlBu_0DRh7PvAt-GULEmd>`_
-- `Jeremy Bullock <https://www.youtube.com/channel/UCwJw2-V5S1TkBjLQ3_Ws54g>`_
-- `KidsCanCode <https://www.youtube.com/channel/UCNaPQ5uLX5iIEHUCLmfAgKg/playlists>`__
-- `Mister Taft Creates <https://www.youtube.com/playlist?list=PL4vbr3u7UKWqwQlvwvgNcgDL1p_3hcNn2>`_
-- `Miziziziz <https://www.youtube.com/playlist?list=PLmugv6_kd0qN6AyjG245_Pdak4MXKUx88>`_
-- `P1X / Krzysztof Jankowski <https://www.youtube.com/playlist?list=PLvDk7UKhld4xGPovdB4IFtAHYMYjx_-3K>`_
-- `Pigdev <https://www.youtube.com/playlist?list=PLPMN4vCRFdordS3E-3zi0Hdh7pAsbWQ6a>`_
-- `Steincodes <https://www.youtube.com/c/steincodes/playlists>`__
-- `Code with Tom <https://www.youtube.com/playlist?list=PLiUQR4U_J9ec0k91iHPme_qtfS1nrWF3W>`_
-- `BornCG <https://www.youtube.com/playlist?list=PLda3VoSoc_TSBBOBYwcmlamF1UrjVtccZ>`_
+- `Emilio <https://www.youtube.com/channel/UC9DR22-qohBDtZ74R3FxOZg>`_ (2D, GDScript and VisualScript).
+- `GDQuest <https://www.youtube.com/channel/UCxboW7x0jZqFdvMdCFKTMsQ/playlists>`_ (2D and 3D, GDScript, VisualScript and C#).
+- `Game Endeavor <https://www.youtube.com/channel/UCLweX1UtQjRjj7rs_0XQ2Eg/videos>`_ (2D, GDScript).
+- `Game from Scratch <https://www.youtube.com/watch?v=iDEcP8Mc-7s&list=PLS9MbmO_ssyDk79j9ewONxV88fD5e_o5d>`_ (2D and 3D, GDScript and C#).
+- `HeartBeast <https://www.youtube.com/watch?v=wETY5_9kFtA&list=PL9FzW-m48fn2jlBu_0DRh7PvAt-GULEmd>`_ (2D, GDScript).
+- `Jeremy Bullock <https://www.youtube.com/channel/UCwJw2-V5S1TkBjLQ3_Ws54g>`_ (2D and 3D, GDScript, VisualScript and C#).
+- `KidsCanCode <https://www.youtube.com/channel/UCNaPQ5uLX5iIEHUCLmfAgKg/playlists>`__ (2D and 3D, GDScript and VisualScript).
+- `Mister Taft Creates <https://www.youtube.com/playlist?list=PL4vbr3u7UKWqwQlvwvgNcgDL1p_3hcNn2>`_ (2D, GDScript).
+- `Miziziziz <https://www.youtube.com/playlist?list=PLmugv6_kd0qN6AyjG245_Pdak4MXKUx88>`_ (2D, GDScript).
+- `P1X / Krzysztof Jankowski <https://www.youtube.com/playlist?list=PLvDk7UKhld4xGPovdB4IFtAHYMYjx_-3K>`_ (3D).
+- `Pigdev <https://www.youtube.com/playlist?list=PLPMN4vCRFdordS3E-3zi0Hdh7pAsbWQ6a>`_ (2D, GDScript).
+- `Steincodes <https://www.youtube.com/c/steincodes/playlists>`__ (2D, GDScript and VisualScript).
+- `TheBuffED <https://www.youtube.com/watch?v=ygGaN1EOQEA&list=PLvN5Z3tTxXEDfQkt4Frg6ALirespSwZd7>`_ (2D, GDScript).
+- `Code with Tom <https://www.youtube.com/playlist?list=PLiUQR4U_J9ec0k91iHPme_qtfS1nrWF3W>`_ (2D and 3D, GDScript).
+- `BornCG <https://www.youtube.com/playlist?list=PLda3VoSoc_TSBBOBYwcmlamF1UrjVtccZ>`_ (3D, GDScript).
 
 Text tutorials
 --------------

+ 60 - 50
conf.py

@@ -2,109 +2,114 @@
 #
 # Godot Engine documentation build configuration file
 
+import sphinx_rtd_theme
 import sys
 import os
 
 # -- General configuration ------------------------------------------------
 
-needs_sphinx = '1.3'
+needs_sphinx = "1.3"
 
 # Sphinx extension module names and templates location
-sys.path.append(os.path.abspath('extensions'))
-extensions = ['gdscript', 'sphinx_tabs.tabs', 'sphinx.ext.imgmath']
+sys.path.append(os.path.abspath("extensions"))
+extensions = ["gdscript", "sphinx_tabs.tabs", "sphinx.ext.imgmath"]
 
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 # You can specify multiple suffix as a list of string: ['.rst', '.md']
-source_suffix = '.rst'
-source_encoding = 'utf-8-sig'
+source_suffix = ".rst"
+source_encoding = "utf-8-sig"
 
 # The master toctree document
-master_doc = 'index'
+master_doc = "index"
 
 # General information about the project
-project = 'Godot Engine'
-copyright = '2014-2020, Juan Linietsky, Ariel Manzur and the Godot community (CC-BY 3.0)'
-author = 'Juan Linietsky, Ariel Manzur and the Godot community'
+project = "Godot Engine"
+copyright = (
+    "2014-2020, Juan Linietsky, Ariel Manzur and the Godot community (CC-BY 3.0)"
+)
+author = "Juan Linietsky, Ariel Manzur and the Godot community"
 
 # Version info for the project, acts as replacement for |version| and |release|
 # The short X.Y version
-version = 'latest'
+version = "latest"
 # The full version, including alpha/beta/rc tags
-release = 'latest'
+release = "latest"
 
 # Parse Sphinx tags passed from RTD via environment
-env_tags = os.getenv('SPHINX_TAGS')
-if env_tags != None:
-   for tag in env_tags.split(','):
-       print("Adding Sphinx tag: %s" % tag.strip())
-       tags.add(tag.strip())
+env_tags = os.getenv("SPHINX_TAGS")
+if env_tags is not None:
+    for tag in env_tags.split(","):
+        print("Adding Sphinx tag: %s" % tag.strip())
+        tags.add(tag.strip())  # noqa: F821
 
 # Language / i18n
-language = os.getenv('READTHEDOCS_LANGUAGE', 'en')
-is_i18n = tags.has('i18n')
+language = os.getenv("READTHEDOCS_LANGUAGE", "en")
+is_i18n = tags.has("i18n")  # noqa: F821
 
-exclude_patterns = ['_build']
+exclude_patterns = ["_build"]
 
+# fmt: off
+# These imports should *not* be moved to the start of the file,
+# they depend on the sys.path.append call registering "extensions".
 # GDScript syntax highlighting
 from gdscript import GDScriptLexer
 from sphinx.highlighting import lexers
-lexers['gdscript'] = GDScriptLexer()
+
+lexers["gdscript"] = GDScriptLexer()
+# fmt: on
 
 # Pygments (syntax highlighting) style to use
-pygments_style = 'sphinx'
-highlight_language = 'gdscript'
+pygments_style = "sphinx"
+highlight_language = "gdscript"
 
 # -- Options for HTML output ----------------------------------------------
 
 # on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org
-on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
+on_rtd = os.environ.get("READTHEDOCS", None) == "True"
 
-import sphinx_rtd_theme
-html_theme = 'sphinx_rtd_theme'
+
+html_theme = "sphinx_rtd_theme"
 html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
 if on_rtd:
     using_rtd_theme = True
 
 # Theme options
 html_theme_options = {
-    # 'typekit_id': 'hiw1hhg',
-    # 'analytics_id': '',
-    # 'sticky_navigation': True  # Set to False to disable the sticky nav while scrolling.
-    'logo_only': True,  # if we have a html_logo below, this shows /only/ the logo with no title text
-    'collapse_navigation': False,  # Collapse navigation (False makes it tree-like)
-    # 'display_version': True,  # Display the docs version
-    # 'navigation_depth': 4,  # Depth of the headers shown in the navigation bar
+    # if we have a html_logo below, this shows /only/ the logo with no title text
+    "logo_only": True,
+    # Collapse navigation (False makes it tree-like)
+    "collapse_navigation": False,
 }
 
 # VCS options: https://docs.readthedocs.io/en/latest/vcs.html#github
 html_context = {
-    "display_github": not is_i18n, # Integrate GitHub
-    "github_user": "godotengine", # Username
-    "github_repo": "godot-docs", # Repo name
-    "github_version": "master", # Version
-    "conf_py_path": "/", # Path in the checkout to the docs root
+    "display_github": not is_i18n,  # Integrate GitHub
+    "github_user": "godotengine",  # Username
+    "github_repo": "godot-docs",  # Repo name
+    "github_version": "master",  # Version
+    "conf_py_path": "/",  # Path in the checkout to the docs root
 }
 
-html_logo = 'img/docs_logo.png'
+html_logo = "img/docs_logo.png"
 
 # These folders are copied to the documentation's HTML output
-html_static_path = ['_static']
+html_static_path = ["_static"]
 
-html_extra_path = ['robots.txt']
+html_extra_path = ["robots.txt"]
 
 # These paths are either relative to html_static_path
 # or fully qualified paths (eg. https://...)
 html_css_files = [
-    'css/custom.css',
+    "css/custom.css",
 ]
 
 html_js_files = [
-    'js/custom.js',
+    "js/custom.js",
 ]
 
 # Output file base name for HTML help builder
-htmlhelp_basename = 'GodotEnginedoc'
+htmlhelp_basename = "GodotEnginedoc"
 
 # -- Options for reStructuredText parser ----------------------------------
 
@@ -117,8 +122,13 @@ file_insertion_enabled = False
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-  (master_doc, 'GodotEngine.tex', 'Godot Engine Documentation',
-   'Juan Linietsky, Ariel Manzur and the Godot community', 'manual'),
+    (
+        master_doc,
+        "GodotEngine.tex",
+        "Godot Engine Documentation",
+        "Juan Linietsky, Ariel Manzur and the Godot community",
+        "manual",
+    ),
 ]
 
 # -- Options for linkcheck builder ----------------------------------------
@@ -130,7 +140,7 @@ linkcheck_timeout = 10
 
 # -- I18n settings --------------------------------------------------------
 
-locale_dirs = ['../sphinx/po/']
+locale_dirs = ["../sphinx/po/"]
 gettext_compact = False
 
 # Couldn't find a way to retrieve variables nor do advanced string
@@ -142,10 +152,10 @@ rst_epilog = """
     :alt: Translation status
     :target: https://hosted.weblate.org/engage/godot-engine{target_locale}/?utm_source=widget
 """.format(
-    image_locale='-' if language == 'en' else language,
-    target_locale='' if language == 'en' else '/' + language
+    image_locale="-" if language == "en" else language,
+    target_locale="" if language == "en" else "/" + language,
 )
 
 # Exclude class reference when marked with tag i18n.
 if is_i18n:
-    exclude_patterns = ['classes']
+    exclude_patterns = ["classes"]

+ 1 - 1
development/compiling/compiling_for_android.rst

@@ -60,7 +60,7 @@ to the same path, especially if you are using custom Android modules,
 since some Gradle plugins rely on the NDK and use this variable to
 determine its location.
 
-To set those environment variables on Windows, press **Windows + R**, type
+To set those environment variables on Windows, press :kbd:`Windows + R`, type
 "control system", then click on **Advanced system settings** in the left
 pane, then click on **Environment variables** on the window that
 appears.

+ 32 - 48
development/compiling/compiling_for_osx.rst

@@ -8,13 +8,21 @@ Compiling for macOS
 Requirements
 ------------
 
-For compiling under Linux or other Unix variants, the following is
-required:
+For compiling under macOS, the following is required:
 
--  Python 2.7+ or Python 3.5+
--  SCons build system
--  Xcode (or the more lightweight Command Line Tools for Xcode)
--  *Optional* - yasm (for WebM SIMD optimizations)
+- Python 3.5+ (recommended) or Python 2.7+.
+- `SCons <https://www.scons.org>`_ build system.
+- `Xcode <https://apps.apple.com/us/app/xcode/id497799835>`_
+  (or the more lightweight Command Line Tools for Xcode).
+- *Optional* - `yasm <https://yasm.tortall.net/>`_ (for WebM SIMD optimizations).
+
+.. note:: If you have `Homebrew <https://brew.sh/>`_ installed, you can easily
+          install SCons and yasm using the following command::
+
+              brew install scons yasm
+
+          Installing Homebrew will also fetch the Command Line Tools
+          for Xcode automatically if you don't have them already.
 
 .. seealso:: For a general overview of SCons usage for Godot, see
              :ref:`doc_introduction_to_the_buildsystem`.
@@ -22,55 +30,37 @@ required:
 Compiling
 ---------
 
-Start a terminal, go to the root dir of the engine source code and type:
-
-::
+Start a terminal, go to the root directory of the engine source code and type::
 
     scons platform=osx --jobs=$(sysctl -n hw.logicalcpu)
 
 If all goes well, the resulting binary executable will be placed in the
-"bin" subdirectory. This executable file contains the whole engine and
+``bin/`` subdirectory. This executable file contains the whole engine and
 runs without any dependencies. Executing it will bring up the project
 manager.
 
 To create an .app like in the official builds, you need to use the template
-located in ``misc/dist/osx_tools.app``. Typically, for a ".64" optimised binary
-built with `scons p=osx target=release_debug`:
-
-::
+located in ``misc/dist/osx_tools.app``. Typically, for an optimized editor
+binary built with ``scons p=osx target=release_debug``::
 
     user@host:~/godot$ cp -r misc/dist/osx_tools.app ./Godot.app
     user@host:~/godot$ mkdir -p Godot.app/Contents/MacOS
     user@host:~/godot$ cp bin/godot.osx.tools.64 Godot.app/Contents/MacOS/Godot
     user@host:~/godot$ chmod +x Godot.app/Contents/MacOS/Godot
 
-Compiling for 32 and 64-bit
----------------------------
-
-All macOS versions after 10.6 are 64-bit exclusive, so the executable
-will be a ".64" file by default for most users. If you would like to
-compile a ".fat" executable which contains both 32 and 64-bit code,
-you can do so by specifying the bits in the scons command like so:
-
-::
+Cross-compiling for macOS from Linux
+------------------------------------
 
-    user@host:~/godot$ scons platform=osx bits=fat
+It is possible to compile for macOS in a Linux environment (and maybe also in
+Windows using the Windows Subsystem for Linux). For that, you'll need to install
+`OSXCross <https://github.com/tpoechtrager/osxcross>`__ to be able to use macOS
+as a target. First, follow the instructions to install it:
 
-Cross-compiling
----------------
+Clone the `OSXCross repository <https://github.com/tpoechtrager/osxcross>`__
+somewhere on your machine (or download a ZIP file and extract it somewhere),
+e.g.::
 
-It is possible to compile for macOS in a Linux environment (and maybe
-also in Windows with Cygwin). For that you will need
-`OSXCross <https://github.com/tpoechtrager/osxcross>`__ to be able
-to use macOS as target. First, follow the instructions to install it:
-
-Clone the `OSXCross repository <https://github.com/tpoechtrager/osxcross>`
-somewhere on your machine (or download a zip file and extract it somewhere),
-e.g.:
-
-::
-
-    user@host:~$ git clone https://github.com/tpoechtrager/osxcross.git /home/myuser/sources/osxcross
+    user@host:~$ git clone --depth=1 https://github.com/tpoechtrager/osxcross.git "$HOME/osxcross"
 
 1. Follow the instructions to package the SDK:
    https://github.com/tpoechtrager/osxcross#packaging-the-sdk
@@ -79,20 +69,14 @@ e.g.:
 
 After that, you will need to define the ``OSXCROSS_ROOT`` as the path to
 the OSXCross installation (the same place where you cloned the
-repository/extracted the zip), e.g.:
+repository/extracted the zip), e.g.::
 
-::
+    user@host:~$ export OSXCROSS_ROOT="$HOME/osxcross"
 
-    user@host:~$ export OSXCROSS_ROOT=/home/myuser/sources/osxcross
-
-Now you can compile with SCons like you normally would:
-
-::
+Now you can compile with SCons like you normally would::
 
     user@host:~/godot$ scons platform=osx
 
-If you have an OSXCross SDK version different from the one expected by the SCons buildsystem, you can specify a custom one with the ``osxcross_sdk`` argument:
-
-::
+If you have an OSXCross SDK version different from the one expected by the SCons buildsystem, you can specify a custom one with the ``osxcross_sdk`` argument::
 
     user@host:~/godot$ scons platform=osx osxcross_sdk=darwin15

+ 2 - 2
development/compiling/compiling_for_uwp.rst

@@ -139,6 +139,6 @@ to build it at least once to generate some needed files, you can do so by
 right-clicking the project (*not* the solution) in the "Solution Explorer" and
 selecting "Build".
 
-Now you can just run the project and your app should open. You can use also
-the "Start Without Debugging" from the "Debug" menu (Ctrl+F5) to make it
+Now you can just run the project and your app should open. You can also use
+the "Start Without Debugging" option from the "Debug" menu (or press :kbd:`Ctrl + F5`) to make it
 launch faster.

+ 23 - 0
development/compiling/compiling_for_x11.rst

@@ -114,6 +114,11 @@ manager.
           make the final executable smaller and faster by adding the
           SCons option ``target=release_debug``.
 
+          If you are compiling Godot with GCC, you can make the binary
+          even smaller and faster by adding the SCons option ``use_lto=yes``.
+          As link-time optimization is a memory-intensive process,
+          this will require about 3 GB of available RAM while compiling.
+
 Building export templates
 -------------------------
 
@@ -169,3 +174,21 @@ here:
 You don't even need to copy them, you can just reference the resulting
 files in the ``bin/`` directory of your Godot source folder, so the next
 time you build, you automatically have the custom templates referenced.
+
+Using Clang and LLD for faster development
+------------------------------------------
+
+You can also use Clang and LLD to build Godot. This has two upsides compared to
+the default GCC + GNU ld setup:
+
+- LLD links Godot significantly faster compared to GNU ld or gold. This leads to
+  faster iteration times.
+- Clang tends to give more useful error messages compared to GCC.
+
+To do so, install Clang and the ``lld`` package from your distribution's package manager
+then use the following SCons command::
+
+    user@host:~/godot$ scons platform=x11 use_llvm=yes use_lld=yes
+
+It's still recommended to use GCC for production builds as they can be compiled using
+link-time optimization, making the resulting binaries smaller and faster.

+ 6 - 1
development/compiling/optimizing_for_size.rst

@@ -56,7 +56,12 @@ a lot of them:
 
 ::
 
-    scons p=windows target=release tools=no module_bmp_enabled=no module_bullet_enabled=no module_csg_enabled=no module_dds_enabled=no module_enet_enabled=no module_etc_enabled=no module_gdnative_enabled=no module_gridmap_enabled=no module_hdr_enabled=no module_mbedtls_enabled=no module_mobile_vr_enabled=no module_opus_enabled=no module_pvr_enabled=no module_recast_enabled=no module_regex_enabled=no module_squish_enabled=no module_tga_enabled=no module_thekla_unwrap_enabled=no module_theora_enabled=no module_tinyexr_enabled=no module_vorbis_enabled=no module_webm_enabled=no module_websocket_enabled=no
+    scons p=windows target=release tools=no module_arkit_enabled=no module_assimp_enabled=no module_bmp_enabled=no module_bullet_enabled=no module_camera_enabled=no module_csg_enabled=no module_dds_enabled=no module_enet_enabled=no module_etc_enabled=no module_gdnative_enabled=no module_gridmap_enabled=no module_hdr_enabled=no module_jsonrpc_enabled=no module_mbedtls_enabled=no module_mobile_vr_enabled=no module_opensimplex_enabled=no module_opus_enabled=no module_pvr_enabled=no module_recast_enabled=no module_regex_enabled=no module_squish_enabled=no module_svg_enabled=no module_tga_enabled=no module_theora_enabled=no module_tinyexr_enabled=no module_upnp_enabled=no module_vhacd_enabled=no module_vorbis_enabled=no module_webm_enabled=no module_webp_enabled=no module_webrtc_enabled=no module_websocket_enabled=no module_xatlas_unwrap_enabled=no
+
+If this proves not to work for your use case, you should review the list of
+modules and see which ones you actually still need for your game (e.g. you
+might want to keep networking-related modules, regex support, or theora/webm
+to play videos).
 
 Optimizing for size instead of speed
 ------------------------------------

+ 5 - 5
development/cpp/configuring_an_ide.rst

@@ -270,12 +270,12 @@ Visual Studio Code
 
 - Ensure that C/C++ extension is installed. You can find instructions in `docs <https://code.visualstudio.com/docs/languages/cpp>`_.
 
-- Now open cloned godot folder in VS Code (File > Open Folder...)
+- Open cloned godot folder in VS Code with ``File > Open Folder...``
 
-In order to build the project, we need two configuration files: *launch.json* and *tasks.json*.
+In order to build the project, you need two configuration files: *launch.json* and *tasks.json*.
 To create them:
 
-- Open Debug view (Ctrl + Shift + D) and select cogwheel with an orange dot:
+- Open *Debug* view by pressing :kbd:`Ctrl + Shift + D` and select cogwheel with an orange dot:
 
 .. image:: img/vscode_1_create_launch.json.png
 
@@ -287,7 +287,7 @@ To create them:
 
 (Note that *godot.x11.tools.64* in "program" value might be named differently on macOS or Windows)
 
-- Create *tasks.json* by starting the Debug process (F5). VS Code will show a dialog with a *Configure Task* button. Tap it and select *Create tasks.json file from template*, then select *Others*
+- Create *tasks.json* by starting the Debug process with :kbd:`F5`. VS Code will show a dialog with a *Configure Task* button. Tap it and select *Create tasks.json file from template*, then select *Others*
 
 - Update *tasks.json* to match:
 
@@ -305,7 +305,7 @@ To create them:
 Android Studio
 --------------
 
-`Android Studio <https://developer.android.com/studio>`_ is a `Jetbrain <https://www.jetbrains.com/>`_ IDE for Android development. It has a feature-rich editor which supports Java and C/C++, so it can be used for development of the Godot core engine, and Android platform codebases.
+`Android Studio <https://developer.android.com/studio>`_ is a `JetBrains <https://www.jetbrains.com/>`_ IDE for Android development. It has a feature-rich editor which supports Java and C/C++, so it can be used for development of the Godot core engine, and Android platform codebases.
 
 Project setup
 ^^^^^^^^^^^^^

+ 76 - 0
development/cpp/custom_modules_in_cpp.rst

@@ -257,6 +257,82 @@ The output will be ``60``.
              template. See the :ref:`Compiling <toc-devel-compiling>` pages
              for more information.
 
+Customizing module types initialization
+---------------------------------------
+
+Modules can interact with other built-in engine classes during runtime and even
+affect the way core types are initialized. So far, we've been using
+``register_summator_types`` as a way to bring in module classes to be available
+within the engine.
+
+A crude order of the engine setup can be summarized as a list of the following
+type registration methods:
+
+.. code-block:: cpp
+
+    preregister_module_types();
+    preregister_server_types();
+    register_core_singletons();
+    register_server_types();
+    register_scene_types();
+    EditorNode::register_editor_types();
+    register_platform_apis();
+    register_module_types();
+    initialize_physics();
+    initialize_navigation_server();
+    register_server_singletons();
+    register_driver_types();
+    ScriptServer::init_languages();
+
+Our ``Summator`` class is initialized during the ``register_module_types()``
+call. Imagine that we need to satisfy some common module run-time dependency
+(like singletons), or allow us to override existing engine method callbacks
+before they can be assigned by the engine itself. In that case, we want to
+ensure that our module classes are registered *before* any other built-in type.
+
+This is where we can define an optional ``preregister_summator_types()``
+method which will be called before anything else during the
+``preregister_module_types()`` engine setup stage.
+
+We now need to add this method to ``register_types`` header and source files:
+
+.. code-block:: cpp
+
+    /* register_types.h */
+
+    #define MODULE_SUMMATOR_HAS_PREREGISTER
+    void preregister_summator_types();
+
+    void register_summator_types();
+    void unregister_summator_types();
+
+.. note:: Unlike other register methods, we have to explicitly define
+          ``MODULE_SUMMATOR_HAS_PREREGISTER`` to let the build system know what
+          relevant method calls to include at compile time. The module's name
+          has to be converted to uppercase as well.
+
+.. code-block:: cpp
+
+    /* register_types.cpp */
+
+    #include "register_types.h"
+
+    #include "core/class_db.h"
+    #include "summator.h"
+
+    void preregister_summator_types() {
+        // Called before any other core types are registered.
+        // Nothing to do here in this example.
+    }
+
+    void register_summator_types() {
+        ClassDB::register_class<Summator>();
+    }
+
+    void unregister_summator_types() {
+       // Nothing to do here in this example.
+    }
+
 Improving the build system for development
 ------------------------------------------
 

+ 251 - 138
development/cpp/custom_resource_format_loaders.rst

@@ -18,7 +18,7 @@ References
 ~~~~~~~~~~
 
 - :ref:`ResourceLoader<class_resourceloader>`
-- `core/io/resource_loader.cpp <https://github.com/godotengine/godot/blob/master/core/io/resource_loader.cpp#L258>`__
+- `core/io/resource_loader.cpp <https://github.com/godotengine/godot/blob/master/core/io/resource_loader.cpp>`_
 
 What for?
 ---------
@@ -38,7 +38,7 @@ ImageFormatLoader should be used to load images.
 References
 ~~~~~~~~~~
 
-- `core/io/image_loader.h <https://github.com/godotengine/godot/blob/master/core/io/image_loader.h>`__
+- `core/io/image_loader.h <https://github.com/godotengine/godot/blob/master/core/io/image_loader.h>`_
 
 
 Creating a ResourceFormatLoader
@@ -57,54 +57,102 @@ read and handle data serialization.
 
 .. code-block:: cpp
 
-	#ifndef MY_JSON_LOADER_H
-	#define MY_JSON_LOADER_H
+    /* resource_loader_json.h */
 
-	#include "core/io/resource_loader.h"
+    #ifndef RESOURCE_LOADER_JSON_H
+    #define RESOURCE_LOADER_JSON_H
 
-	class ResourceFormatLoaderMyJson : public ResourceFormatLoader {
-	public:
-		virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL);
-		virtual void get_recognized_extensions(List<String> *p_extensions) const;
-		virtual bool handles_type(const String &p_type) const;
-		virtual String get_resource_type(const String &p_path) const;
+    #include "core/io/resource_loader.h"
 
-		ResourceFormatLoaderMyJson();
-		virtual ~ResourceFormatLoaderMyJson() {}
-	};
-	#endif // MY_JSON_LOADER_H
+    class ResourceFormatLoaderJson : public ResourceFormatLoader {
+    	GDCLASS(ResourceFormatLoaderJson, ResourceFormatLoader);
+    public:
+    	virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL);
+    	virtual void get_recognized_extensions(List<String> *r_extensions) const;
+    	virtual bool handles_type(const String &p_type) const;
+    	virtual String get_resource_type(const String &p_path) const;
+    };
+    #endif // RESOURCE_LOADER_JSON_H
 
 .. code-block:: cpp
 
-	#include "my_json_loader.h"
-	#include "my_json.h"
+    /* resource_loader_json.cpp */
 
-	ResourceFormatLoaderMyJson::ResourceFormatLoaderMyJson() {
-	}
+    #include "resource_loader_json.h"
 
-	RES ResourceFormatLoaderMyJson::load(const String &p_path, const String &p_original_path, Error *r_error) {
-		MyJson *my = memnew(MyJson);
-		if (r_error)
-			*r_error = OK;
-		Error err = my->set_file(p_path);
-		return Ref<MyJson>(my);
-	}
+    #include "resource_json.h"
 
-	void ResourceFormatLoaderMyJson::get_recognized_extensions(List<String> *p_extensions) const {
-		p_extensions->push_back("mjson");
-	}
+    RES ResourceFormatLoaderJson::load(const String &p_path, const String &p_original_path, Error *r_error) {
+    Ref<JsonResource> json = memnew(JsonResource);
+    	if (r_error) {
+    		*r_error = OK;
+    	}
+    	Error err = json->load_file(p_path);
+    	return json;
+    }
+
+    void ResourceFormatLoaderJson::get_recognized_extensions(List<String> *r_extensions) const {
+    	if (!r_extensions->find("json")) {
+    		r_extensions->push_back("json");
+    	}
+    }
+
+    String ResourceFormatLoaderJson::get_resource_type(const String &p_path) const {
+    	return "Resource";
+    }
+
+    bool ResourceFormatLoaderJson::handles_type(const String &p_type) const {
+    	return ClassDB::is_parent_class(p_type, "Resource");
+    }
+
+Creating a ResourceFormatSaver
+------------------------------
 
-	String ResourceFormatLoaderMyJson::get_resource_type(const String &p_path) const {
+If you'd like to be able to edit and save a resource, you can implement a
+``ResourceFormatSaver``:
 
-		if (p_path.get_extension().to_lower() == "mjson")
-			return "MyJson";
-		return "";
-	}
+.. code-block:: cpp
+
+    /* resource_saver_json.h */
+
+    #ifndef RESOURCE_SAVER_JSON_H
+    #define RESOURCE_SAVER_JSON_H
+
+    #include "core/io/resource_saver.h"
+
+    class ResourceFormatSaverJson : public ResourceFormatSaver {
+    	GDCLASS(ResourceFormatSaverJson, ResourceFormatSaver);
+    public:
+    	virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
+    	virtual bool recognize(const RES &p_resource) const;
+    	virtual void get_recognized_extensions(const RES &p_resource, List<String> *r_extensions) const;
+    };
+    #endif // RESOURCE_SAVER_JSON_H
+
+.. code-block:: cpp
 
-	bool ResourceFormatLoaderMyJson::handles_type(const String &p_type) const {
-		return (p_type == "MyJson");
-	}
+    /* resource_saver_json.cpp */
 
+    #include "resource_saver_json.h"
+
+    #include "resource_json.h"
+    #include "scene/resources/resource_format_text.h"
+
+    Error ResourceFormatSaverJson::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+    	Ref<JsonResource> json = memnew(JsonResource);
+    	Error error = json->save_file(p_path, p_resource);
+    	return error;
+    }
+
+    bool ResourceFormatSaverJson::recognize(const RES &p_resource) const {
+    	return Object::cast_to<JsonResource>(*p_resource) != NULL;
+    }
+
+    void ResourceFormatSaverJson::get_recognized_extensions(const RES &p_resource, List<String> *r_extensions) const {
+    	if (Object::cast_to<JsonResource>(*p_resource)) {
+    		r_extensions->push_back("json");
+    	}
+    }
 
 Creating custom data types
 --------------------------
@@ -113,62 +161,102 @@ Godot may not have a proper substitute within its :ref:`doc_core_types`
 or managed resources. Godot needs a new registered data type to
 understand additional binary formats such as machine learning models.
 
-Here is an example of how to create a custom datatype
+Here is an example of creating a custom datatype:
 
 .. code-block:: cpp
 
-	#ifndef MY_JSON_H
-	#define MY_JSON_H
-
-	#include "core/dictionary.h"
-	#include "core/io/json.h"
-	#include "core/reference.h"
-	#include "core/variant.h"
-	#include "core/variant_parser.h"
-
-	class MyJson : public Resource {
-		GDCLASS(MyJson, Resource);
-
-	protected:
-		static void _bind_methods() {
-			ClassDB::bind_method(D_METHOD("to_string"), &MyJson::to_string);
-		}
-
-	private:
-		Dictionary dict;
-
-	public:
-		Error set_file(const String &p_path) {
-			Error error_file;
-			FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &error_file);
-
-			String buf = String("");
-			while (!file->eof_reached()) {
-				buf += file->get_line();
-			}
-			String err_string;
-			int err_line;
-			JSON cmd;
-			Variant ret;
-			Error err = cmd.parse(buf, ret, err_string, err_line);
-			dict = Dictionary(ret);
-			file->close();
-			return OK;
-		}
-
-		String to_string() const {
-			return String(*this);
-		}
-
-		operator String() const {
-			JSON a;
-			return a.print(dict);
-		}
-
-		MyJson() {};
-		~MyJson() {};
-	};
-	#endif // MY_JSON_H
+    /* resource_json.h */
+
+    #ifndef RESOURCE_JSON_H
+    #define RESOURCE_JSON_H
+
+    #include "core/io/json.h"
+    #include "core/variant_parser.h"
+
+    class JsonResource : public Resource {
+    	GDCLASS(JsonResource, Resource);
+
+    protected:
+    	static void _bind_methods() {
+    		ClassDB::bind_method(D_METHOD("set_dict", "dict"), &JsonResource::set_dict);
+    		ClassDB::bind_method(D_METHOD("get_dict"), &JsonResource::get_dict);
+
+    		ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "content"), "set_dict", "get_dict");
+    	}
+
+    private:
+    	Dictionary content;
+
+    public:
+    	Error load_file(const String &p_path);
+    	Error save_file(const String &p_path, const RES &p_resource);
+
+    	void set_dict(const Dictionary &p_dict);
+    	Dictionary get_dict();
+    };
+    #endif // RESOURCE_JSON_H
+
+.. code-block:: cpp
+
+    /* resource_json.cpp */
+
+    #include "resource_json.h"
+
+    Error JsonResource::load_file(const String &p_path) {
+    	Error error;
+    	FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &error);
+    	if (error != OK) {
+    		if (file) {
+    			file->close();
+    		}
+    		return error;
+    	}
+
+    	String json_string = String("");
+    	while (!file->eof_reached()) {
+    		json_string += file->get_line();
+    	}
+    	file->close();
+
+    	String error_string;
+    	int error_line;
+    	JSON json;
+    	Variant result;
+    	error = json.parse(json_string, result, error_string, error_line);
+    	if (error != OK) {
+    		file->close();
+    		return error;
+    	}
+
+    	content = Dictionary(result);
+    	return OK;
+    }
+
+    Error JsonResource::save_file(const String &p_path, const RES &p_resource) {
+    	Error error;
+    	FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &error);
+    	if (error != OK) {
+    		if (file) {
+    			file->close();
+    		}
+    		return error;
+    	}
+
+    	Ref<JsonResource> json_ref = p_resource.get_ref_ptr();
+    	JSON json;
+
+    	file->store_string(json.print(json_ref->get_dict(), "    "));
+    	file->close();
+    	return OK;
+    }
+
+    void JsonResource::set_dict(const Dictionary &p_dict) {
+    	content = p_dict;
+    }
+
+    Dictionary JsonResource::get_dict() {
+    	return content;
+    }
 
 Considerations
 ~~~~~~~~~~~~~~
@@ -181,40 +269,42 @@ calls into ``std::istream``.
 
 .. code-block:: cpp
 
-	#include <istream>
-	#include <streambuf>
-
-	class GodotFileInStreamBuf : public std::streambuf {
-
-	public:
-		GodotFileInStreamBuf(FileAccess *fa) {
-			_file = fa;
-		}
-		int underflow() {
-			if (_file->eof_reached()) {
-				return EOF;
-			} else {
-				size_t pos = _file->get_position();
-				uint8_t ret = _file->get_8();
-				_file->seek(pos); // required since get_8() advances the read head
-				return ret;
-			}
-		}
-		int uflow() {
-			return _file->eof_reached() ?  EOF : _file->get_8();
-		}
-
-	private:
-		FileAccess *_file;
-	};
+    #include "core/os/file_access.h"
+
+    #include <istream>
+    #include <streambuf>
+
+    class GodotFileInStreamBuf : public std::streambuf {
+
+    public:
+    	GodotFileInStreamBuf(FileAccess *fa) {
+    		_file = fa;
+    	}
+    	int underflow() {
+    		if (_file->eof_reached()) {
+    			return EOF;
+    		} else {
+    			size_t pos = _file->get_position();
+    			uint8_t ret = _file->get_8();
+    			_file->seek(pos); // Required since get_8() advances the read head.
+    			return ret;
+    		}
+    	}
+    	int uflow() {
+    		return _file->eof_reached() ?  EOF : _file->get_8();
+    	}
+
+    private:
+    	FileAccess *_file;
+    };
 
 
 References
 ~~~~~~~~~~
 
-- `istream <http://www.cplusplus.com/reference/istream/istream/>`__
-- `streambuf <http://www.cplusplus.com/reference/streambuf/streambuf/?kw=streambuf>`__
-- `core/io/fileaccess.h <https://github.com/godotengine/godot/blob/master/core/os/file_access.h>`__
+- `istream <http://www.cplusplus.com/reference/istream/istream/>`_
+- `streambuf <http://www.cplusplus.com/reference/streambuf/streambuf/?kw=streambuf>`_
+- `core/io/fileaccess.h <https://github.com/godotengine/godot/blob/master/core/os/file_access.h>`_
 
 Registering the new file format
 -------------------------------
@@ -225,36 +315,58 @@ when ``load`` is called.
 
 .. code-block:: cpp
 
-	/* register_types.cpp */
-	#include "register_types.h"
-	#include "core/class_db.h"
+    /* register_types.h */
+
+    void register_json_types();
+    void unregister_json_types();
+
+.. code-block:: cpp
+
+    /* register_types.cpp */
+
+    #include "register_types.h"
+
+    #include "core/class_db.h"
+    #include "resource_loader_json.h"
+    #include "resource_saver_json.h"
+    #include "resource_json.h"
 
-	#include "my_json_loader.h"
-	#include "my_json.h"
+    static Ref<ResourceFormatLoaderJson> json_loader;
+    static Ref<ResourceFormatSaverJson> json_saver;
 
-	static ResourceFormatLoaderMyJson *my_json_loader = NULL;
-	void register_my_json_types() {
-		my_json_loader = memnew(ResourceFormatLoaderMyJson);
-		ResourceLoader::add_resource_format_loader(my_json_loader);
-		ClassDB::register_class<MyJson>();
-	}
+    void register_json_types() {
+    	ClassDB::register_class<JsonResource>();
 
-	void unregister_my_json_types() {
-		memdelete(my_json_loader);
-	}
+    	json_loader.instance();
+    	ResourceLoader::add_resource_format_loader(json_loader);
+
+    	json_saver.instance();
+    	ResourceSaver::add_resource_format_saver(json_saver);
+    }
+
+    void unregister_json_types() {
+    	ResourceLoader::remove_resource_format_loader(json_loader);
+    	json_loader.unref();
+
+    	ResourceSaver::remove_resource_format_saver(json_saver);
+    	json_saver.unref();
+    }
 
 References
 ~~~~~~~~~~
 
-- `core/io/resource_loader.cpp <https://github.com/godotengine/godot/blob/master/core/io/resource_loader.cpp#L280>`__
+- `core/io/resource_loader.cpp <https://github.com/godotengine/godot/blob/master/core/io/resource_loader.cpp>`_
 
 Loading it on GDScript
 ----------------------
 
+Save a file called ``demo.json`` with the following contents and place it in the
+project's root folder:
+
 .. code-block:: json
 
     {
-      "savefilename" : "demo.mjson",
+      "savefilename": "demo.json",
       "demo": [
         "welcome",
         "to",
@@ -264,10 +376,11 @@ Loading it on GDScript
       ]
     }
 
-::
+Then attach the following script to any node::
 
     extends Node
 
+    onready var json_resource = load("res://demo.json")
+
     func _ready():
-        var myjson = load("res://demo.mjson")
-        print(myjson.to_string())
+        print(json_resource.get_dict())

+ 295 - 124
extensions/gdscript.py

@@ -13,164 +13,335 @@
 
 import re
 
-from pygments.lexer import Lexer, RegexLexer, include, bygroups, using, \
-    default, words, combined, do_insertions
-from pygments.util import get_bool_opt, shebang_matches
-from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
-    Number, Punctuation, Generic, Other, Error
-from pygments import unistring as uni
+from pygments.lexer import (
+    RegexLexer,
+    include,
+    bygroups,
+    default,
+    words,
+    combined,
+)
+from pygments.token import (
+    Text,
+    Comment,
+    Operator,
+    Keyword,
+    Name,
+    String,
+    Number,
+    Punctuation,
+)
 
-__all__ = ['GDScriptLexer']
+__all__ = ["GDScriptLexer"]
 
-line_re = re.compile('.*?\n')
+line_re = re.compile(".*?\n")
 
 
 class GDScriptLexer(RegexLexer):
     """
-    For `Godot source code <https://www.godotengine.org>`_ source code.
+    For `GDScript source code <https://www.godotengine.org>`_.
     """
 
-    name = 'GDScript'
-    aliases = ['gdscript', 'gd']
-    filenames = ['*.gd']
-    mimetypes = ['text/x-gdscript', 'application/x-gdscript']
+    name = "GDScript"
+    aliases = ["gdscript", "gd"]
+    filenames = ["*.gd"]
+    mimetypes = ["text/x-gdscript", "application/x-gdscript"]
 
     def innerstring_rules(ttype):
         return [
             # the old style '%s' % (...) string formatting
-            (r'%(\(\w+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?'
-             '[hlL]?[E-GXc-giorsux%]', String.Interpol),
+            (
+                r"%(\(\w+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?"
+                "[hlL]?[E-GXc-giorsux%]",
+                String.Interpol,
+            ),
             # backslashes, quotes and formatting signs must be parsed one at a time
             (r'[^\\\'"%\n]+', ttype),
             (r'[\'"\\]', ttype),
             # unhandled string formatting sign
-            (r'%', ttype),
+            (r"%", ttype),
             # newlines are an error (use "nl" state)
         ]
 
     tokens = {
-        'root': [
-            (r'\n', Text),
-            (r'^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")',
-             bygroups(Text, String.Affix, String.Doc)),
-            (r"^(\s*)([rRuUbB]{,2})('''(?:.|\n)*?''')",
-             bygroups(Text, String.Affix, String.Doc)),
-            (r'[^\S\n]+', Text),
-            (r'#.*$', Comment.Single),
-            (r'[]{}:(),;[]', Punctuation),
-            (r'\\\n', Text),
-            (r'\\', Text),
-            (r'(in|and|or|not)\b', Operator.Word),
-            (r'!=|==|<<|>>|&&|\+=|-=|\*=|/=|%=|&=|\|=|\|\||[-~+/*%=<>&^.!|$]', Operator),
-            include('keywords'),
-            (r'(func)((?:\s|\\\s)+)', bygroups(Keyword, Text), 'funcname'),
-            (r'(class)((?:\s|\\\s)+)', bygroups(Keyword, Text), 'classname'),
-            include('builtins'),
-            ('([rR]|[uUbB][rR]|[rR][uUbB])(""")',
-             bygroups(String.Affix, String.Double), 'tdqs'),
-            ("([rR]|[uUbB][rR]|[rR][uUbB])(''')",
-             bygroups(String.Affix, String.Single), 'tsqs'),
-            ('([rR]|[uUbB][rR]|[rR][uUbB])(")',
-             bygroups(String.Affix, String.Double), 'dqs'),
-            ("([rR]|[uUbB][rR]|[rR][uUbB])(')",
-             bygroups(String.Affix, String.Single), 'sqs'),
-            ('([uUbB]?)(""")', bygroups(String.Affix, String.Double),
-             combined('stringescape', 'tdqs')),
-            ("([uUbB]?)(''')", bygroups(String.Affix, String.Single),
-             combined('stringescape', 'tsqs')),
-            ('([uUbB]?)(")', bygroups(String.Affix, String.Double),
-             combined('stringescape', 'dqs')),
-            ("([uUbB]?)(')", bygroups(String.Affix, String.Single),
-             combined('stringescape', 'sqs')),
-            include('name'),
-            include('numbers'),
+        "root": [
+            (r"\n", Text),
+            (
+                r'^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")',
+                bygroups(Text, String.Affix, String.Doc),
+            ),
+            (
+                r"^(\s*)([rRuUbB]{,2})('''(?:.|\n)*?''')",
+                bygroups(Text, String.Affix, String.Doc),
+            ),
+            (r"[^\S\n]+", Text),
+            (r"#.*$", Comment.Single),
+            (r"[]{}:(),;[]", Punctuation),
+            (r"\\\n", Text),
+            (r"\\", Text),
+            (r"(in|and|or|not)\b", Operator.Word),
+            (
+                r"!=|==|<<|>>|&&|\+=|-=|\*=|/=|%=|&=|\|=|\|\||[-~+/*%=<>&^.!|$]",
+                Operator,
+            ),
+            include("keywords"),
+            (r"(func)((?:\s|\\\s)+)", bygroups(Keyword, Text), "funcname"),
+            (r"(class)((?:\s|\\\s)+)", bygroups(Keyword, Text), "classname"),
+            include("builtins"),
+            (
+                '([rR]|[uUbB][rR]|[rR][uUbB])(""")',
+                bygroups(String.Affix, String.Double),
+                "tdqs",
+            ),
+            (
+                "([rR]|[uUbB][rR]|[rR][uUbB])(''')",
+                bygroups(String.Affix, String.Single),
+                "tsqs",
+            ),
+            (
+                '([rR]|[uUbB][rR]|[rR][uUbB])(")',
+                bygroups(String.Affix, String.Double),
+                "dqs",
+            ),
+            (
+                "([rR]|[uUbB][rR]|[rR][uUbB])(')",
+                bygroups(String.Affix, String.Single),
+                "sqs",
+            ),
+            (
+                '([uUbB]?)(""")',
+                bygroups(String.Affix, String.Double),
+                combined("stringescape", "tdqs"),
+            ),
+            (
+                "([uUbB]?)(''')",
+                bygroups(String.Affix, String.Single),
+                combined("stringescape", "tsqs"),
+            ),
+            (
+                '([uUbB]?)(")',
+                bygroups(String.Affix, String.Double),
+                combined("stringescape", "dqs"),
+            ),
+            (
+                "([uUbB]?)(')",
+                bygroups(String.Affix, String.Single),
+                combined("stringescape", "sqs"),
+            ),
+            include("name"),
+            include("numbers"),
         ],
-        'keywords': [
-            (words((
-                'and', 'in', 'not', 'or', 'as', 'breakpoint', 'class', 'class_name',
-                'extends', 'is', 'func', 'setget', 'signal', 'tool', 'const',
-                'enum', 'export', 'onready', 'static', 'var', 'break', 'continue',
-                'if', 'elif', 'else', 'for', 'pass', 'return', 'match', 'while',
-                'remote', 'master', 'puppet', 'remotesync', 'mastersync',
-                'puppetsync'), suffix=r'\b'),
-             Keyword),
+        "keywords": [
+            (
+                words(
+                    (
+                        "and",
+                        "in",
+                        "not",
+                        "or",
+                        "as",
+                        "breakpoint",
+                        "class",
+                        "class_name",
+                        "extends",
+                        "is",
+                        "func",
+                        "setget",
+                        "signal",
+                        "tool",
+                        "const",
+                        "enum",
+                        "export",
+                        "onready",
+                        "static",
+                        "var",
+                        "break",
+                        "continue",
+                        "if",
+                        "elif",
+                        "else",
+                        "for",
+                        "pass",
+                        "return",
+                        "match",
+                        "while",
+                        "remote",
+                        "master",
+                        "puppet",
+                        "remotesync",
+                        "mastersync",
+                        "puppetsync",
+                    ),
+                    suffix=r"\b",
+                ),
+                Keyword,
+            ),
         ],
-        'builtins': [
-            (words((
-                'Color8', 'ColorN', 'abs', 'acos', 'asin', 'assert', 'atan', 'atan2',
-                'bytes2var', 'ceil', 'char', 'clamp', 'convert', 'cos', 'cosh',
-                'db2linear', 'decimals', 'dectime', 'deg2rad', 'dict2inst',
-                'ease', 'exp', 'floor', 'fmod', 'fposmod', 'funcref', 'hash',
-                'inst2dict', 'instance_from_id', 'is_inf', 'is_nan', 'lerp',
-                'linear2db', 'load', 'log', 'max', 'min', 'nearest_po2', 'pow',
-                'preload', 'print', 'print_stack', 'printerr', 'printraw',
-                'prints', 'printt', 'rad2deg', 'rand_range', 'rand_seed',
-                'randf', 'randi', 'randomize', 'range', 'round', 'seed', 'sign',
-                'sin', 'sinh', 'sqrt', 'stepify', 'str', 'str2var', 'tan',
-                'tan', 'tanh', 'type_exist', 'typeof', 'var2bytes', 'var2str',
-                'weakref', 'yield'),
-                prefix=r'(?<!\.)', suffix=r'\b'),
-             Name.Builtin),
-            (r'((?<!\.)(self|false|true)|(PI|TAU|NAN|INF)'
-             r')\b', Name.Builtin.Pseudo),
-            (words((
-                'bool', 'int', 'float', 'String', 'NodePath'
-                'Vector2', 'Rect2', 'Transform2D',
-                'Vector3', 'Rect3', 'Plane', 'Quat', 'Basis', 'Transform',
-                'Color', "RID", 'Object', 'NodePath', 'Dictionary',
-                'Array', 'PoolByteArray', 'PoolIntArray', 'PoolRealArray',
-                'PoolStringArray', 'PoolVector2Array', 'PoolVector3Array', 'PoolColorArray',
-                'null',
-            ), prefix=r'(?<!\.)', suffix=r'\b'), Name.Builtin.Type),
+        "builtins": [
+            (
+                words(
+                    (
+                        "Color8",
+                        "ColorN",
+                        "abs",
+                        "acos",
+                        "asin",
+                        "assert",
+                        "atan",
+                        "atan2",
+                        "bytes2var",
+                        "ceil",
+                        "char",
+                        "clamp",
+                        "convert",
+                        "cos",
+                        "cosh",
+                        "db2linear",
+                        "decimals",
+                        "dectime",
+                        "deg2rad",
+                        "dict2inst",
+                        "ease",
+                        "exp",
+                        "floor",
+                        "fmod",
+                        "fposmod",
+                        "funcref",
+                        "hash",
+                        "inst2dict",
+                        "instance_from_id",
+                        "is_inf",
+                        "is_nan",
+                        "lerp",
+                        "linear2db",
+                        "load",
+                        "log",
+                        "max",
+                        "min",
+                        "nearest_po2",
+                        "pow",
+                        "preload",
+                        "print",
+                        "print_stack",
+                        "printerr",
+                        "printraw",
+                        "prints",
+                        "printt",
+                        "rad2deg",
+                        "rand_range",
+                        "rand_seed",
+                        "randf",
+                        "randi",
+                        "randomize",
+                        "range",
+                        "round",
+                        "seed",
+                        "sign",
+                        "sin",
+                        "sinh",
+                        "sqrt",
+                        "stepify",
+                        "str",
+                        "str2var",
+                        "tan",
+                        "tan",
+                        "tanh",
+                        "type_exist",
+                        "typeof",
+                        "var2bytes",
+                        "var2str",
+                        "weakref",
+                        "yield",
+                    ),
+                    prefix=r"(?<!\.)",
+                    suffix=r"\b",
+                ),
+                Name.Builtin,
+            ),
+            (r"((?<!\.)(self|false|true)|(PI|TAU|NAN|INF)" r")\b", Name.Builtin.Pseudo),
+            (
+                words(
+                    (
+                        "bool",
+                        "int",
+                        "float",
+                        "String",
+                        "NodePath",
+                        "Vector2",
+                        "Rect2",
+                        "Transform2D",
+                        "Vector3",
+                        "Rect3",
+                        "Plane",
+                        "Quat",
+                        "Basis",
+                        "Transform",
+                        "Color",
+                        "RID",
+                        "Object",
+                        "NodePath",
+                        "Dictionary",
+                        "Array",
+                        "PoolByteArray",
+                        "PoolIntArray",
+                        "PoolRealArray",
+                        "PoolStringArray",
+                        "PoolVector2Array",
+                        "PoolVector3Array",
+                        "PoolColorArray",
+                        "null",
+                    ),
+                    prefix=r"(?<!\.)",
+                    suffix=r"\b",
+                ),
+                Name.Builtin.Type,
+            ),
         ],
-        'numbers': [
-            (r'(\d+\.\d*|\d*\.\d+)([eE][+-]?[0-9]+)?j?', Number.Float),
-            (r'\d+[eE][+-]?[0-9]+j?', Number.Float),
-            (r'0[xX][a-fA-F0-9]+', Number.Hex),
-            (r'\d+j?', Number.Integer)
+        "numbers": [
+            (r"(\d+\.\d*|\d*\.\d+)([eE][+-]?[0-9]+)?j?", Number.Float),
+            (r"\d+[eE][+-]?[0-9]+j?", Number.Float),
+            (r"0[xX][a-fA-F0-9]+", Number.Hex),
+            (r"\d+j?", Number.Integer),
         ],
-        'name': [
-            ('[a-zA-Z_]\w*', Name),
+        "name": [(r"[a-zA-Z_]\w*", Name)],
+        "funcname": [(r"[a-zA-Z_]\w*", Name.Function, "#pop"), default("#pop")],
+        "classname": [(r"[a-zA-Z_]\w*", Name.Class, "#pop")],
+        "stringescape": [
+            (
+                r'\\([\\abfnrtv"\']|\n|N\{.*?\}|u[a-fA-F0-9]{4}|'
+                r"U[a-fA-F0-9]{8}|x[a-fA-F0-9]{2}|[0-7]{1,3})",
+                String.Escape,
+            )
         ],
-        'funcname': [
-            ('[a-zA-Z_]\w*', Name.Function, '#pop'),
-            default('#pop'),
-        ],
-        'classname': [
-            ('[a-zA-Z_]\w*', Name.Class, '#pop')
-        ],
-        'stringescape': [
-            (r'\\([\\abfnrtv"\']|\n|N\{.*?\}|u[a-fA-F0-9]{4}|'
-             r'U[a-fA-F0-9]{8}|x[a-fA-F0-9]{2}|[0-7]{1,3})', String.Escape)
-        ],
-        'strings-single': innerstring_rules(String.Single),
-        'strings-double': innerstring_rules(String.Double),
-        'dqs': [
-            (r'"', String.Double, '#pop'),
+        "strings-single": innerstring_rules(String.Single),
+        "strings-double": innerstring_rules(String.Double),
+        "dqs": [
+            (r'"', String.Double, "#pop"),
             (r'\\\\|\\"|\\\n', String.Escape),  # included here for raw strings
-            include('strings-double')
+            include("strings-double"),
         ],
-        'sqs': [
-            (r"'", String.Single, '#pop'),
+        "sqs": [
+            (r"'", String.Single, "#pop"),
             (r"\\\\|\\'|\\\n", String.Escape),  # included here for raw strings
-            include('strings-single')
+            include("strings-single"),
         ],
-        'tdqs': [
-            (r'"""', String.Double, '#pop'),
-            include('strings-double'),
-            (r'\n', String.Double)
+        "tdqs": [
+            (r'"""', String.Double, "#pop"),
+            include("strings-double"),
+            (r"\n", String.Double),
         ],
-        'tsqs': [
-            (r"'''", String.Single, '#pop'),
-            include('strings-single'),
-            (r'\n', String.Single)
+        "tsqs": [
+            (r"'''", String.Single, "#pop"),
+            include("strings-single"),
+            (r"\n", String.Single),
         ],
     }
 
+
 def setup(sphinx):
-    sphinx.add_lexer('gdscript', GDScriptLexer())
+    sphinx.add_lexer("gdscript", GDScriptLexer())
 
     return {
-        'parallel_read_safe': True,
-        'parallel_write_safe': True,
+        "parallel_read_safe": True,
+        "parallel_write_safe": True,
     }

+ 1 - 1
getting_started/editor/unity_to_godot.rst

@@ -22,7 +22,7 @@ Differences
 +===================+====================================================================================+================================================================================================================+
 | License           | Proprietary, closed, free license with revenue caps and usage restrictions         | MIT license, free and fully open source without any restriction                                                |
 +-------------------+------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+
-| OS (editor)       | Windows, macOS, Linux (unofficial and unsupported)                                 | Windows, macOS, X11 (Linux, \*BSD)                                                                             |
+| OS (editor)       | Windows, macOS, Linux                                                              | Windows, macOS, X11 (Linux, \*BSD)                                                                             |
 +-------------------+------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+
 | OS (export)       | * **Desktop:** Windows, macOS, Linux                                               | * **Desktop:** Windows, macOS, X11                                                                             |
 |                   | * **Mobile:** Android, iOS, Windows Phone, Tizen                                   | * **Mobile:** Android, iOS                                                                                     |

+ 11 - 7
getting_started/scripting/c_sharp/c_sharp_basics.rst

@@ -79,9 +79,9 @@ Configuring an external editor
 C# support in Godot's script editor is minimal. Consider using an
 external IDE or editor, such as  `Visual Studio Code <https://code.visualstudio.com/>`_
 or MonoDevelop. These provide autocompletion, debugging, and other
-useful features for C#. To select an external editor in Godot, 
+useful features for C#. To select an external editor in Godot,
 click on **Editor → Editor Settings** and scroll down to
-**Mono**. Under **Mono**, click on **Editor**, and select your 
+**Mono**. Under **Mono**, click on **Editor**, and select your
 external editor of choice. Godot currently supports the following
 external editors:
 
@@ -222,9 +222,9 @@ take a look over the official
   `#20271 <https://github.com/godotengine/godot/issues/20271>`_).
 - Attached C# scripts should refer to a class that has a class name
   that matches the file name.
-- There are some methods such as ``Get()``/``Set()``, ``Call()``/``CallDeferred()`` 
+- There are some methods such as ``Get()``/``Set()``, ``Call()``/``CallDeferred()``
   and signal connection method ``Connect()`` that rely on Godot's ``snake_case`` API
-  naming conventions. 
+  naming conventions.
   So when using e.g. ``CallDeferred("AddChild")``, ``AddChild`` will not work because
   the API is expecting the original ``snake_case`` version ``add_child``. However, you
   can use any custom properties or methods without this limitation.
@@ -251,13 +251,17 @@ the ``.csproj`` file located in the project root:
     :emphasize-lines: 2
 
         <ItemGroup>
-            <PackageReference Include="Newtonsoft.Json" Version="11.0.2"/>
+            <PackageReference Include="Newtonsoft.Json">
+              <Version>11.0.2</Version>
+            </PackageReference>
         </ItemGroup>
         ...
     </Project>
 
+.. note::
+    By default, tools like NuGet put ``Version`` as an attribute of the ```PackageReference``` Node. **You must manually create a Version node as shown above.**  This is because the version of MSBuild used requires this. (This will be fixed in Godot 4.0.)
 
-Whenever packages are added or modified, run ``nuget restore`` in the root of the
+Whenever packages are added or modified, run ``nuget restore`` (*not* ``dotnet restore``) in the root of the
 project directory. To ensure that NuGet packages will be available for
 msbuild to use, run:
 
@@ -268,7 +272,7 @@ msbuild to use, run:
 Profiling your C# code
 ----------------------
 
-- `Mono log profiler <https://www.mono-project.com/docs/debug+profile/profile/profiler/>`_ is available via `this PR <https://github.com/godotengine/godot/pull/26513>`_.
+- `Mono log profiler <https://www.mono-project.com/docs/debug+profile/profile/profiler/>`_ is available for Linux and macOS. Due to a Mono change, it does not work on Windows currently.
 - External Mono profiler like `JetBrains dotTrace <https://www.jetbrains.com/profiler/>`_ can be used as described `here <https://github.com/godotengine/godot/pull/34382>`_.
 
 Configuring VS 2019 for debugging

+ 67 - 0
getting_started/scripting/c_sharp/c_sharp_features.rst

@@ -169,3 +169,70 @@ Finally, signals can be created by calling ``AddUserSignal``, but be aware that
         AddUserSignal("MyOtherSignal");
         EmitSignal("MyOtherSignal");
     }
+
+Preprocessor defines
+--------------------
+
+Godot has a set of defines that allow you to change your C# code
+depending on the environment you are compiling to.
+
+.. note:: If you created your project before Godot 3.2, you have to modify
+          or regenerate your `csproj` file to use this feature
+          (compare ``<DefineConstants>`` with a new 3.2+ project).
+
+Examples
+~~~~~~~~
+
+For example, you can change code based on the platform:
+
+.. code-block:: csharp
+
+        public override void _Ready()
+        {
+    #if GODOT_SERVER
+            // Don't try to load meshes or anything, this is a server!
+            LaunchServer();
+    #elif GODOT_32 || GODOT_MOBILE || GODOT_WEB
+            // Use simple objects when running on less powerful systems.
+            SpawnSimpleObjects();
+    #else
+            SpawnComplexObjects();
+    #endif
+        }
+
+Or you can detect which engine your code is in, useful for making cross-engine libraries:
+
+.. code-block:: csharp
+
+        public void MyPlatformPrinter()
+        {
+    #if GODOT
+            GD.Print("This is Godot.");
+    #elif UNITY_5_3_OR_NEWER
+            print("This is Unity.");
+    #else
+            throw new InvalidWorkflowException("Only Godot and Unity are supported.");
+    #endif
+        }
+
+Full list of defines
+~~~~~~~~~~~~~~~~~~~~
+
+* ``GODOT`` is always defined for Godot projects.
+
+* One of ``GODOT_64`` or ``GODOT_32`` is defined depending on if the architecture is 64-bit or 32-bit.
+
+* One of ``GODOT_X11``, ``GODOT_WINDOWS``, ``GODOT_OSX``, ``GODOT_ANDROID``, ``GODOT_HTML5``,
+  or ``GODOT_SERVER`` depending on the OS. These names may change in the future.
+  These are created from the ``get_name()`` method of the :ref:``OS <class_OS>`` singleton,
+  but not every possible OS the method returns is an OS that Godot with Mono runs on.
+
+When **exporting**, the following may also be defined depending on the export features:
+
+* One of ``GODOT_PC``, ``GODOT_MOBILE``, or ``GODOT_WEB`` depending on the platform type.
+
+* One of ``GODOT_ARM64_V8A`` or ``GODOT_ARMEABI_V7A`` on Android only depending on the architecture.
+
+* One of ``GODOT_S3TC``, ``GODOT_ETC``, or ``GODOT_ETC2`` depending on the texture compression type.
+
+* Any custom features added in the export menu will be capitalized and prefixed: ``foo`` -> ``GODOT_FOO``.

+ 53 - 53
getting_started/scripting/gdscript/gdscript_advanced.rst

@@ -59,17 +59,17 @@ Static:
 
 .. code-block:: cpp
 
-    int a; // Value uninitialized
-    a = 5; // This is valid
-    a = "Hi!"; // This is invalid
+    int a; // Value uninitialized.
+    a = 5; // This is valid.
+    a = "Hi!"; // This is invalid.
 
 Dynamic:
 
 ::
 
-    var a # null by default
-    a = 5 # Valid, 'a' becomes an integer
-    a = "Hi!" # Valid, 'a' changed to a string
+    var a # 'null' by default.
+    a = 5 # Valid, 'a' becomes an integer.
+    a = "Hi!" # Valid, 'a' changed to a string.
 
 As function arguments:
 ~~~~~~~~~~~~~~~~~~~~~~
@@ -88,8 +88,8 @@ Static:
 
     [..]
 
-    print_value(55); // Valid
-    print_value("Hello"); // Invalid
+    print_value(55); // Valid.
+    print_value("Hello"); // Invalid.
 
 Dynamic:
 
@@ -100,8 +100,8 @@ Dynamic:
 
     [..]
 
-    print_value(55) # Valid
-    print_value("Hello") # Valid
+    print_value(55) # Valid.
+    print_value("Hello") # Valid.
 
 Pointers & referencing:
 ~~~~~~~~~~~~~~~~~~~~~~~
@@ -128,9 +128,9 @@ too. Some Examples:
 
     void do_something() {
 
-        SomeClass *instance = new SomeClass; // Created as pointer
-        use_class(instance); // Passed as pointer
-        delete instance; // Otherwise it will leak memory
+        SomeClass *instance = new SomeClass; // Created as pointer.
+        use_class(instance); // Passed as pointer.
+        delete instance; // Otherwise it will leak memory.
     }
 
 -  Java:
@@ -145,10 +145,10 @@ too. Some Examples:
 
     public final void do_something() {
 
-        SomeClass instance = new SomeClass(); // Created as reference
-        use_class(instance); // Passed as reference
+        SomeClass instance = new SomeClass(); // Created as reference.
+        use_class(instance); // Passed as reference.
         // Garbage collector will get rid of it when not in
-        // use and freeze your game randomly for a second
+        // use and freeze your game randomly for a second.
     }
 
 -  GDScript:
@@ -159,9 +159,9 @@ too. Some Examples:
         instance.use() # Will work with any class that has a ".use()" method.
 
     func do_something():
-        var instance = SomeClass.new() # Created as reference
-        use_class(instance) # Passed as reference
-        # Will be unreferenced and deleted
+        var instance = SomeClass.new() # Created as reference.
+        use_class(instance) # Passed as reference.
+        # Will be unreferenced and deleted.
 
 In GDScript, only base types (int, float, string and the vector types)
 are passed by value to functions (value is copied). Everything else
@@ -179,35 +179,35 @@ Compare for example arrays in statically typed languages:
 
 .. code-block:: cpp
 
-    int *array = new int[4]; // Create array
-    array[0] = 10; // Initialize manually
-    array[1] = 20; // Can't mix types
+    int *array = new int[4]; // Create array.
+    array[0] = 10; // Initialize manually.
+    array[1] = 20; // Can't mix types.
     array[2] = 40;
     array[3] = 60;
-    // Can't resize
-    use_array(array); // Passed as pointer
-    delete[] array; // Must be freed
+    // Can't resize.
+    use_array(array); // Passed as pointer.
+    delete[] array; // Must be freed.
 
     // or
 
     std::vector<int> array;
     array.resize(4);
-    array[0] = 10; // Initialize manually
-    array[1] = 20; // Can't mix types
+    array[0] = 10; // Initialize manually.
+    array[1] = 20; // Can't mix types.
     array[2] = 40;
     array[3] = 60;
-    array.resize(3); // Can be resized
-    use_array(array); // Passed reference or value
-    // Freed when stack ends
+    array.resize(3); // Can be resized.
+    use_array(array); // Passed reference or value.
+    // Freed when stack ends.
 
 And in GDScript:
 
 ::
 
-    var array = [10, "hello", 40, 60] # Simple, and can mix types
-    array.resize(3) # Can be resized
-    use_array(array) # Passed as reference
-    # Freed when no longer in use
+    var array = [10, "hello", 40, 60] # Simple, and can mix types.
+    array.resize(3) # Can be resized.
+    use_array(array) # Passed as reference.
+    # Freed when no longer in use.
 
 In dynamically typed languages, arrays can also double as other
 datatypes, such as lists:
@@ -246,7 +246,7 @@ Example of Dictionary:
 
 ::
 
-    var d = {"name": "John", "age": 22} # Simple syntax
+    var d = {"name": "John", "age": 22} # Simple syntax.
     print("Name: ", d["name"], " Age: ", d["age"])
 
 Dictionaries are also dynamic, keys can be added or removed at any point
@@ -254,16 +254,16 @@ at little cost:
 
 ::
 
-    d["mother"] = "Rebecca" # Addition
-    d["age"] = 11 # Modification
-    d.erase("name") # Removal
+    d["mother"] = "Rebecca" # Addition.
+    d["age"] = 11 # Modification.
+    d.erase("name") # Removal.
 
 In most cases, two-dimensional arrays can often be implemented more
 easily with dictionaries. Here's a simple battleship game example:
 
 ::
 
-    # Battleship game
+    # Battleship Game
 
     const SHIP = 0
     const SHIP_HIT = 1
@@ -277,12 +277,12 @@ easily with dictionaries. Here's a simple battleship game example:
         board[Vector2(1, 3)] = SHIP
 
     func missile(pos):
-        if pos in board: # Something at that pos
-            if board[pos] == SHIP: # There was a ship! hit it
+        if pos in board: # Something at that position.
+            if board[pos] == SHIP: # There was a ship! hit it.
                 board[pos] = SHIP_HIT
             else:
-                print("Already hit here!") # Hey dude you already hit here
-        else: # Nothing, mark as water
+                print("Already hit here!") # Hey dude you already hit here.
+        else: # Nothing, mark as water.
             board[pos] = WATER_HIT
 
     func game():
@@ -299,20 +299,21 @@ states and quick structs:
 ::
 
     # Same example, lua-style support.
-    # This syntax is a lot more readable and usable
-    # Like any GDScript identifier, keys written in this form cannot start with a digit.
+    # This syntax is a lot more readable and usable.
+    # Like any GDScript identifier, keys written in this form cannot start
+    # with a digit.
 
     var d = {
         name = "John",
         age = 22
     }
 
-    print("Name: ", d.name, " Age: ", d.age) # Used "." based indexing
+    print("Name: ", d.name, " Age: ", d.age) # Used "." based indexing.
 
     # Indexing
 
     d["mother"] = "Rebecca"
-    d.mother = "Caroline" # This would work too to create a new key
+    d.mother = "Caroline" # This would work too to create a new key.
 
 For & while
 -----------
@@ -325,8 +326,7 @@ Iterating in some statically typed languages can be quite complex:
 
     [..]
 
-    for (int i = 0; i < 50; i++)
-    {
+    for (int i = 0; i < 50; i++) {
 
         printf("Value: %s\n", i, strings[i]);
     }
@@ -364,9 +364,9 @@ The range() function can take 3 arguments:
 
 ::
 
-    range(n) # Will go from 0 to n-1
-    range(b, n) # Will go from b to n-1
-    range(b, n, s) # Will go from b to n-1, in steps of s
+    range(n) # Will go from 0 to n-1.
+    range(b, n) # Will go from b to n-1.
+    range(b, n, s) # Will go from b to n-1, in steps of s.
 
 Some statically typed programming language examples:
 
@@ -457,7 +457,7 @@ And it can be used like any other iterator:
 
     var itr = ForwardIterator.new(0, 6, 2)
     for i in itr:
-        print(i) # Will print 0, 2, and 4
+        print(i) # Will print 0, 2, and 4.
 
 Make sure to reset the state of the iterator in ``_iter_init``, otherwise nested
 for-loops that use custom iterators will not work as expected.

+ 62 - 43
getting_started/scripting/gdscript/gdscript_basics.rst

@@ -63,6 +63,7 @@ here's a simple example of how GDScript looks.
 
     class_name MyClass, "res://path/to/optional/icon.svg"
 
+
     # Member variables
 
     var a = 5
@@ -87,6 +88,7 @@ here's a simple example of how GDScript looks.
     var v2 = Vector2(1, 2)
     var v3 = Vector3(1, 2, 3)
 
+
     # Function
 
     func some_function(param1, param2):
@@ -108,17 +110,20 @@ here's a simple example of how GDScript looks.
         var local_var2 = param1 + 3
         return local_var2
 
+
     # Functions override functions with the same name on the base/parent class.
     # If you still want to call them, use '.' (like 'super' in other languages).
 
     func something(p1, p2):
         .something(p1, p2)
 
+
     # Inner class
 
     class Something:
         var a = 10
 
+
     # Constructor
 
     func _init():
@@ -563,8 +568,8 @@ after the variable name, followed by the type.
 If the variable is initialized within the declaration, the type can be inferred, so
 it's possible to omit the type name::
 
-    var my_vector2 := Vector2() # 'my_vector2' is of type 'Vector2'
-    var my_node := Sprite.new() # 'my_node' is of type 'Sprite'
+    var my_vector2 := Vector2() # 'my_vector2' is of type 'Vector2'.
+    var my_node := Sprite.new() # 'my_node' is of type 'Sprite'.
 
 Type inference is only possible if the assigned value has a defined type, otherwise
 it will raise an error.
@@ -590,14 +595,14 @@ same type or a subtype of the cast type.
 ::
 
     var my_node2D: Node2D
-    my_node2D = $Sprite as Node2D # Works since Sprite is a subtype of Node2D
+    my_node2D = $Sprite as Node2D # Works since Sprite is a subtype of Node2D.
 
 If the value is not a subtype, the casting operation will result in a ``null`` value.
 
 ::
 
     var my_node2D: Node2D
-    my_node2D = $Button as Node2D # Results in 'null' since a Button is not a subtype of Node2D
+    my_node2D = $Button as Node2D # Results in 'null' since a Button is not a subtype of Node2D.
 
 For built-in types, they will be forcibly converted if possible, otherwise the
 engine will raise an error.
@@ -605,8 +610,8 @@ engine will raise an error.
 ::
 
     var my_int: int
-    my_int = "123" as int # The string can be converted to int
-    my_int = Vector2() as int # A Vector2 can't be converted to int, this will cause an error
+    my_int = "123" as int # The string can be converted to int.
+    my_int = Vector2() as int # A Vector2 can't be converted to int, this will cause an error.
 
 Casting is also useful to have better type-safe variables when interacting with
 the scene tree::
@@ -987,11 +992,11 @@ By default, all script files are unnamed classes. In this case, you can only
 reference them using the file's path, using either a relative or an absolute
 path. For example, if you name a script file ``character.gd``::
 
-   # Inherit from Character.gd
+   # Inherit from 'Character.gd'.
 
    extends "res://path/to/character.gd"
 
-   # Load character.gd and create a new node instance from it
+   # Load character.gd and create a new node instance from it.
 
    var Character = load("res://path/to/character.gd")
    var character_node = Character.new()
@@ -1067,7 +1072,7 @@ the ``is`` keyword can be used::
     # [...]
 
     # Use 'is' to check inheritance.
-    if (entity is Enemy):
+    if entity is Enemy:
         entity.apply_damage()
 
 To call a function in a *parent class* (i.e. one ``extend``-ed in your current
@@ -1293,7 +1298,7 @@ to. To create custom signals for a class, use the ``signal`` keyword.
 
    extends Node
 
-   # A signal named health_depleted
+   # A signal named health_depleted.
    signal health_depleted
 
 .. note::
@@ -1312,14 +1317,14 @@ In the example below, we connect the ``health_depleted`` signal from a
 ``Character`` node to a ``Game`` node. When the ``Character`` node emits the
 signal, the game node's ``_on_Character_health_depleted`` is called::
 
-   # Game.gd
+    # Game.gd
 
-   func _ready():
-      var character_node = get_node('Character')
-      character_node.connect("health_depleted", self, "_on_Character_health_depleted")
+    func _ready():
+        var character_node = get_node('Character')
+        character_node.connect("health_depleted", self, "_on_Character_health_depleted")
 
-   func _on_Character_health_depleted():
-      get_tree().reload_current_scene()
+    func _on_Character_health_depleted():
+        get_tree().reload_current_scene()
 
 You can emit as many arguments as you want along with a signal.
 
@@ -1342,7 +1347,7 @@ the :ref:`Object.connect() <class_Object_method_connect>` method::
         health -= amount
 
         # We emit the health_changed signal every time the
-        # character takes damage
+        # character takes damage.
         emit_signal("health_changed", old_health, health)
     ...
 
@@ -1351,7 +1356,7 @@ the :ref:`Object.connect() <class_Object_method_connect>` method::
     # Lifebar.gd
 
     # Here, we define a function to use as a callback when the
-    # character's health_changed signal is emitted
+    # character's health_changed signal is emitted.
 
     ...
     func _on_Character_health_changed(old_value, new_value):
@@ -1361,7 +1366,7 @@ the :ref:`Object.connect() <class_Object_method_connect>` method::
             progress_bar.modulate = Color.green
 
         # Imagine that `animate` is a user-defined function that animates the
-        # bar filling up or emptying itself
+        # bar filling up or emptying itself.
         progress_bar.animate(old_value, new_value)
     ...
 
@@ -1376,13 +1381,13 @@ node in this case.
 
 ::
 
-   # Game.gd
+    # Game.gd
 
-   func _ready():
-      var character_node = get_node('Character')
-      var lifebar_node = get_node('UserInterface/Lifebar')
+    func _ready():
+        var character_node = get_node('Character')
+        var lifebar_node = get_node('UserInterface/Lifebar')
 
-      character_node.connect("health_changed", lifebar_node, "_on_Character_health_changed")
+        character_node.connect("health_changed", lifebar_node, "_on_Character_health_changed")
 
 This allows the ``Lifebar`` to react to health changes without coupling it to
 the ``Character`` node.
@@ -1390,8 +1395,8 @@ the ``Character`` node.
 You can write optional argument names in parentheses after the signal's
 definition::
 
-   # Defining a signal that forwards two arguments
-   signal health_changed(old_value, new_value)
+    # Defining a signal that forwards two arguments.
+    signal health_changed(old_value, new_value)
 
 These arguments show up in the editor's node dock, and Godot can use them to
 generate callback functions for you. However, you can still emit any number of
@@ -1414,23 +1419,24 @@ taken by each character on the screen, like ``Player1 took 22 damage.``. The
 damage. So when we connect the signal to the in-game console, we can add the
 character's name in the binds array argument::
 
-   # Game.gd
+    # Game.gd
 
-   func _ready():
-      var character_node = get_node('Character')
-      var battle_log_node = get_node('UserInterface/BattleLog')
+    func _ready():
+        var character_node = get_node('Character')
+        var battle_log_node = get_node('UserInterface/BattleLog')
 
-      character_node.connect("health_changed", battle_log_node, "_on_Character_health_changed", [character_node.name])
+        character_node.connect("health_changed", battle_log_node, "_on_Character_health_changed", [character_node.name])
 
 Our ``BattleLog`` node receives each element in the binds array as an extra argument::
 
-   # BattleLog.gd
+    # BattleLog.gd
 
-   func _on_Character_health_changed(old_value, new_value, character_name):
-      if not new_value <= old_value:
-         return
-      var damage = old_value - new_value
-      label.text += character_name + " took " + str(damage) + " damage."
+    func _on_Character_health_changed(old_value, new_value, character_name):
+        if not new_value <= old_value:
+            return
+            
+        var damage = old_value - new_value
+        label.text += character_name + " took " + str(damage) + " damage."
 
 
 Coroutines with yield
@@ -1445,9 +1451,9 @@ function returns. Once resumed, the state object becomes invalid. Here is
 an example::
 
     func my_func():
-       print("Hello")
-       yield()
-       print("world")
+        print("Hello")
+        yield()
+        print("world")
 
     func _ready():
         var y = my_func()
@@ -1466,9 +1472,9 @@ It is also possible to pass values between ``yield()`` and ``resume()``,
 for example::
 
     func my_func():
-       print("Hello")
-       print(yield())
-       return "cheers!"
+        print("Hello")
+        print(yield())
+        return "cheers!"
 
     func _ready():
         var y = my_func()
@@ -1482,6 +1488,19 @@ Will print::
     world
     cheers!
 
+Remember to save the new function state, when using multiple ``yield``\s::
+
+    func co_func():
+        for i in range(1, 5):
+            print("Turn %d" % i)
+            yield();
+
+    func _ready():
+        var co = co_func();
+        while co is GDScriptFunction && co.is_valid():
+            co = co.resume();
+
+
 Coroutines & signals
 ^^^^^^^^^^^^^^^^^^^^
 

+ 8 - 6
getting_started/scripting/gdscript/gdscript_styleguide.rst

@@ -29,7 +29,8 @@ Here is a complete class example based on these guidelines:
     class_name StateMachine
     extends Node
     # Hierarchical State machine for the player.
-    # Initializes states and delegates engine callbacks (_physics_process, _unhandled_input) to the state.
+    # Initializes states and delegates engine callbacks
+    # (_physics_process, _unhandled_input) to the state.
 
 
     signal state_changed(previous, new)
@@ -40,6 +41,7 @@ Here is a complete class example based on these guidelines:
     onready var _state = get_node(initial_state) setget set_state
     onready var _state_name = _state.name
 
+
     func _init():
         add_to_group("state_machine")
 
@@ -359,7 +361,7 @@ This helps differentiate text comments from disabled code.
 .. note::
 
    In the script editor, to toggle the selected code commented, press
-   <kbd>Ctrl</kbd> <kbd>K</kbd>. This feature adds a single # sign at the start
+   :kbd:`Ctrl + K`. This feature adds a single # sign at the start
    of the selected lines.
 
 Whitespace
@@ -570,7 +572,7 @@ variables, in that order.
 
 ::
 
-   enum Jobs { KNIGHT, WIZARD, ROGUE, HEALER, SHAMAN }
+   enum Jobs {KNIGHT, WIZARD, ROGUE, HEALER, SHAMAN}
 
    const MAX_LIVES = 3
 
@@ -663,21 +665,21 @@ GDScript compiler infer the variable's type when possible.
 
    onready var health_bar: ProgressBar = get_node("UI/LifeBar")
 
-   var health := 0 # The compiler will use the int type
+   var health := 0 # The compiler will use the int type.
 
 **Bad**:
 
 ::
 
    # The compiler can't infer the exact type and will use Node
-   # instead of ProgressBar
+   # instead of ProgressBar.
    onready var health_bar := get_node("UI/LifeBar")
 
 When you let the compiler infer the type hint, write the colon and equal signs together: ``:=``.
 
 ::
 
-   var health := 0 # The compiler will use the int type
+   var health := 0 # The compiler will use the int type.
 
 Add a space on either sides of the return type arrow when defining functions.
 

+ 29 - 13
getting_started/scripting/gdscript/static_typing.rst

@@ -33,16 +33,17 @@ who work with your code should always pass an ``Item`` to the
 
 ::
 
-    # In Item.gd
+    # In 'Item.gd'.
     class_name Item
-
-    # In Inventory.gd
+    # In 'Inventory.gd'.
     class_name Inventory
 
+
     func add(reference: Item, amount: int = 1):
         var item = find_item(reference)
         if not item:
             item = _instance_item_from_db(reference)
+
         item.amount += amount
 
 Another significant advantage of typed GDScript is the new **warning
@@ -122,7 +123,7 @@ script you want to use as a type in a constant:
 
 ::
 
-    const Rifle = preload('res://player/weapons/Rifle.gd')
+    const Rifle = preload("res://player/weapons/Rifle.gd")
     var my_rifle: Rifle
 
 The second method is to use the ``class_name`` keyword when you create.
@@ -165,6 +166,7 @@ to use this type. This forces the variable to stick to the
         var player := body as PlayerController
         if not player:
             return
+
         player.damage()
 
 As we’re dealing with a custom type, if the ``body`` doesn’t extend
@@ -238,6 +240,7 @@ You can also use your own nodes as return types:
         var item: Item = find_item(reference)
         if not item:
             item = ItemDatabase.get_instance(reference)
+            
         item.amount += amount
         return item
 
@@ -257,20 +260,28 @@ dynamic style:
 ::
 
     extends Node
-        func _ready():
-            pass
-        func _process(delta):
-            pass
+
+
+    func _ready():
+        pass
+
+
+    func _process(delta):
+        pass
 
 And with static typing:
 
 ::
 
     extends Node
-        func _ready() -> void:
-            pass
-        func _process(delta: float) -> void:
-            pass
+
+
+    func _ready() -> void:
+        pass
+
+
+    func _process(delta: float) -> void:
+        pass
 
 As you can see, you can also use types with the engine’s virtual
 methods. Signal callbacks, like any methods, can also use types. Here’s
@@ -296,6 +307,7 @@ to cast parameters automatically:
     func _on_area_entered(bullet: Bullet) -> void:
         if not bullet:
             return
+
         take_damage(bullet.damage)
 
 The ``bullet`` variable could hold any ``CollisionObject2D`` here, but
@@ -378,7 +390,7 @@ element the ``for`` keyword loops over already has a different type. So you
 
 ::
 
-    var names = ['John', 'Marta', 'Samantha', 'Jimmy']
+    var names = ["John", "Marta", "Samantha", "Jimmy"]
     for name: String in names:
         pass
 
@@ -387,17 +399,21 @@ Two scripts can’t depend on each other in a cyclic fashion:
 ::
 
     # Player.gd
+
     extends Area2D
     class_name Player
 
+
     var rifle: Rifle
 
 ::
 
     # Rifle.gd
+
     extends Area2D
     class_name Rifle
 
+
     var player: Player
 
 Summary

+ 3 - 3
getting_started/scripting/visual_script/nodes_purposes.rst

@@ -119,7 +119,7 @@ This is the most common way to edit *Scene Nodes* in Visual Scripting. Select a
 
 The result is that this value can be changed from your script by writing to a *Data Port*.
 
-If instead reading this value is desired, drag the node again but hold the *Control* key (or Command on Mac). This will create a getter:
+If instead reading this value is desired, drag the node again but hold :kbd:`Ctrl` (or :kbd:`Cmd` on macOS). This will create a getter:
 
 .. image:: img/visual_script22.png
 
@@ -155,7 +155,7 @@ To use the variable in the script, simply drag it to the canvas to create a gett
 .. image:: img/visual_script26.png
 
 
-Likewise, hold *Control* (*Command* on Mac) to drop a setter:
+Likewise, hold :kbd:`Ctrl` (or :kbd:`Cmd` on macOS) to drop a setter:
 
 .. image:: img/visual_script27.png
 
@@ -195,7 +195,7 @@ Below the member panel, exists the list of all available node types:
 .. image:: img/visual_script33.png
 
 
-Ctrl-F (Command-F on Mac) allows you to search the list.
+Pressing :kbd:`Ctrl + F` (or :kbd:`Cmd + F` on macOS) allows you to search the list.
 
 Any of them can be dragged to the scene. Unlike nodes (e.g. dragging a property
 from the Inspector sets the context to the node being edited automatically), these are added without any "contextual" information, so this has to be done manually.

+ 1 - 1
getting_started/step_by_step/animations.rst

@@ -70,7 +70,7 @@ keyframes with different values, the animation happens.
 
 .. image:: img/robisplash_anim_editor_keyframe_2.png
 
-Pressing "Play selected animation from start. (Shift-D)" on the animation panel
+Pressing "Play selected animation from start" button on the animation panel (or :kbd:`Shift + D` on keyboard)
 will make the logo descend.
 
 .. image:: img/robisplash_anim_editor_play_start.png

+ 119 - 0
getting_started/step_by_step/exporting.rst

@@ -125,6 +125,123 @@ changed:
         emit_signal("hit")
         $CollisionShape2D.set_deferred("disabled", true)
 
+ .. code-tab:: csharp
+
+    using Godot;
+    using System;
+
+    public class Player : Area2D
+    {
+        [Signal]
+        public delegate void Hit();
+
+        [Export]
+        public int Speed = 400;
+
+        private Vector2 _screenSize;
+        // Add this variable to hold the clicked position.
+        private Vector2 _target;
+
+        public override void _Ready()
+        {
+            Hide();
+            _screenSize = GetViewport().Size;
+        }
+
+        public void Start(Vector2 pos)
+        {
+            Position = pos;
+            // Initial target us the start position.
+            _target = pos;
+            Show();
+            GetNode<CollisionShape2D>("CollisionShape2D").Disabled = false;
+        }
+
+        // Change the target whenever a touch event happens.
+        public override void _Input(InputEvent @event)
+        {
+            if (@event is InputEventScreenTouch eventMouseButton && eventMouseButton.Pressed)
+            {
+                _target = (@event as InputEventScreenTouch).Position;
+            }
+        }
+
+        public override void _Process(float delta)
+        {
+            var velocity = new Vector2();
+            // Move towards the target and stop when close.
+            if (Position.DistanceTo(_target) > 10)
+            {
+                velocity = (_target - Position).Normalized() * Speed;
+            }
+            else
+            {
+                velocity = new Vector2();
+            }
+
+            // Remove keyboard controls.
+            //if (Input.IsActionPressed("ui_right"))
+            //{
+            //    velocity.x += 1;
+            //}
+
+            //if (Input.IsActionPressed("ui_left"))
+            //{
+            //    velocity.x -= 1;
+            //}
+
+            //if (Input.IsActionPressed("ui_down"))
+            //{
+            //    velocity.y += 1;
+            //}
+
+            //if (Input.IsActionPressed("ui_up"))
+            //{
+            //    velocity.y -= 1;
+            //}
+
+            var animatedSprite = GetNode<AnimatedSprite>("AnimatedSprite");
+
+            if (velocity.Length() > 0)
+            {
+                velocity = velocity.Normalized() * Speed;
+                animatedSprite.Play();
+            }
+            else
+            {
+                animatedSprite.Stop();
+            }
+
+            Position += velocity * delta;
+            // We still need to clamp the player's position here because on devices that don't
+            // match your game's aspect ratio, Godot will try to maintain it as much as possible
+            // by creating black borders, if necessary.
+            // Without clamp(), the player would be able to move under those borders. 
+            Position = new Vector2(
+                x: Mathf.Clamp(Position.x, 0, _screenSize.x),
+                y: Mathf.Clamp(Position.y, 0, _screenSize.y)
+            );
+
+            if (velocity.x != 0)
+            {
+                animatedSprite.Animation = "right";
+                animatedSprite.FlipV = false;
+                animatedSprite.FlipH = velocity.x < 0;
+            }
+            else if(velocity.y != 0)
+            {
+                animatedSprite.Animation = "up";
+                animatedSprite.FlipV = velocity.y > 0;
+            }
+        }
+        public void OnPlayerBodyEntered(PhysicsBody2D body)
+        {
+            Hide(); // Player disappears after being hit.
+            EmitSignal("Hit");
+            GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred("disabled", true);
+        }
+    }
+
 Setting a main scene
 --------------------
 
@@ -298,6 +415,8 @@ to wait a few moments while the game loads before you see the start screen.
 The console window beneath the game tells you if anything goes wrong. You can
 disable it by setting "Export With Debug" off when you export the project.
 
+.. image:: img/export_web_export_with_debug_disabled.png
+
 .. note:: While WASM is supported in all major browsers, it is still an emerging
           technology and you may find some things that don't work. Make sure
           you have updated your browser to the most recent version, and report

BIN
getting_started/step_by_step/img/export_touchsettings.png


BIN
getting_started/step_by_step/img/export_web_export_with_debug_disabled.png


BIN
getting_started/step_by_step/img/instancing.png


BIN
getting_started/step_by_step/img/instancingpre.png


BIN
getting_started/step_by_step/img/signals_connect_dialog_timer.png


+ 4 - 3
getting_started/step_by_step/instancing.rst

@@ -79,7 +79,7 @@ Multiple instances
 
 You can add as many instances as you like to a scene, either by using the
 "Instance" button again, or by clicking on the ball instance and pressing
-"Duplicate" (Ctrl-D):
+"Duplicate" (:kbd:`Ctrl + D`):
 
 .. image:: img/instancing_multiball.png
 
@@ -90,8 +90,9 @@ Run the scene again and all of the balls will fall.
 Editing instances
 -----------------
 
-Open the ``Ball`` scene and add a ``PhysicsMaterial`` by clicking on the down
-arrow and selecting "New PhysicsMaterial".
+Open the ``Ball`` scene and add a ``PhysicsMaterial`` by opening the "Physics
+Material Override" dropdown in the Inspector dock and selecting "New
+PhysicsMaterial".
 
 .. image:: img/instancing_physicsmat1.png
 

+ 12 - 11
getting_started/step_by_step/intro_to_the_editor_interface.rst

@@ -79,21 +79,21 @@ When the folder path is correct, you'll see a green checkmark.
 Your first look at Godot’s editor
 ---------------------------------
 
-Welcome to Godot! With your project open, you should see the editor’s
-interface with empty docks on the right side.
+Welcome to Godot! With your project open, you should see the editor’s interface
+with menus along the top of the interface and docks along the far extremes of
+the interface on either side of the viewport.
 
 .. image:: img/editor_ui_intro_editor_interface_overview.png
 
 At the top, from left to right, you can see the **main menus**, the
 **workspaces**, and the **playtest buttons**.
 
-On the bottom left side, you have the **FileSystem dock**, where you’ll
-manage your project files and assets.
+The **FileSystem dock** is where you’ll manage your project files and assets.
 
 .. image:: img/editor_ui_intro_dock_filesystem.png
 
-On the right side, you’ll find the **Scene dock**, which lists the active
-scene’s content and the **Inspector** in the bottom right corner.
+The **Scene dock** lists the active scene’s content and the **Inspector**
+allows for the management of the properties of a scene's content.
 
 .. image:: img/editor_ui_intro_dock_inspector.png
 
@@ -116,12 +116,13 @@ You can see four workspace buttons at the top: 2D, 3D, Script and
 AssetLib.
 
 You’ll use the **2D workspace** for all types of games. In addition to 2D games,
-the 2D workspace is where you'll build your interfaces. Press F1 to access it.
+the 2D workspace is where you'll build your interfaces. Press :kbd:`F1` 
+(or :kbd:`Alt + 1` on macOS) to access it.
 
 .. image:: img/editor_ui_intro_editor_04_2d_workspace.png
 
 In the **3D workspace**, you can work with meshes, lights, and design
-levels for 3D games. Press F2 to access it.
+levels for 3D games. Press :kbd:`F2` (or :kbd:`Alt + 2` on macOS) to access it.
 
 .. image:: img/editor_ui_intro_editor_05_3d_workspace.png
 
@@ -133,8 +134,8 @@ related to the 3D viewport.
 .. note:: Read :ref:`doc_introduction_to_3d` for more detail about **3D workspace**.
 
 The **Script** workspace is a complete code editor with a debugger, rich
-auto-completion, and built-in code reference. Press F3 to access it, and
-F4 to search the reference.
+auto-completion, and built-in code reference. Press :kbd:`F3` (or :kbd:`Alt + 3` on macOS) 
+to access it, and :kbd:`F4` to search the reference.
 
 .. image:: img/editor_ui_intro_editor_06_script_workspace_expanded.png
 
@@ -146,7 +147,7 @@ Modify the interface
 
 Godot’s interface lives in a single window. You cannot split it across
 multiple screens although you can work with an external code editor like
-Atom or Visual Studio for instance.
+Atom or Visual Studio Code for instance.
 
 Move and resize docks
 ~~~~~~~~~~~~~~~~~~~~~

+ 3 - 4
getting_started/step_by_step/scenes_and_nodes.rst

@@ -130,9 +130,8 @@ And finally, create the Label! A lot happens when Create is pressed:
 First of all, the scene changes to the 2D editor (because Label is a 2D Node
 type), and the Label appears, selected, at the top left corner of the viewport.
 
-The node appears in the scene tree editor (box in the top right
-corner), and the label properties appear in the Inspector (box in the
-bottom right corner).
+The node appears in the scene tree editor in the Scene dock, and the label
+properties appear in the Inspector dock.
 
 The next step will be to change the "Text" Property of the label. Let's
 change it to "Hello World":
@@ -140,7 +139,7 @@ change it to "Hello World":
 .. image:: img/hw.png
 
 Ok, everything's ready to run the scene! Press the PLAY SCENE Button on
-the top bar (or hit F6):
+the top bar (or hit :kbd:`F6`):
 
 .. image:: img/playscene.png
 

+ 2 - 2
getting_started/step_by_step/scripting.rst

@@ -104,7 +104,7 @@ than a few minutes to get an overview of the concepts.
 Scene setup
 ~~~~~~~~~~~
 
-Use the "Add Child Node" dialogue accessed from the Scene tab (or by pressing ``Ctrl+A``) to create a hierarchy with the following
+Use the "Add Child Node" dialogue accessed from the Scene tab (or by pressing :kbd:`Ctrl + A`) to create a hierarchy with the following
 nodes:
 
 - Panel
@@ -252,7 +252,7 @@ Next, write a function which will be called when the button is pressed:
         GetNode<Label>("Label").Text = "HELLO!";
     }
 
-Finally, connect the button's "pressed" signal to ``_ready()`` by
+Finally, connect the button's "pressed" signal to ``_on_Button_pressed()`` by
 using :ref:`Object.connect() <class_Object_method_connect>`.
 
 .. tabs::

+ 55 - 1
getting_started/step_by_step/signals.rst

@@ -60,6 +60,10 @@ node.
 .. warning:: The target node *must* have a script attached or you'll receive
              an error message.
 
+On the right side, you can bind an arbitrary number of arguments of (possibly) different
+types. This can be useful when you have more than one signal connected to the same method,
+as each signal propagation will result in different values for those extra call arguments.
+
 On the bottom of the window is a field labeled "Receiver Method". This is the name
 of the function in the target node's script that you want to use. By default,
 Godot will create this function using the naming convention ``_on_<node_name>_<signal_name>``
@@ -79,7 +83,7 @@ Click "Connect" and you'll see that the function has been created in the script:
 
     public class TimerExample : Node2D
     {
-        private void _on_Timer_timeout()
+        public void _on_Timer_timeout()
         {
             // Replace with function body.
         }
@@ -204,6 +208,56 @@ To emit a signal via code, use the ``emit_signal`` function:
             EmitSignal(nameof(MySignal));
         }
     }
+    
+A signal can also optionally declare one or more arguments. Specify the
+argument names between parentheses:
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    extends Node
+
+    signal my_signal(value, other_value)
+
+ .. code-tab:: csharp
+
+    public class Main : Node
+    {
+        [Signal]
+        public delegate void MySignal();
+    }
+
+.. note::
+
+    The signal arguments show up in the editor's node dock, and Godot
+    can use them to generate callback functions for you. However, you can still
+    emit any number of arguments when you emit signals. So it's up to you to
+    emit the correct values.
+
+To pass values, add them as the second argument to the ``emit_signal`` function:
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    extends Node
+
+    signal my_signal(value, other_value)
+
+    func _ready():
+        emit_signal("my_signal", true, 42)
+
+ .. code-tab:: csharp
+
+    public class Main : Node
+    {
+        [Signal]
+        public delegate void MySignal();
+
+        public override void _Ready()
+        {
+            EmitSignal(nameof(MySignal), true, 42);
+        }
+    }
 
 Conclusion
 ----------

+ 1 - 1
getting_started/step_by_step/ui_code_a_life_bar.rst

@@ -353,7 +353,7 @@ This method needs to:
 
 Also call ``update_health`` at the end of the ``_ready`` function to
 initialize the ``Number`` node's ``text`` with the right value at the
-start of the game. Press F5 to test the game: the life bar updates with
+start of the game. Press :kbd:`F5` to test the game: the life bar updates with
 every attack!
 
 .. figure:: img/lifebar_tutorial_LifeBar_health_update_no_anim.gif

+ 4 - 4
getting_started/step_by_step/ui_game_user_interface.rst

@@ -163,7 +163,7 @@ parent ``MarginContainer``.
 As they have a container as their direct parent, we cannot move them
 freely: the ``Count`` node will always reset their anchors, their size
 and position. Try to move and resize the nodes in the viewport. Then,
-select any of the three textures and press Ctrl Up or Ctrl Down to
+select any of the three textures and press :kbd:`Ctrl + Up` or :kbd:`Ctrl + Down` to
 reorder them in the Scene dock. They'll snap back to their previous size
 and position.
 
@@ -256,7 +256,7 @@ Design the bomb and emerald counters
 The bomb and emerald counters are like the bar's ``Count`` node. So we'll
 duplicate it and use it as a template.
 
-Under the ``Bar`` node, select ``Count`` and press Ctrl D to duplicate
+Under the ``Bar`` node, select ``Count`` and press :kbd:`Ctrl + D` to duplicate
 it. Drag and drop the new node under the ``Counters`` ``HBoxContainer``
 at the bottom of the scene tree. You should see it resize automatically.
 Don't worry about this for now, we'll fix the size soon.
@@ -408,7 +408,7 @@ Inherit the Bar Scene to build the LifeBar
 Go to ``Scene -> New Inherited Scene`` to create a new type of ``Bar``.
 Select the Bar scene and open it. You should see a new [unsaved] tab,
 that's like your ``Bar``, but with all nodes except the root in grey.
-Press ``Meta+S`` to save the new inherited scene and name it
+Press :kbd:`Meta + S` to save the new inherited scene and name it
 ``LifeBar``.
 
 .. figure:: img/ui_gui_step_tutorial_inherited_scene_parent.png
@@ -474,7 +474,7 @@ all the resources this node uses and create unique copies for us.
 .. tip::
 
     When you duplicate a node from the Scene tree, with
-    ``Meta+D``, it shares its resources with the original node. You
+    :kbd:`Meta + D`, it shares its resources with the original node. You
     need to use ``Make Sub-Resources Unique`` before you can tweak the
     resources without affecting the source node.
 

+ 1 - 1
getting_started/step_by_step/ui_introduction_to_the_ui_system.rst

@@ -101,7 +101,7 @@ TextureButton
 one for each of the button's states. Most of the time, you'll use the
 Normal, Pressed, and Hover textures. Focused is useful if your interface
 listens to the keyboard's input. The sixth image slot, the Click Mask,
-lets you define the clickable area using a 2-bit, pure black and white
+lets you define the clickable area using a 1-bit, pure black and white
 image.
 
 In the Base Button section, you'll find a few checkboxes that change how

+ 5 - 5
getting_started/step_by_step/ui_main_menu.rst

@@ -127,7 +127,7 @@ We have to add a root node before we can save the scene. Your UI's root
 should be the outermost container or element. In this case it's a
 ``MarginContainer``. ``MarginContainer`` is a good starting point for
 most interfaces, as you often need padding around the UI. Press
-``Meta+S`` to save the scene to the disk. Name it *MainMenu*.
+:kbd:`Meta + S` to save the scene to the disk. Name it *MainMenu*.
 
 Select the ``MarginContainer`` again, and head to the inspector to
 define the margins' size. Scroll down the ``Control`` class, to the
@@ -152,9 +152,9 @@ Select the ``MarginContainer``, and create the UI elements as
 3. the version note,
 4. and the main menu’s illustration.
 
-Click the **Add Node** button or press ``Meta+A`` on your keyboard.
+Click the **Add Node** button or press :kbd:`Meta + A` on your keyboard.
 Start to type ``TextureRect`` to find the corresponding node and press
-enter. With the new node selected, press ``Meta+D`` five times to
+enter. With the new node selected, press :kbd:`Meta + D` five times to
 create five extra ``TextureRect`` instances.
 
 Click each of the nodes to select it. In the inspector, find the **Texture**
@@ -234,7 +234,7 @@ automatically.
 
 To space out the menu options and the logo on the left, we'll use one
 final container and its size flags. Select the ``VBoxContainer`` and
-press ``Meta+A`` to add a new node inside it. Add a second
+press :kbd:`Meta + A` to add a new node inside it. Add a second
 ``VBoxContainer`` and name it *MenuOptions*. Select all three menu
 options, ``Continue``, ``NewGame`` and ``Options``, and drag and drop
 them inside the new ``VBoxContainer``. The UI's layout should barely
@@ -288,7 +288,7 @@ size of UI elements.
 
 The order in which you nest matters. To see if your
 UI adapts nicely to different screen ratios, select the root node, press
-the Q key to activate the Select Mode, select the container and click
+:kbd:`Q` to activate the Select Mode, select the container and click
 and drag on one of the container's corners to resize it. The UI
 components should flow inside of it.
 

+ 9 - 10
getting_started/step_by_step/your_first_game.rst

@@ -82,7 +82,7 @@ are not selectable."
 
 .. image:: img/lock_children.png
 
-Save the scene. Click Scene -> Save, or press ``Ctrl+S`` on Windows/Linux or ``Command+S`` on Mac.
+Save the scene. Click Scene -> Save, or press :kbd:`Ctrl + S` on Windows/Linux or :kbd:`Cmd + S` on macOS.
 
 .. note:: For this project, we will be following the Godot naming conventions.
 
@@ -206,7 +206,7 @@ which is a good time to find the size of the game window:
 
     public override void _Ready()
     {
-        _screenSize = GetViewport().GetSize();
+        _screenSize = GetViewport().Size;
     }
 
 Now we can use the ``_process()`` function to define what the player will do.
@@ -373,9 +373,9 @@ Let's place this code at the end of our ``_process()`` function:
         if (velocity.x != 0)
         {
             animatedSprite.Animation = "right";
+            animatedSprite.FlipV = false;
             // See the note below about boolean assignment
             animatedSprite.FlipH = velocity.x < 0;
-            animatedSprite.FlipV = false;
         }
         else if(velocity.y != 0)
         {
@@ -674,10 +674,9 @@ you will see some new buttons at the top of the editor:
 .. image:: img/path2d_buttons.png
 
 Select the middle one ("Add Point") and draw the path by clicking to add
-the points at the corners shown. To have the points snap to the grid, make sure "Snap to
-Grid" is checked. This option can be found under the "Snapping options"
-button to the left of the "Lock" button, appearing as a series of three
-vertical dots.
+the points at the corners shown. To have the points snap to the grid, make
+sure "Use Grid Snap" is selected. This option can be found to the left of
+the "Lock" button, appearing as a magnet next to some intersecting lines.
 
 .. image:: img/draw_path2d.gif
 
@@ -740,7 +739,7 @@ Drag ``Mob.tscn`` from the "FileSystem" panel and drop it in the
 
 Next, click on the Player and connect the ``hit`` signal. We want to make a
 new function named ``game_over``, which will handle what needs to happen when a
-game ends. Type "game_over" in the "Method In Node" box at the bottom of the
+game ends. Type "game_over" in the "Receiver Method" box at the bottom of the
 "Connecting Signal" window. Add the following code, as well as a ``new_game``
 function to set everything up for a new game:
 
@@ -816,7 +815,7 @@ Note that a new instance must be added to the scene using
 
     func _on_MobTimer_timeout():
         # Choose a random location on Path2D.
-        $MobPath/MobSpawnLocation.set_offset(randi())
+        $MobPath/MobSpawnLocation.offset = randi()
         # Create a Mob instance and add it to the scene.
         var mob = Mob.instance()
         add_child(mob)
@@ -1228,7 +1227,7 @@ This is the default input event associated with the spacebar.
 
 .. image:: img/start_button_shortcut.png
 
-Now when the start button appears, you can either click it or press the spacebar
+Now when the start button appears, you can either click it or press :kbd:`Space`
 to start the game.
 
 Project files

+ 3 - 2
getting_started/workflow/assets/escn_exporter/material.rst

@@ -46,8 +46,9 @@ difficulties in implementation, which are:
 - shader nodes except ``PrincipledBSDF``, ``Diffuse``, ``Glossy``, ``Glass``, ``add shader`` and ``mix shader``
 
 .. warning::
-  If possible try to use PrincipledBSDF node with GGX distribution as the output shader
-  node, it is the only one guarantee to be exactly correctly. Others are just based on approximation.
+
+    If possible, try to use PrincipledBSDF node with GGX distribution as the output shader
+    node, it is the only one guaranteed to be exactly correct. Others are just based on approximation.
 
 Sometimes materials may not be valid for exporting (e.g. has some unsupported node) or it
 is using Blender Internal Engine, only the diffuse color and a few flags (e.g. unshaded) are

+ 46 - 9
getting_started/workflow/assets/importing_images.rst

@@ -30,6 +30,36 @@ Detect 3D
 This option makes Godot be aware of when a texture (which is imported for 2D as default) is used in 3D. If this happens, setting are changed so the texture flags
 are friendlier to 3D (mipmaps, filter and repeat become enabled and compression is changed to VRAM). Texture is also reimported automatically.
 
+Supported image formats
+-----------------------
+
+Godot can import the following image formats:
+
+- BMP (``.bmp``)
+- DirectDraw Surface (``.dds``)
+  - If mipmaps are present in the texture, they will be loaded directly.
+  This can be used to achieve effects using custom mipmaps.
+- OpenEXR (``.exr``)
+  - Supports HDR (highly recommended for panorama skies).
+- Radiance HDR (``.hdr``)
+  - Supports HDR (highly recommended for panorama skies).
+- JPEG (``.jpg``, ``.jpeg``)
+  - Doesn't support transparency per the format's limitations.
+- PNG (``.png``)
+  - Precision is limited to 8 bits per channel upon importing (no HDR images).
+- Truevision Targa (``.tga``)
+- SVG (``.svg``, ``.svgz``)
+  - SVGs are rasterized using `NanoSVG <https://github.com/memononen/nanosvg>`__
+  when importing them. Support is limited; complex vectors may not render correctly.
+  For complex vectors, rendering them to PNGs using Inkscape is often a better solution.
+  This can be automated thanks to its `command-line interface <https://wiki.inkscape.org/wiki/index.php/Using_the_Command_Line#Export_files>`__.
+- WebP (``.webp``)
+
+.. note::
+
+    If you've compiled the Godot editor from source with specific modules disabled,
+    some formats may not be available.
+
 Compression
 -----------
 
@@ -39,21 +69,28 @@ Godot offers several compression methods, depending on the use case.
 Compress Mode
 ~~~~~~~~~~~~~
 
-* VRAM Compression: This is the most common compression mode for 3D assets. File on disk is reduced and
-  video memory usage is also reduced considerably. For 3D, it may present unwanted artifacts, though.
-* Lossless Compression: This is the most common compression for 2D assets. It shows assets without any
-  kind of artifacting, and disk compression is decent. It will use considerably more amount of video memory than VRAM, though.
-* Lossy Compression: For games with lots of large 2D assets, lossy compression can be a great choice. It has some artifacting,
-  but less than VRAM and the file size is almost a tenth of Lossless.
-* Uncompressed: Only useful for formats that can't be compressed (like, raw float).
+- **VRAM Compression:** This is the most common compression mode for 3D assets.
+  Size on disk is reduced and video memory usage is also decreased considerably
+  (usually by a factor between 4 and 6). This mode should be avoided for 2D as it
+  exhibits noticeable artifacts.
+- **Lossless Compression:** This is the most common compression mode for 2D assets.
+  It shows assets without any kind of artifacting, and disk compression is
+  decent. It will use considerably more amount of video memory than
+  VRAM Compression, though. This is also the recommended setting for pixel art.
+- **Lossy Compression:** This is a good choice for large 2D assets. It has some
+  artifacts, but less than VRAM and the file size is several times lower
+  compared to Lossless or Uncompressed. Video memory usage isn't decreased by
+  this mode; it's the same as with Lossless Compression or Uncompressed.
+- **Uncompressed:** Only useful for formats that can't be compressed (such as
+  raw float images).
 
 In this table, each of the four options are described together with their
-advantages and disadvantages ( |good| = Best, |bad| =Worst ):
+advantages and disadvantages (|good| = best, |bad| = worst):
 
 +----------------+------------------------+---------------------------+-------------------------+------------------------------------------------------+
 |                | Uncompressed           | Compress Lossless (PNG)   | Compress Lossy (WebP)   | Compress VRAM                                        |
 +================+========================+===========================+=========================+======================================================+
-| Description    | Stored as raw pixels   | Stored as PNG             | Stored as WebP          | Stored as S3TC/BC,PVRTC/ETC, depending on platform   |
+| Description    | Stored as raw pixels   | Stored as PNG             | Stored as WebP          | Stored as S3TC/BC or PVRTC/ETC depending on platform |
 +----------------+------------------------+---------------------------+-------------------------+------------------------------------------------------+
 | Size on Disk   | |bad| Large            | |regular| Small           | |good| Very Small       | |regular| Small                                      |
 +----------------+------------------------+---------------------------+-------------------------+------------------------------------------------------+

+ 19 - 9
getting_started/workflow/assets/importing_translations.rst

@@ -38,11 +38,21 @@ Translation format
 ------------------
 
 To complete the picture and allow efficient support for translations,
-Godot has a special importer that can read CSV files. All spreadsheet
-editors (be it Libreoffice, Microsoft Office, Google Docs, etc.) can
-export to this format, so the only requirement is that the files have
-a special arrangement. The CSV files must be saved in UTF-8 encoding
-and be formatted as follows:
+Godot has a special importer that can read CSV files. Most spreadsheet
+editors can export to this format, so the only requirement is that the files
+have a special arrangement. The CSV files **must** be saved with UTF-8 encoding
+without a `byte order mark <https://en.wikipedia.org/wiki/Byte_order_mark>`__.
+
+.. warning::
+
+    By default, Microsoft Excel will always save CSV files with ANSI encoding
+    rather than UTF-8. There is no built-in way to do this, but there are
+    workarounds as described
+    `here <https://stackoverflow.com/questions/4221176/excel-to-csv-with-utf8-encoding>`__.
+
+    We recommend using `LibreOffice <https://www.libreoffice.org/>`__ or Google Sheets instead.
+
+CSV files must be formatted as follows:
 
 +--------+----------+----------+----------+
 | keys   | <lang1>  | <lang2>  | <langN>  |
@@ -77,11 +87,11 @@ Here's an example:
 
 The same example is shown below as a comma-separated plain text file,
 which should be the result of editing the above in a spreadsheet.
-When editing the plain text version, be sure to enclose with double 
+When editing the plain text version, be sure to enclose with double
 quotes any message that contains commas, line breaks or double quotes,
 so that commas are not parsed as delimiters, line breaks don't create new
 entries and double quotes are not parsed as enclosing characters. Be sure
-to escape any double quotes a message may contain by preceding them with 
+to escape any double quotes a message may contain by preceding them with
 another double quote. Alternatively, you can select another delimiter than
 comma in the import options.
 
@@ -104,10 +114,10 @@ translations to load when the game runs, specified in project.godot (or the
 project settings). Godot allows loading and removing translations at
 runtime as well.
 
-Select the ``.csv`` file and access the "Import" dock to define import
+Select the ``.csv`` file and access the **Import** dock to define import
 options. You can toggle the compression of the imported translations, and
 select the delimiter to use when parsing the CSV file.
 
 .. image:: img/import_csv.png
 
-Be sure to click "Reimport" after any change to these options.
+Be sure to click **Reimport** after any change to these options.

+ 1 - 1
getting_started/workflow/best_practices/autoloads_versus_internal_nodes.rst

@@ -103,7 +103,7 @@ instead to get auto-completion for a type in your entire project.
    Autoload is not exactly a Singleton. Nothing prevents you from instantiating
    copies of an auto-loaded node. It is only a tool that makes a node load
    automatically as a child of the root of your scene tree, regardless of your
-   game's node structure or which scene you run, e.g. by pressing the ``F6`` key.
+   game's node structure or which scene you run, e.g. by pressing :kbd:`F6` key.
 
    As a result, you can get the auto-loaded node, for example an autoload called
    ``Sound``, by calling ``get_node("/root/Sound")``.

+ 1 - 1
getting_started/workflow/export/android_custom_build.rst

@@ -114,7 +114,7 @@ In there, run ``sdkmanager --licenses``:
 
 .. image:: img/custom_build_sdkmanager.png
 
-This will ask you to accept several licenses, just write ``y`` and press Enter
+This will ask you to accept several licenses, just write ``y`` and press :kbd:`Enter`
 on every of them until it's done.
 
 Afterwards, install the platform tools (this is required to install ``adb``):

+ 19 - 10
getting_started/workflow/export/exporting_for_android.rst

@@ -3,20 +3,24 @@
 Exporting for Android
 =====================
 
-Exporting for Android has fewer requirements than compiling Godot for it. The
-following steps detail what is needed to setup the SDK and the engine.
+Exporting for Android has fewer requirements than compiling Godot for it.
+The following steps detail what is needed to setup the SDK and the engine.
 
 Download the Android SDK
 ------------------------
 
 Download and install the Android SDK from
-https://developer.android.com/studio/
+`developer.android.com <https://developer.android.com/studio/>`__.
+
+If you install Android Studio, you need to run it once to complete the SDK setup.
 
 Install OpenJDK or Oracle JDK
 -----------------------------
 
 Download and install  `OpenJDK <https://github.com/ojdkbuild/ojdkbuild>`__ or `Oracle JDK <http://www.oracle.com/technetwork/java/javase/downloads/index.html>`__. Versions below JDK 8 may not work; some users have reported issues with the jarsigner (used to sign the APKs) in JDK 7.
 
+If you install OpenJDK, choose ``1.8``. Don't choose the ``openjdk-jre`` files as that only contains the JRE, not the JDK which is required here.
+
 Create a debug.keystore
 -----------------------
 
@@ -26,16 +30,16 @@ projects, ant or eclipse probably generated one for you (on Linux and
 macOS, you can find it in the ``~/.android`` directory).
 
 If you can't find it or need to generate one, the keytool command from
-the JDK can be used for this purpose:
-
-::
+the JDK can be used for this purpose::
 
     keytool -keyalg RSA -genkeypair -alias androiddebugkey -keypass android -keystore debug.keystore -storepass android -dname "CN=Android Debug,O=Android,C=US" -validity 9999
 
+This will create a ``debug.keystore`` file in your current directory. You should move it to a memorable location such as ``%USERPROFILE%\.android\``, because you will need its location in a later step. For more information on ``keytool`` usage, see `this Q&A article <https://godotengine.org/qa/21349/jdk-android-file-missing>`__.
+
 Make sure you have adb
 ----------------------
 
-Android Debug Bridge (adb) is the command line tool used to communicate with
+Android Debug Bridge (``adb``) is the command line tool used to communicate with
 Android devices. It's installed with the SDK, but you may need to install one
 (any) of the Android API levels for it to be installed in the SDK directory.
 
@@ -54,9 +58,14 @@ Scroll down to the section where the Android settings are located:
 
 In that screen, the path to 3 files needs to be set:
 
--  The *adb* executable (adb.exe on Windows)
--  The *jarsigner* executable (from JDK 6 or 8)
--  The debug *keystore*
+- The ``adb`` executable (``adb.exe`` on Windows)
+  - It can usually be found at ``%LOCALAPPDATA%\Android\Sdk\platform-tools\adb.exe``.
+
+- The ``jarsigner`` executable (from JDK 6 or 8)
+  - On Windows, OpenJDK installs to a dir like ``%PROGRAMFILES%\ojdkbuild\java-1.8.0-openjdk-1.8.0.232-2\bin``. The exact path may vary depending on the OpenJDK update you've installed.
+
+- The debug ``.keystore`` file
+  - It can be found in the folder where you put the ``debug.keystore`` file you created above.
 
 Once that is configured, everything is ready to export to Android!
 

+ 1 - 1
getting_started/workflow/export/exporting_for_web.rst

@@ -225,5 +225,5 @@ defaulting to ``false`` to prevent polluting the global namespace::
 
     func my_func4():
         # execute in global execution context,
-        # thus adding a new JavaScript global variable `MyGlobal`
+        # thus adding a new JavaScript global variable `SomeGlobal`
         JavaScript.eval("var SomeGlobal = {};", true)

+ 5 - 0
getting_started/workflow/export/exporting_pcks.rst

@@ -120,6 +120,11 @@ file in the directory of the games executable. The PCK file contains a
     subfolder). However, it is also a way of creating patches for one's own game. A
     PCK file of this kind can fix the content of a previously loaded PCK.
 
+.. note::
+    For a C# project, you need to build the DLL and place it in the project directory first.
+    Then, before loading the resource pack, you need to load its DLL as follows:
+    ``Assembly.LoadFile("mod.dll")``
+
 Summary
 -------
 

+ 0 - 1
make.bat

@@ -10,7 +10,6 @@ if "%SPHINXBUILD%" == "" (
 set SOURCEDIR=.
 set BUILDDIR=_build
 set SPHINXPROJ=Test
-set SPHINXOPTS=-j auto
 
 if "%1" == "" goto help
 

+ 1 - 0
robots.txt

@@ -1,4 +1,5 @@
 user-agent: *
+disallow: /*/3.2
 disallow: /*/3.1
 disallow: /*/3.0
 disallow: /*/2.0

+ 2 - 2
tutorials/2d/2d_lights_and_shadows.rst

@@ -25,7 +25,7 @@ For this demo we use four textures: two for the lights, one for the shadow caste
 and one for the background. I've included links to them all here if you want to download them
 separately from the demo.
 
-The first is the background image (`bg.png <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/bg.png>`_)
+The first is the background image (`background.png <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/background.png>`_)
 used in the demo. You do not necessarily need a background, but we use one for the demo.
 
 The second is a plain black image (`caster.png <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/caster.png>`_)
@@ -110,7 +110,7 @@ Step by step
 Now that we have covered the basics of the nodes being used, we can now walk step by step through
 the process of making a scene like the one found in the demo.
 
-First add a :ref:`Sprite <class_Sprite>` and set its texture to the `background image <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/bg.png>`_. For your game this can be any
+First add a :ref:`Sprite <class_Sprite>` and set its texture to the `background image <https://raw.githubusercontent.com/godotengine/godot-demo-projects/master/2d/lights_and_shadows/background.png>`_. For your game this can be any
 background you choose. For this style of shadow it is most likely to be a floor texture.
 
 .. image:: img/light_shadow_background.png

+ 48 - 15
tutorials/2d/2d_sprite_animation.rst

@@ -6,18 +6,18 @@
 Introduction
 ------------
 
-In this tutorial, you'll learn two different ways to create 2D animated
-characters. Typically, when you create or download an animated character, it
+In this tutorial, you'll learn how to create 2D animated
+characters with the AnimatedSprite class and the AnimationPlayer. Typically, when you create or download an animated character, it
 will come in one of two ways: as individual images or as a single sprite sheet
-containing all the animation's frames. Depending on which type of assets you
-have, you can choose one of the following solutions.
+containing all the animation's frames.  Both can be animated in Godot with the AnimatedSprite class.
 
 First, we'll use :ref:`AnimatedSprite <class_AnimatedSprite>` to
-animate a collection of individual images. Then, to use a sprite sheet, we'll
-use :ref:`AnimationPlayer <class_AnimationPlayer>` along with the *Animation*
+animate a collection of individual images. Then we will animate a sprite sheet using this class.  Finally, we will learn another way to animate a sprite sheet
+with :ref:`AnimationPlayer <class_AnimationPlayer>` and the *Animation*
 property of :ref:`Sprite <class_Sprite>`.
 
-.. note:: Art for the following examples by https://opengameart.org/users/ansimuz
+.. note:: Art for the following examples by https://opengameart.org/users/ansimuz and by 
+                                           https://opengameart.org/users/tgfcoder
 
 Individual images with AnimatedSprite
 -------------------------------------
@@ -86,12 +86,46 @@ released.
             $AnimatedSprite.stop()
 
 
+Sprite sheet with AnimatedSprite
+--------------------------------
+
+You can also easily animate from a sprite sheet with the class ``AnimatedSprite``.  We will use this public domain sprite sheet:
+
+.. image:: img/2d_animation_frog_spritesheet.png
+
+Right-click the image and choose "Save Image As" to download it, and then copy the image into your project folder.
+
+Set up your scene tree the same way you did previously when using individual images.  Select the ``AnimatedSprite`` and in its *SpriteFrames* property, select
+"New SpriteFrames".
+
+Click on the new SpriteFrames resource.  This time, when the bottom panel appears, select "Add frames from a Sprite Sheet".
+
+.. image:: img/2d_animation_add_from_spritesheet.png
+
+You will be prompted to open a file.  Select your sprite sheet.  
+
+A new window will open, showing your sprite sheet.  The first thing you will need to do is to change the number of vertical and horizontal images in your sprite sheet.  In this sprite sheet, we have four images horizontally and two images vertically.
+
+.. image:: img/2d_animation_spritesheet_select_rows.png
+
+Next, select the frames from the sprite sheet that you want to include in your animation.  We will select the top four, then click "Add 4 frames" to create the animation.
+
+.. image:: img/2d_animation_spritesheet_selectframes.png
+
+You will now see your animation under the list of animations in the bottom panel.  Double click on default to change the name of the animation to jump.
+
+.. image:: img/2d_animation_spritesheet_animation.png
+
+Finally, check Playing on the  AnimatedSprite in the inspector to see your frog jump!
+
+.. image:: img/2d_animation_play_spritesheet_animation.png
+
+
 Sprite sheet with AnimationPlayer
 ---------------------------------
 
-In the event you have a sprite sheet containing all of your animation frames,
-you can't easily use ``AnimatedSprite``. Instead, you can use a standard
-:ref:`Sprite <class_Sprite>` node to display the texture, and then animate the
+Another way that you can animate when using a sprite sheet is to use a standard
+:ref:`Sprite <class_Sprite>` node to display the texture, and then animating the
 change from texture to texture with :ref:`AnimationPlayer <class_AnimationPlayer>`.
 
 Consider this sprite sheet, which contains 6 frames of animation:
@@ -178,8 +212,7 @@ released.
 Summary
 -------
 
-These examples illustrate the two most common situations you'll encounter in
-2D animation. Each has its benefits. Working with ``AnimationPlayer`` is
-a bit more complex, but provides additional functionality, since you can also
-animate other properties like position or scale. Experiment and see which
-works best for your needs.
+These examples illustrate the two classes you can use in Godot for
+2D animation. ``AnimationPlayer`` is
+a bit more complex than ``AnimatedSprite``, but it provides additional functionality, since you can also
+animate other properties like position or scale. The class ``AnimationPlayer`` can also be used with an ``AnimatedSprite``.  Experiment to see what works best for your needs.

BIN
tutorials/2d/img/2d_animation_add_from_spritesheet.png


BIN
tutorials/2d/img/2d_animation_frog_spritesheet.png


BIN
tutorials/2d/img/2d_animation_play_spritesheet_animation.png


BIN
tutorials/2d/img/2d_animation_spritesheet_animation.png


BIN
tutorials/2d/img/2d_animation_spritesheet_select_rows.png


BIN
tutorials/2d/img/2d_animation_spritesheet_selectframes.png


BIN
tutorials/2d/img/viewport_transforms2.png


+ 1 - 1
tutorials/2d/using_tilemaps.rst

@@ -159,7 +159,7 @@ Tips and tricks
 
 - You can flip and rotate tiles using the icons at the top right of the editor.
 
-- To draw straight lines, hold <Shift> while clicking and dragging a tile.
+- To draw straight lines, hold :kbd:`Shift` while clicking and dragging a tile.
 
 - Tools such as copy, paste, and bucket fill, can be found in the "TileMap"
   menu in the upper-right.

+ 4 - 4
tutorials/3d/fps_tutorial/part_one.rst

@@ -566,7 +566,7 @@ Here is what the :ref:`Spatial <class_Spatial>` gizmo shows when you are using l
 Notice how the arrows follow the rotation of the object on the left, which looks exactly
 the same as the 3D example for local space.
 
-.. note:: You can change between local and world space modes by pressing T or the little cube button
+.. note:: You can change between local and world space modes by pressing :kbd:`T` or the little cube button
           when you have a :ref:`Spatial <class_Spatial>` based node selected.
 
 .. image:: img/LocalSpaceExampleGizmo.png
@@ -680,8 +680,8 @@ _________
 To test the code, open up the scene named ``Testing_Area.tscn``, if it's not already opened up. We will be using
 this scene as we go through the next few tutorial parts, so be sure to keep it open in one of your scene tabs.
 
-Go ahead and test your code either by pressing ``F6`` with ``Testing_Area.tscn`` as the open tab, by pressing the
-play button in the top right corner, or by pressing ``F5``.
+Go ahead and test your code either by pressing :kbd:`F6` with ``Testing_Area.tscn`` as the open tab, by pressing the
+play button in the top right corner, or by pressing :kbd:`F5`.
 You should now be able to walk around, jump in the air, and look around using the mouse.
 
 
@@ -829,7 +829,7 @@ Now, when the player is sprinting, we'll use ``SPRINT_ACCEL`` instead of ``ACCEL
 
 _________
 
-You should now be able to sprint if you press the ``shift`` button, and can toggle the flash light on and off by pressing the ``F`` button!
+You should now be able to sprint if you press :kbd:`Shift`, and can toggle the flash light on and off by pressing :kbd:`F`!
 
 Go try it out! You can change the sprint-related class variables to make the player faster or slower when sprinting!
 

+ 5 - 3
tutorials/3d/fps_tutorial/part_three.rst

@@ -23,10 +23,12 @@ Changing levels
 
 Now that we have a fully working FPS, let's move to a more FPS-like level.
 
-Open up ``Space_Level.tscn`` (``assets/Space_Level_Objects/Space_Level.tscn``) and/or ``Ruins_Level.tscn`` (``assets/Ruin_Level_Objects/Ruins_Level.tscn``).
+Open up ``Space_Level.tscn`` (``assets/Space_Level_Objects/Space_Level.tscn``) 
+and/or ``Ruins_Level.tscn`` (``assets/Ruin_Level_Objects/Ruins_Level.tscn``).
 
-``Space_Level.tscn`` and ``Ruins_Level.tscn`` are complete custom FPS levels created for the purpose of this tutorial. Press ``F6`` to
-play the open scene, or press the ``play current scene button``, and give each a try.
+``Space_Level.tscn`` and ``Ruins_Level.tscn`` are complete custom FPS levels 
+created for the purpose of this tutorial. Press ``Play Current Scene`` button,
+or :kbd:`F6` on keyboard, and give each a try.
 
 .. warning:: ``Space_Level.tscn`` is more graphically demanding of the GPU than ``Ruins_Level.tscn``. If your computer is struggling to render
           ``Space_Level.tscn``, try using ``Ruins_Level.tscn`` instead.

+ 7 - 7
tutorials/3d/fps_tutorial/part_two.rst

@@ -300,13 +300,13 @@ reach the point where the muzzle starts to flash.
           light that escapes the muzzle when a bullet is fired. The muzzle is also sometimes referred to as the
           barrel of the gun.
 
-.. tip:: For finer control when scrubbing the timeline, press ``control`` and scroll forward with the mouse wheel to zoom in.
+.. tip:: For finer control when scrubbing the timeline, press :kbd:`Ctrl` and scroll forward with the mouse wheel to zoom in.
          Scrolling backwards will zoom out.
 
          You can also change how the timeline scrubbing snaps by changing the value in ``Step (s)`` to a lower/higher value.
 
-Once you get to a point you like, right click on the row for "Animation Player" and press insert key.
-In the empty name field, enter ``animation_callback`` and press ``enter``.
+Once you get to a point you like, right click on the row for "Animation Player" and press ``Insert Key``.
+In the empty name field, enter ``animation_callback`` and press :kbd:`Enter`.
 
 .. image:: img/AnimationPlayerInsertKey.png
 
@@ -324,7 +324,7 @@ Go to the "Rifle_fire" animation from the animation drop down. Add the call meth
 animation track list by clicking the "Add Track" button above the list. Find the point where the muzzle starts
 to flash and right click and press ``Insert Key`` to add a call method track point at that position on the track.
 
-Type "animation_callback" into the name field of the pop up which opened and press ``enter``.
+Type "animation_callback" into the name field of the pop up which opened and press :kbd:`Enter`.
 
 Now we need to apply the callback method track to the knife animation. Select the "Knife_fire" animation and scroll to the bottom of the
 animation tracks. Click the "Add Track" button above the list and add a method track.
@@ -334,7 +334,7 @@ Next find a point around the first third of the animation to place the animation
          For this tutorial we are reusing the gun firing logic for our knife, so the animation has been named in a style that
          is consistent with the other animations.
 
-From there right click on the timeline and click "Insert Key". Put "animation_callback" into the name field and press ``enter``.
+From there right click on the timeline and click "Insert Key". Put "animation_callback" into the name field and press :kbd:`Enter`.
 
 .. tip:: Be sure to save your work!
 
@@ -354,7 +354,7 @@ its own collision code. In this method we create/spawn a bullet object in the di
 it travels forward.
 
 There are several advantages to this method. The first being we do not have to store the bullets in our player. We can simply create the bullet
-and then move on, and the bullet itself with handle checking for collisions, sending the proper signal(s) to the object it collides with, and destroying itself.
+and then move on, and the bullet itself will handle checking for collisions, sending the proper signal(s) to the object it collides with, and destroying itself.
 
 Another advantage is we can have more complex bullet movement. If we want to make the bullet fall ever so slightly as time goes on, we can make the bullet
 controlling script slowly push the bullet towards the ground. Using an object also makes the bullet take time to reach its target, it doesn't instantly
@@ -1216,7 +1216,7 @@ Now we need to attach this script to all of the :ref:`RigidBody <class_RigidBody
 
 Open up ``Testing_Area.tscn`` and select all the cubes parented to the ``Cubes`` node.
 
-.. tip:: If you select the top cube, and then hold down ``shift`` and select the last cube, Godot will
+.. tip:: If you select the top cube, and then hold down :kbd:`Shift` and select the last cube, Godot will
          select all the cubes in-between!
 
 Once you have all the cubes selected, scroll down in the inspector until you get to

+ 32 - 34
tutorials/3d/high_dynamic_range.rst

@@ -21,11 +21,11 @@ their respective scenes. So what's the problem?
 The display has a limited range of intensity, depending on the display type.
 The game engine renders to an unlimited range of intensity values, however.
 While "maximum intensity" means something to an sRGB display, it has no bearing
-in the game engine; there is only a potentially infinitely wide range of intensity
-values generated per frame of rendering.
+in the game engine; there is only a potentially infinitely wide range
+of intensity values generated per frame of rendering.
 
 This means that some transformation of the scene light intensity, also known
-as scene-referred light ratios, need to be transformed and mapped to fit
+as *scene-referred* light ratios, need to be transformed and mapped to fit
 within the particular output range of the chosen display. This can be most
 easily understood if we consider virtually photographing our game engine scene
 through a virtual camera. Here, our virtual camera would apply a particular
@@ -42,71 +42,69 @@ the ratios out of the uniquely colored lights at each reddish, greenish,
 and blueish emission site.
 
 For a majority of computer displays, the specifications of the display are
-outlined in accordance with IEC 61966-2-1, also known as the 1996 sRGB specification.
-This specification outlines how an sRGB display is to behave, including the
-color of the lights in the LED pixels as well as the transfer characteristics
-of the input (OETF) and output (EOTF).
+outlined in accordance with IEC 61966-2-1, also known as the
+1996 sRGB specification. This specification outlines how an sRGB display
+is to behave, including the color of the lights in the LED pixels as well as
+the transfer characteristics of the input (OETF) and output (EOTF).
 
-Not all displays use the same OETF and EOTF as a computer display however,
-for example, television broadcast displays use the BT.1886 EOTF. It should
-be noted that Godot is limited in its pixel management chain,
-and only supports sRGB displays currently.
+Not all displays use the same OETF and EOTF as a computer display.
+For example, television broadcast displays use the BT.1886 EOTF.
+However, Godot currently only supports sRGB displays.
 
 The sRGB standard is based around the nonlinear relationship between the current
 to light output of common desktop computing CRT displays.
 
 .. image:: img/hdr_gamma.png
 
-The mathematics of a scene referred model require that we multiply the scene by different
-values to adjust the intensities and exposure to different light ranges.
-The transfer function of the display cannot appropriately render
+The mathematics of a scene-referred model require that we multiply the scene by
+different values to adjust the intensities and exposure to different
+light ranges. The transfer function of the display can't appropriately render
 the wider dynamic range of the game engine's scene output using the simple
-transfer function of the display however, and therefore a more complex approach
-to encoding is required.
+transfer function of the display. A more complex approach to encoding
+is required.
 
 Scene linear & asset pipelines
 ------------------------------
 
-Working in scene linear sRGB is not as simple as just pressing a switch. First,
+Working in scene-linear sRGB is not as simple as just pressing a switch. First,
 imported image assets must be converted to linear light ratios on import. Even
-when linearized, those assets may not be perfectly well suited for use as textures,
-depending on how they were generated.
+when linearized, those assets may not be perfectly well suited for use
+as textures, depending on how they were generated.
 
 There are two ways to do this:
 
 sRGB transfer function to display linear ratios on image import
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-This is the easiest, but not the most ideal, method of using sRGB assets.
-One issue with this is loss of quality. Using 8 bit per channel to represent
-linear light ratios is not a sufficient but depth to quantise the values correctly.
-These textures might later be compressed too, which can exacerbate the problem.
+This is the easiest method of using sRGB assets, but it's not the most ideal.
+One issue with this is loss of quality. Using 8 bits per channel to represent
+linear light ratios is not sufficient to quantize the values correctly.
+These textures may also be compressed later, which can exacerbate the problem.
 
 Hardware sRGB transfer function to display linear conversion
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The GPU will do the conversion after reading the
-texel using floating point. This works fine on PC and consoles, but most
-mobile devices do no support it, or do not support it on compressed
-texture format (iOS for example).
+The GPU will do the conversion after reading the texel using floating point.
+This works fine on PC and consoles, but most mobile devices don't support it,
+or they don't support it on compressed texture formats (iOS for example).
 
 Scene linear to display referred nonlinear
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 After all the rendering is done, the scene linear render requires transforming
-to a suitable output such as an sRGB display. To do this, enable sRGB conversion in the
-current :ref:`Environment <class_Environment>` (more on that below).
+to a suitable output such as an sRGB display. To do this, enable sRGB conversion
+in the current :ref:`Environment <class_Environment>` (more on that below).
 
-Keep in mind that sRGB -> Display Linear and Display Linear -> sRGB conversions
-must always be **both** enabled. Failing to enable one of them will
+Keep in mind that the **sRGB -> Display Linear** and **Display Linear -> sRGB**
+conversions must always be **both** enabled. Failing to enable one of them will
 result in horrible visuals suitable only for avant-garde experimental
 indie games.
 
 Parameters of HDR
 -----------------
 
-HDR setting can be found in the :ref:`Environment <class_Environment>`
-resource. These are found most of the time inside a
+HDR settings can be found in the :ref:`Environment <class_Environment>`
+resource. Most of the time, these are found inside a
 :ref:`WorldEnvironment <class_WorldEnvironment>`
-node or set in a camera. For more information see
+node or set in a Camera node. For more information, see
 :ref:`doc_environment_and_post_processing`.

+ 2 - 2
tutorials/3d/introduction_to_3d.rst

@@ -159,9 +159,9 @@ Vector3,Color,etc.).
 
 Some useful keybindings:
 
--  To snap placement or rotation, press the "Ctrl" key while moving, scaling
+-  To snap placement or rotation, press :kbd:`Ctrl` while moving, scaling
    or rotating.
--  To center the view on the selected object, press the "f" key.
+-  To center the view on the selected object, press :kbd:`F`.
 
 View menu
 ---------

+ 4 - 4
tutorials/3d/using_gridmaps.rst

@@ -85,15 +85,15 @@ The "Cell/Size" property should be set to the size of your meshes. You can leave
 it at the default value for the demo. Set the "Center Y" property to "Off".
 
 Now you can start designing the level by choosing a tile from the palette and
-placing it with Left-Click in the editor window. To remove a tile, use
-Shift+Right-click.
+placing it with Left-Click in the editor window. To remove a tile, hold :kbd:`Shift` 
+and use Right-click.
 
 Click on the "GridMap" menu to see options and shortcuts. For example, pressing
-"S" rotates a tile around the y-axis.
+:kbd:`S` rotates a tile around the y-axis.
 
 .. image:: img/gridmap_menu.png
 
-Holding <Shift> and dragging with the left mouse button will draw a selection
+Holding :kbd:`Shift` and dragging with the left mouse button will draw a selection
 box. You can duplicate or clear the selected area using the respective menu
 options.
 

+ 3 - 3
tutorials/animation/cutout_animation.rst

@@ -80,8 +80,8 @@ create a child sprite and load the torso texture, later accommodate it properly:
 .. image:: img/tuto_cutout3.png
 
 This looks good. Let's see if our hierarchy works as a skeleton by
-rotating the torso. We can do this be pressing ``E`` to enter rotate mode,
-and dragging with the left mouse button. To exit rotate mode hit ``ESC``.
+rotating the torso. We can do this be pressing :kbd:`E` to enter rotate mode,
+and dragging with the left mouse button. To exit rotate mode hit :kbd:`ESC`.
 
 .. image:: img/tutovec_torso1.gif
 
@@ -101,7 +101,7 @@ Sprite:
 .. image:: img/tuto_cutout5.png
 
 The pivot can also be adjusted *visually*. While hovering over the
-desired pivot point,  press the "v" key to move the pivot there for the
+desired pivot point,  press :kbd:`V` to move the pivot there for the
 selected Sprite. There is also a tool in the tool bar that has a
 similar function.
 

+ 2 - 2
tutorials/animation/introduction_2d.rst

@@ -99,8 +99,8 @@ to the node and the affected property.
 
    If you animate the wrong property, you can edit a track's path anytime.
    Double click on it and type the new path. Play the animation using the
-   "Play from beginning" button |Play from beginning| (Default shortcut:
-   Shift+D) to see the changes instantly.
+   "Play from beginning" button |Play from beginning| (or pressing
+   :kbd:`Shift + D` on keyboard) to see the changes instantly.
 
 Tutorial: Creating a simple animation
 -------------------------------------

+ 61 - 5
tutorials/assetlib/uploading_to_assetlib.rst

@@ -13,6 +13,67 @@ As mentioned in the :ref:`doc_using_assetlib` document, in order to be able to
 submit assets to the AssetLib, you need to have a registered account, and be
 logged in.
 
+Submission guidelines
+---------------------
+
+Before submitting your asset, please ensure it follows all of the
+requirements, and also consider following the recommendations.
+
+Requirements
+~~~~~~~~~~~~
+
+Generally speaking, most assets people submit to the asset library
+are accepted. However, in order for your asset to be accepted, there
+are a few requirements your asset needs to meet to be approved.
+
+* The asset must work. If the asset doesn't run or otherwise doesn't
+  work in the specified Godot version, then it will be rejected.
+
+* No submodules, or any submodules must be non-essential. GitHub
+  does not include submodules in the downloaded ZIP file, so if the
+  asset needs the contents of the submodule, your asset won't work.
+
+* The license needs to be correct. The license listed on the asset
+  library must match the license in the repository.
+
+* Do not set the download commit to "master". The asset library validates
+  all assets with a SHA256 hash, so the version hosted on GitHub needs
+  to be *exactly* the same. Instead of "master", either specify a commit
+  hash, or tag versions and specify a version number.
+
+* Use proper English for the name and description of your asset.
+  This includes using correct capitalization, and using full
+  sentences in the description.
+
+* The icon link must be a direct link. For icons hosted on GitHub, the
+  link must start with "raw.githubusercontent.com", not "github.com".
+
+Recommendations
+~~~~~~~~~~~~~~~
+
+These things are not required for your asset to be approved, but
+if you follow these recommendations, you can help make the asset
+library a better place for all users.
+
+* Fix or suppress all script warnings. The warning system is there to
+  help identify issues with your code, but people using your asset
+  don't need to see them.
+
+* Make your code conform to the official style guides. Having a
+  consistent style helps other people read your code, and it also helps
+  if other people wish to contribute to your asset. See: the
+  :ref:`doc_gdscript_styleguide` or the :ref:`doc_c_sharp_styleguide`.
+
+* If your asset is a library for working with other files,
+  consider including example files in the asset.
+
+* The icon should be a square, its aspect ratio should be 1:1. It should
+  also ideally have a minimum resolution of 64x64 pixels.
+
+* While the asset library allows more than just GitHub, consider
+  hosting your asset's source code on GitHub. Other services may not
+  work reliably, and a lack of familiarity can be a barrier to contributors.
+
 Submitting
 ----------
 
@@ -102,9 +163,4 @@ You may have some luck accelerating the approval process by messaging the
 moderators/assetlib reviewers on IRC (the #godotengine-atelier channel on Freenode),
 or the official Discord server.
 
-Submission guidelines
----------------------
-
-[TODO]
-
 .. |image0| image:: ./img/assetlib_submit.png

+ 13 - 0
tutorials/assetlib/what_is_assetlib.rst

@@ -25,6 +25,19 @@ Please note that the AssetLib is relatively young - it may have various pain poi
 and usability issues. As with all Godot projects, the code repository is available on `GitHub <https://github.com/godotengine/godot-asset-library>`_,
 where you can submit pull requests and issues, so please do not hesitate to visit it!
 
+Types of assets
+---------------
+
+Be aware that there are, broadly, two different types of assets you can post.
+
+* Assets labeled as "Templates", "Projects", or "Demos" appear under
+  the "Templates" tab in the Godot project manager. These assets are
+  standalone Godot projects that can run by themselves.
+
+* Other assets show up inside of the Godot editor under the "AssetLib"
+  main screen tab, next to "2D", "3D", and "Script". These assets are
+  meant to be downloaded and placed into an existing Godot project.
+
 Frequently asked questions
 --------------------------
 

+ 1 - 9
tutorials/audio/sync_with_audio.rst

@@ -32,15 +32,7 @@ This delay can't be avoided but it can be estimated by calling :ref:`AudioServer
 
 The output latency (what happens after the mix) can also be estimated by calling :ref:`AudioServer.get_output_latency()<class_AudioServer_method_get_output_latency>`.
 
-Add these two and it's possible to guess almost exactly when sound or music will begin playing in the speakers:
-
-.. tabs::
- .. code-tab:: gdscript GDScript
-
-    var actual_play_time = AudioServer.get_time_to_next_mix() + AudioServer.get_output_latency()
-    $Song.play()
-
-This way, obtaining the actual playback position during *_process()* is possible:
+Add these two and it's possible to guess almost exactly when sound or music will begin playing in the speakers during *_process()*:
 
 .. tabs::
  .. code-tab:: gdscript GDScript

+ 1 - 1
tutorials/content/procedural_geometry/immediategeometry.rst

@@ -10,7 +10,7 @@ API like the SurfaceTool, but it's actually designed to create content on the fl
 Generating complex geometry (several thousand vertices) with this node is inefficient, even if it's
 done only once. Instead, it is designed to generate simple geometry that changes every frame.
 
-Before starting, you should clear the clear the geometry by calling ``clear()``. This ensures that
+Before starting, you should clear the geometry by calling ``clear()``. This ensures that
 you are not building upon the geometry from the previous frame. If you want to keep geometry between frames, do
 not call ``clear()``.
 

+ 128 - 7
tutorials/inputs/input_examples.rst

@@ -31,17 +31,34 @@ Examples:
 .. tabs::
  .. code-tab:: gdscript GDScript
 
-    # input event - runs when the input happens
     func _input(event):
         if event.is_action_pressed("jump"):
             jump()
 
-    # polling - runs every frame
     func _physics_process(delta):
         if Input.is_action_pressed("move_right"):
-            # move as long as the key/button is pressed
+            # Move as long as the key/button is pressed.
             position.x += speed * delta
 
+ .. code-tab:: csharp
+
+    public override void _Input(InputEvent inputEvent)
+    {
+        if (inputEvent.IsActionPressed("jump"))
+        {
+            Jump();
+        }
+    }
+
+    public override void _PhysicsProcess(float delta)
+    {
+        if (Input.IsActionPressed("move_right"))
+        {
+            // Move as long as the key/button is pressed.
+            position.x += speed * delta;
+        }
+    }
+
 This gives you the flexibility to mix-and-match the type of input processing
 you do.
 
@@ -64,6 +81,13 @@ attach the following script:
     func _input(event):
         print(event.as_text())
 
+ .. code-tab:: csharp
+
+    public override void _Input(InputEvent inputEvent)
+    {
+        GD.Print(inputEvent.AsText());
+    }
+
 As you press keys, move the mouse, and perform other inputs, you'll see each
 event scroll by in the output window. Here's an example of the output:
 
@@ -83,7 +107,7 @@ input. Key events are even printed as their key symbols. For example, let's cons
 It inherits from the following classes:
 
 - :ref:`InputEvent <class_InputEvent>` - the base class for all input events
-- :ref:`InputEventWithModifiers <class_InputEventWithModifiers>` - adds the ability to check if modifiers are pressed, such as ``Shift`` or ``Alt``.
+- :ref:`InputEventWithModifiers <class_InputEventWithModifiers>` - adds the ability to check if modifiers are pressed, such as :kbd:`Shift` or :kbd:`Alt`.
 - :ref:`InputEventMouse <class_InputEventMouse>` - adds mouse event properties, such as ``position``
 - :ref:`InputEventMouseButton <class_InputEventMouseButton>` - contains the index of the button that was pressed, whether it was a double-click, etc.
 
@@ -102,6 +126,15 @@ avoid this, make sure to test the event type first:
         if event is InputEventMouseButton:
             print("mouse button event at ", event.position)
 
+ .. code-tab:: csharp
+
+    public override void _Input(InputEvent inputEvent)
+    {
+        if (inputEvent is InputEventMouseButton mouseEvent)
+        {
+            GD.Print($"mouse button event at {mouseEvent.Position}");
+        }
+    }
 
 InputMap
 --------
@@ -129,13 +162,23 @@ the action you're looking for:
         if event.is_action_pressed("my_action"):
             print("my_action occurred!")
 
+ .. code-tab:: csharp
+
+    public override void _Input(InputEvent inputEvent)
+    {
+        if (inputEvent.IsActionPressed("my_action"))
+        {
+            GD.Print("my_action occurred!");
+        }
+    }
+
 Keyboard events
 ---------------
 
 Keyboard events are captured in :ref:`InputEventKey <class_InputEventKey>`.
 While it's recommended to use input actions instead, there may be cases where
 you want to specifically look at key events. For this example, let's check for
-the "T" key:
+the :kbd:`T`:
 
 .. tabs::
  .. code-tab:: gdscript GDScript
@@ -145,6 +188,19 @@ the "T" key:
             if event.scancode == KEY_T:
                 print("T was pressed")
 
+ .. code-tab:: csharp
+
+    public override void _Input(InputEvent inputEvent)
+    {
+        if (inputEvent is InputEventKey keyEvent && keyEvent.Pressed)
+        {
+            if ((Keylist)keyEvent.Scancode == KeyList.T)
+            {
+                GD.Print("T was pressed");
+            }
+        }
+    }
+
 .. tip:: See :ref:`@GlobalScope_KeyList <enum_@GlobalScope_KeyList>` for a list of scancode
         constants.
 
@@ -154,8 +210,8 @@ Keyboard modifiers
 Modifier properties are inherited from
 :ref:`InputEventWithModifiers <class_InputEventWithModifiers>`. This  allows
 you to check for modifier combinations using boolean properties. Let's imagine
-you want one thing to happen when the "T" key is pressed, but something
-different when it's "Shift+T":
+you want one thing to happen when the :kbd:`T` is pressed, but something
+different when it's :kbd:`Shift + T`:
 
 .. tabs::
  .. code-tab:: gdscript GDScript
@@ -168,6 +224,21 @@ different when it's "Shift+T":
                 else:
                     print("T was pressed")
 
+ .. code-tab:: csharp
+
+    public override void _Input(InputEvent inputEvent)
+    {
+        if (inputEvent is InputEventKey keyEvent && keyEvent.Pressed)
+        {
+            switch ((KeyList)keyEvent.Scancode)
+            {
+                case KeyList.T:
+                    GD.Print(keyEvent.Shift ? "Shift+T was pressed" : "T was pressed");
+                    break;
+            }
+        }
+    }
+
 .. tip:: See :ref:`@GlobalScope_KeyList <enum_@GlobalScope_KeyList>` for a list of scancode
         constants.
 
@@ -198,6 +269,24 @@ also counts as a button - two buttons, to be precise, with both
             if event.button_index == BUTTON_WHEEL_UP and event.pressed:
                 print("Wheel up")
 
+ .. code-tab:: csharp
+
+    public override void _Input(InputEvent inputEvent)
+    {
+        if (inputEvent as InputEventMouseButton mouseEvent && mouseEvent.Pressed)
+        {
+            switch ((ButtonList)mouseEvent.ButtonIndex)
+            {
+                case ButtonList.Left:
+                    GD.Print($"Left button was clicked at {mouseEvent.Position}");
+                    break;
+                case ButtonList.WheelUp:
+                    GD.Print("Wheel up");
+                    break;
+            }
+        }
+    }
+
 Mouse motion
 ~~~~~~~~~~~~
 
@@ -230,6 +319,38 @@ node:
             # While dragging, move the sprite with the mouse.
             $Sprite.position = event.position
 
+ .. code-tab:: csharp
+
+    public override void _Input(InputEvent inputEvent)
+    {
+        var sprite = GetNodeOrNull<Sprite>("Sprite");
+        if (sprite == null)
+            return;// No suitable node was found.
+
+        if (inputEvent is InputEventMouseButton mouseEvent && (ButtonList)mouseEvent.ButtonIndex == ButtonList.Left)
+        {
+            if ((mouseEvent.Position - sprite.Position).Length() < clickRadius)
+            {
+                // Start dragging if the click is on the sprite.
+                if (!dragging && mouseEvent.Pressed)
+                    dragging = !dragging;
+            }
+            // Stop dragging if the button is released.
+            if (dragging && !mouseEvent.Pressed)
+            {
+                dragging = false;
+            }
+        }
+        else
+        {
+            if (inputEvent is InputEventMouseMotion motionEvent)
+            {
+                // While dragging, move the sprite with the mouse.
+                sprite.Position = motionEvent.Position;
+            }
+        }
+    }
+
 Touch events
 ------------
 

+ 24 - 24
tutorials/io/files/resource_queue.gd

@@ -2,21 +2,24 @@ var thread
 var mutex
 var sem
 
-var time_max = 100 # msec
+var time_max = 100 # Milliseconds.
 
 var queue = []
 var pending = {}
 
-func _lock(caller):
+func _lock(_caller):
 	mutex.lock()
 
-func _unlock(caller):
+
+func _unlock(_caller):
 	mutex.unlock()
 
-func _post(caller):
+
+func _post(_caller):
 	sem.post()
 
-func _wait(caller):
+
+func _wait(_caller):
 	sem.wait()
 
 
@@ -25,8 +28,7 @@ func queue_resource(path, p_in_front = false):
 	if path in pending:
 		_unlock("queue_resource")
 		return
-
-	elif ResourceLoader.has(path):
+	elif ResourceLoader.has_cached(path):
 		var res = ResourceLoader.load(path)
 		pending[path] = res
 		_unlock("queue_resource")
@@ -43,6 +45,7 @@ func queue_resource(path, p_in_front = false):
 		_unlock("queue_resource")
 		return
 
+
 func cancel_resource(path):
 	_lock("cancel_resource")
 	if path in pending:
@@ -51,6 +54,7 @@ func cancel_resource(path):
 		pending.erase(path)
 	_unlock("cancel_resource")
 
+
 func get_progress(path):
 	_lock("get_progress")
 	var ret = -1
@@ -60,9 +64,9 @@ func get_progress(path):
 		else:
 			ret = 1.0
 	_unlock("get_progress")
-
 	return ret
 
+
 func is_ready(path):
 	var ret
 	_lock("is_ready")
@@ -70,16 +74,15 @@ func is_ready(path):
 		ret = !(pending[path] is ResourceInteractiveLoader)
 	else:
 		ret = false
-
 	_unlock("is_ready")
-
 	return ret
 
+
 func _wait_for_resource(res, path):
 	_unlock("wait_for_resource")
 	while true:
 		VisualServer.sync()
-		OS.delay_usec(16000) # wait 1 frame
+		OS.delay_usec(16000) # Wait approximately 1 frame.
 		_lock("wait_for_resource")
 		if queue.size() == 0 || queue[0] != res:
 			return pending[path]
@@ -95,13 +98,11 @@ func get_resource(path):
 				var pos = queue.find(res)
 				queue.remove(pos)
 				queue.insert(0, res)
-
+			
 			res = _wait_for_resource(res, path)
-
 			pending.erase(path)
 			_unlock("return")
 			return res
-
 		else:
 			var res = pending[path]
 			pending.erase(path)
@@ -111,33 +112,32 @@ func get_resource(path):
 		_unlock("return")
 		return ResourceLoader.load(path)
 
+
 func thread_process():
 	_wait("thread_process")
-
 	_lock("process")
-
+	
 	while queue.size() > 0:
-
 		var res = queue[0]
-
 		_unlock("process_poll")
 		var ret = res.poll()
 		_lock("process_check_queue")
-
+		
 		if ret == ERR_FILE_EOF || ret != OK:
 			var path = res.get_meta("path")
-			if path in pending: # else it was already retrieved
+			if path in pending: # Else, it was already retrieved.
 				pending[res.get_meta("path")] = res.get_resource()
-
-			queue.erase(res) # something might have been put at the front of the queue while we polled, so use erase instead of remove
-
+			# Something might have been put at the front of the queue while
+			# we polled, so use erase instead of remove.
+			queue.erase(res)
 	_unlock("process")
 
 
-func thread_func(u):
+func thread_func(_u):
 	while true:
 		thread_process()
 
+
 func start():
 	mutex = Mutex.new()
 	sem = Semaphore.new()

+ 3 - 3
tutorials/legal/complying_with_licenses.rst

@@ -21,10 +21,10 @@ This text reads as follows:
 
 	This game uses Godot Engine, available under the following license:
 
-	Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.
-	Copyright (c) 2014-2019 Godot Engine contributors.
+	Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.
+	Copyright (c) 2014-2020 Godot Engine contributors.
 
-	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:
+	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.
 

BIN
tutorials/math/img/bezier_cubic_handles.png


BIN
tutorials/math/img/bezier_cubic_points.png


BIN
tutorials/math/img/bezier_path_2d.png


BIN
tutorials/math/img/bezier_point_amount.png


BIN
tutorials/math/img/bezier_quadratic_points.png


BIN
tutorials/math/img/empty_grid.png


BIN
tutorials/math/img/matrices_and_transforms/3d-identity.png


BIN
tutorials/math/img/matrices_and_transforms/3d-identity.xcf


BIN
tutorials/math/img/matrices_and_transforms/apply.png


BIN
tutorials/math/img/matrices_and_transforms/apply.xcf


BIN
tutorials/math/img/matrices_and_transforms/identity-godot.png


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