Ver código fonte

Merge branch 'master' into 3.2

Rémi Verschelde 5 anos atrás
pai
commit
76cf11c890
67 arquivos alterados com 1097 adições e 363 exclusões
  1. 12 8
      .github/workflows/ci.yml
  2. 0 4
      Makefile
  3. 1 1
      about/list_of_features.rst
  4. 10 9
      community/channels.rst
  5. 136 39
      community/contributing/best_practices_for_engine_contributors.rst
  6. 4 0
      community/contributing/docs_writing_guidelines.rst
  7. 412 0
      community/contributing/editor_and_docs_localization.rst
  8. BIN
      community/contributing/img/l10n_01_language_list.png
  9. BIN
      community/contributing/img/l10n_02_new_translation.png
  10. BIN
      community/contributing/img/l10n_03_translation_overview.png
  11. BIN
      community/contributing/img/l10n_04_translation_interface.png
  12. BIN
      community/contributing/img/l10n_05_search_location.png
  13. BIN
      community/contributing/img/l10n_06_browse_by_location.png
  14. BIN
      community/contributing/img/l10n_07_download_po_file.png
  15. BIN
      community/contributing/img/l10n_08_edit_on_github.png
  16. BIN
      community/contributing/img/l10n_09_path_to_image.png
  17. 1 0
      community/contributing/index.rst
  18. 6 5
      community/contributing/updating_the_class_reference.rst
  19. 9 0
      community/contributing/ways_to_contribute.rst
  20. 1 1
      conf.py
  21. 5 0
      development/cpp/object_class.rst
  22. 4 12
      getting_started/scripting/c_sharp/c_sharp_basics.rst
  23. 29 2
      getting_started/scripting/gdscript/gdscript_basics.rst
  24. 9 21
      getting_started/scripting/gdscript/gdscript_exports.rst
  25. 1 1
      getting_started/step_by_step/exporting.rst
  26. 1 1
      getting_started/step_by_step/scripting.rst
  27. 2 2
      getting_started/step_by_step/ui_game_user_interface.rst
  28. 10 0
      getting_started/step_by_step/ui_main_menu.rst
  29. 5 3
      getting_started/workflow/assets/importing_scenes.rst
  30. 3 3
      getting_started/workflow/best_practices/autoloads_versus_internal_nodes.rst
  31. 1 1
      getting_started/workflow/export/exporting_for_android.rst
  32. 17 4
      getting_started/workflow/export/exporting_for_dedicated_servers.rst
  33. 3 0
      getting_started/workflow/export/exporting_for_ios.rst
  34. 6 0
      tutorials/assetlib/uploading_to_assetlib.rst
  35. 3 2
      tutorials/audio/recording_with_microphone.rst
  36. 3 0
      tutorials/audio/sync_with_audio.rst
  37. 2 2
      tutorials/content/procedural_geometry/meshdatatool.rst
  38. 26 18
      tutorials/gui/gui_skinning.rst
  39. 2 0
      tutorials/inputs/custom_mouse_cursor.rst
  40. 53 29
      tutorials/inputs/input_examples.rst
  41. 6 6
      tutorials/inputs/inputevent.rst
  42. 4 4
      tutorials/inputs/mouse_and_input_coordinates.rst
  43. 25 18
      tutorials/io/background_loading.rst
  44. 11 10
      tutorials/io/saving_games.rst
  45. BIN
      tutorials/math/img/vector_cross1.png
  46. 0 0
      tutorials/math/img/vector_cross2.png
  47. BIN
      tutorials/math/img/vector_dot1.png
  48. BIN
      tutorials/math/img/vector_dot2.png
  49. 4 10
      tutorials/math/vector_math.rst
  50. 70 69
      tutorials/misc/binary_serialization_api.rst
  51. 8 8
      tutorials/misc/running_code_in_the_editor.rst
  52. 12 9
      tutorials/optimization/using_multimesh.rst
  53. 9 3
      tutorials/optimization/using_servers.rst
  54. 1 1
      tutorials/platform/android_in_app_purchases.rst
  55. 33 1
      tutorials/platform/services_for_ios.rst
  56. 6 0
      tutorials/plugins/editor/import_plugins.rst
  57. 11 3
      tutorials/plugins/editor/inspector_plugins.rst
  58. 33 24
      tutorials/plugins/editor/making_plugins.rst
  59. 26 8
      tutorials/plugins/editor/spatial_gizmos.rst
  60. 13 2
      tutorials/plugins/editor/visual_shader_plugins.rst
  61. 2 2
      tutorials/shading/shading_reference/shading_language.rst
  62. 9 0
      tutorials/threads/using_multiple_threads.rst
  63. 4 4
      tutorials/viewports/custom_postprocessing.rst
  64. 24 8
      tutorials/viewports/multiple_resolutions.rst
  65. 2 2
      tutorials/viewports/viewports.rst
  66. 4 1
      tutorials/vr/developing_for_oculus_quest.rst
  67. 3 2
      tutorials/vr/vr_primer.rst

+ 12 - 8
.github/workflows/ci.yml

@@ -8,16 +8,20 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v2
 
-      - name: Lint and build documentation
+      - name: Install dependencies
         run: |
           # Install tools used by `_tools/format.sh`.
-          sudo apt-get update -qq
-          sudo apt-get install -qq dos2unix recode
-          # Append the `PATH` so we can run `codespell`.
-          export PATH="$HOME/.local/bin:$PATH"
-          pip3 install -r requirements.txt
-          pip3 install codespell
+          sudo apt-get -qq update
+          sudo apt-get -qq install dos2unix recode
+          sudo pip3 install -r requirements.txt
+          sudo pip3 install codespell
+
+      - name: Linter checks
+        run: |
           bash _tools/format.sh
           codespell -I _tools/codespell-ignore.txt {about,community,development,getting_started,tutorials}/**/*.rst
+
+      - name: Sphinx build
+        run: |
           # Use dummy builder to improve performance.
-          sphinx-build --color -b dummy -d _build/doctrees . _build/html
+          sphinx-build --color -b dummy -d _build/doctrees -W . _build/html

+ 0 - 4
Makefile

@@ -13,10 +13,6 @@ ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
 $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
 endif
 
-# check for latex dependencies
-E := $(foreach exec, $(LATEXDEPS),\
-	$(if $(shell which $(exec)), some string,$(warning The $(exec) command was not found: math formulas will not be built. LaTeX is required for math formula support. If you don't have LaTeX installed, grab it from https://www.latex-project.org/get/)))
-
 # Internal variables.
 PAPEROPT_a4     = -D latex_paper_size=a4
 PAPEROPT_letter = -D latex_paper_size=letter

+ 1 - 1
about/list_of_features.rst

@@ -146,7 +146,7 @@ Editor
 - *GLES3:* Proximity fade (soft particles).
 - Distance fade which can use alpha blending or dithering to avoid going through
   the transparent pipeline.
-   - Dithering can be determined on a per-pixel or per-object basis.
+- Dithering can be determined on a per-pixel or per-object basis.
 
 **Real-time lighting:**
 

+ 10 - 9
community/channels.rst

@@ -17,18 +17,18 @@ Q&A
 IRC on Freenode
 ---------------
 
-- `General: #godotengine <http://webchat.freenode.net/?channels=#godotengine>`_
-- `Engine development: #godotengine-devel <http://webchat.freenode.net/?channels=#godotengine-devel>`_
-- `Documentation: #godotengine-doc <http://webchat.freenode.net/?channels=#godotengine-doc>`_
-- `Pull request meetings: #godotengine-meeting <http://webchat.freenode.net/?channels=#godotengine-meeting>`_
-- `GDNative: #godotengine-gdnative <http://webchat.freenode.net/?channels=#godotengine-gdnative>`_
-- `Website and public relations: #godotengine-atelier <http://webchat.freenode.net/?channels=#godotengine-atelier>`_
+- `General: #godotengine <https://webchat.freenode.net/?channels=#godotengine>`_
+- `Engine development: #godotengine-devel <https://webchat.freenode.net/?channels=#godotengine-devel>`_
+- `Documentation: #godotengine-doc <https://webchat.freenode.net/?channels=#godotengine-doc>`_
+- `Pull request meetings: #godotengine-meeting <https://webchat.freenode.net/?channels=#godotengine-meeting>`_
+- `GDNative: #godotengine-gdnative <https://webchat.freenode.net/?channels=#godotengine-gdnative>`_
+- `Website and public relations: #godotengine-atelier <https://webchat.freenode.net/?channels=#godotengine-atelier>`_
 - `IRC logs <https://godot.eska.me/irc-logs/>`_
 
 Other chats
 -----------
 
-- `Discord Server <https://discordapp.com/invite/zH7NUgz>`_
+- `Discord <https://discord.gg/4JBkykG>`_
 - `Matrix (IRC compatible) <https://matrix.to/#/#godotengine:matrix.org>`_
 
 Language-based communities
@@ -45,7 +45,8 @@ Social networks
 
 - `GitHub <https://github.com/godotengine/>`_
 - `Facebook group <https://www.facebook.com/groups/godotengine/>`_
-- `Twitter (also, #godotengine) <https://twitter.com/godotengine>`_
+- `Twitter <https://twitter.com/godotengine>`_
+  (see also the `#GodotEngine <https://twitter.com/hashtag/GodotEngine>`_ hashtag)
 - `Reddit <https://www.reddit.com/r/godot>`_
 - `YouTube <https://www.youtube.com/c/GodotEngineOfficial>`_
 - `Steam <https://steamcommunity.com/app/404790>`_
@@ -53,4 +54,4 @@ Social networks
 Forum
 -----
 
-- `Forum (godotforums.org) <https://godotforums.org/>`_
+- `Godot Forums <https://godotforums.org/>`_

+ 136 - 39
community/contributing/best_practices_for_engine_contributors.rst

@@ -6,16 +6,26 @@ 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.
+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.
+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.
+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*.
+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
 --------------
@@ -23,117 +33,204 @@ 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.
+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.
+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?
+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*.
+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:
+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.
+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.
+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:
+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.
+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.
+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.
+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.
+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.
+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 a 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.
+For developers, the perspective is different. They may find the user's problem
+too unique to justify a solution (instead of a 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.
+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.
+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.
+
+Also, Godot's philosophy is to favor ease of use and maintenance over absolute
+performance. Performance optimizations will be considered, but they may not
+be accepted if they make something too difficult to use or if they add too much
+complexity to the codebase.
 
 #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.
+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.
+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.
+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.
+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 are rarely flexible enough for all users, which keep requesting more functions added (and making the API and codebase more and more complex).
+Big and flexible solutions also have an additional drawback which is that, over
+time, they are rarely 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.
+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.
+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.
+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?
+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 logic that already exists.
+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 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.
+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.
+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.
+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 on it, and because it's key for new contributors as a starting point to learning the codebase.
+This is bad, because readability and cleanness of core APIs is always of extreme
+importance given how much code relies on 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.
+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.
+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.
+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.
+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.
+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 - 0
community/contributing/docs_writing_guidelines.rst

@@ -112,6 +112,10 @@ The progressive forms describe continuous actions. E.g. "is calling",
     Vector2 move ( Vector2 rel_vec )
     Moves the body in the vector's direction. The body **stops** if it collides with an obstacle. [...]
 
+Exception: If the subject is not clear, replacing "ing" verbs is not an
+improvement. For example, in the previous sentence, "it replaces"
+would not make much sense where "replacing" currently is.
+
 You may use the progressive tense to describe actions that are
 continuous in time. Anything like animation or coroutines.
 

+ 412 - 0
community/contributing/editor_and_docs_localization.rst

@@ -0,0 +1,412 @@
+.. _doc_editor_and_docs_localization:
+
+Editor and docs localization
+============================
+
+.. highlight:: none
+
+Godot aims to make game development available to everyone, including people who
+may not know or be comfortable with English. Therefore, we do our best to make
+the most important resources available in many languages, thanks to the
+translation effort of the community.
+
+These resources include:
+
+1. The `Godot editor's interface <https://hosted.weblate.org/projects/godot-engine/godot/>`__
+   (ca. 15,000 words).
+2. The `online documentation <https://hosted.weblate.org/projects/godot-engine/godot-docs/>`__
+   (editor manual and tutorials, ca. 300,000 words).
+3. The `class reference <https://hosted.weblate.org/projects/godot-engine/godot-class-reference/>`__,
+   available both online and in the editor (ca. 200,000 words).
+
+To manage translations, we use the GNU gettext file format (``PO`` files), and
+the open source `Weblate <https://weblate.org>`__ web-based localization
+platform, which allows easy collaboration of many contributors to complete the
+translation for the various components, and keep them up to date. Click the bold
+links above to access each resource on Weblate.
+
+This page gives an overview of the general translation workflow on Weblate, and
+some resource-specific instructions on e.g. how to handle some keywords or the
+localization of images.
+
+.. tip::
+
+    Translating all the official Godot content is a massive undertaking, so we
+    advise prioritizing the resources as they are listed above: first the editor
+    interface, then the online documentation, and eventually the class reference
+    if there are enough translators to keep up with updates.
+
+Using Weblate for translations
+------------------------------
+
+While our translations eventually reside in the Git repositories of the Godot
+engine and its documentation, all translation updates are handled through
+Weblate, and thus direct pull requests to the Git repositories are not accepted.
+Translations are synced manually between Weblate and the Godot repositories by
+maintainers.
+
+You should therefore `register on Weblate <https://hosted.weblate.org/accounts/register/>`__
+to contribute to Godot's translations.
+
+Once signed in, browse to the Godot resource which you want to contribute to (in
+this page we will use the `editor translation <https://hosted.weblate.org/projects/godot-engine/godot/>`__
+as an example) to find the list of all languages:
+
+.. image:: img/l10n_01_language_list.png
+
+.. seealso::
+
+    Feel free to consult Weblate's own documentation on the `translation
+    workflow <https://docs.weblate.org/en/latest/user/translating.html>`__ for
+    more details.
+
+Adding a new language
+^^^^^^^^^^^^^^^^^^^^^
+
+If your language is already listed, click on its name to access the overview,
+and skip the rest of this section.
+
+If your language is not listed, scroll to the bottom of the list of languages
+and click the "Start new translation" button, and select the language you want
+to translate to:
+
+.. image:: img/l10n_02_new_translation.png
+
+.. important::
+
+    If your language is spoken in several countries with only limited regional
+    variations, please consider adding it with its generic variant (e.g. ``fr``
+    for French) instead of a regional variant (e.g. ``fr_FR`` for French
+    (France), ``fr_CA`` for French (Canada), or ``fr_DZ`` for French (Algeria)).
+
+    Godot has a huge amount of content to translate, so duplicating the work for
+    regional variants should only be done if the language variations are
+    significant enough. Additionally, if a translation is done with for a
+    regional variant, it will only be available automatically for users located
+    in this region (or having their system language configured for this region).
+
+    When regional variations are significant enough to warrant separate
+    translations, we advise to focus on completing a generic variant first if
+    possible, then duplicate the fully completed translation for regional
+    variants and do the relevant edits. This is typically a good strategy for
+    e.g. Spanish (work on ``es`` first, then duplicate it to ``es_AR``,
+    ``es_ES``, ``es_MX``, etc. if necessary) or Portuguese (``pt_BR`` vs
+    ``pt_PT``).
+
+Translation interface
+^^^^^^^^^^^^^^^^^^^^^
+
+Once a language has been selected, you will see an overview of the translation
+status, including how many strings are left to translate or review. Each item
+can be clicked and used to browse through the corresponding list. You can also
+click the "Translate" button to get started on the list of strings needing
+action.
+
+.. image:: img/l10n_03_translation_overview.png
+
+After selecting a list of clicking "Translate", you will see the main
+translation interface where all the work happens:
+
+.. image:: img/l10n_04_translation_interface.png
+
+On that page, you have:
+
+ - A toolbar which lets you cycle through strings of the current list, change
+   to another pre-defined list or do a custom search, etc. There is also a "Zen"
+   editing mode with a simplified interface.
+ - The actual string you are working on in the "Translation" panel. By default,
+   there should be the English source string and an edit box for your language.
+   If you are familiar with other languages, you can add them in your user
+   settings to give you more context for translation.
+   Once you are done editing the current string, press "Save" to confirm changes
+   and move to the next entry. Alternatively, use the "Skip" button to skip it.
+   The "Needs editing" checkbox means that the original string was updated, and
+   the translation therefore needs review to take those changes into account (in
+   PO jargon, these are so-called "fuzzy" strings). Such strings won't be used
+   in the translation until fixed.
+ - The bottom panel has various tools which can help with the translation
+   effort, such as context from nearby strings (usually from the same editor
+   tool or documentation page, so they might use similar terms), comments from
+   other translators, machine translations, and a list of all other existing
+   translations for that string.
+ - On the top right, the glossary shows terms for which an entry has been added
+   previously, and which are included in the current string. For example, if
+   you decided with fellow translators to use a specific translation for the
+   "node" term in Godot, you can add it to the glossary to ensure that other
+   translators use the same convention.
+ - The bottom right panel includes information on the source string. The most
+   relevant item is the "source string location", which links you to the
+   original string on GitHub. You may need to search for the string in the page
+   to locate it and its surrounding context.
+
+Locating original content
+-------------------------
+
+PO files are an ordered list of source strings (``msgid``) and their translation
+(``msgstr``), and by default, Weblate will present the strings in that order. It
+can therefore be useful to understand how the content is organized in the PO
+files to help you locate the original content and use it as a reference when
+translating.
+
+.. important::
+
+    It is primordial to use the original context as reference when translating,
+    as many words have several possible translations depending on the context.
+    Using the wrong translation can actually be detrimental to the user and make
+    things harder to understand than if they stayed in English.
+    Using the context also makes the translation effort much easier and more
+    enjoyable, as you can see directly if the translation you wrote will make
+    sense in context.
+
+- The editor interface's translation template is generated by parsing all the
+  C++ source code in **alphabetical order**, so all the strings defined in a
+  given file will be grouped together. For example, if the "source string
+  location" indicates ``editor/code_editor.cpp``, the current string (and the
+  nearby ones) is defined in the ``editor/code_editor.cpp`` code file, and is
+  thereby related to the code editors in Godot (GDScript, shaders).
+- The online documentation's translation template is generated from the source
+  RST files in the same order as seen in the **table of contents**, so for
+  example the first strings are from the front page of the documentation.
+  The recommended workflow is therefore to find a unique string corresponding to
+  a page that you want to translate, and then translate all the strings with the
+  same source string location while comparing with the online version of that
+  page in English. An example of source string location could be
+  ``getting_started/step_by_step/scenes_and_nodes.rst`` for the
+  page :ref:`doc_scenes_and_nodes`.
+- The class reference's translation template is generated from the source XML
+  files in **alphabetical order**, which is also the same as the order of the
+  table of contents for the online version. You can therefore locate the source
+  string corresponding to the brief description of a given class to find the
+  first string to translate and all other descriptions from that class should be
+  in the subsequent strings on Weblate. For example, the descriptions for the
+  :ref:`class_Node2D` class would have the source string location
+  ``doc/classes/Node2D.xml``.
+
+A handy tool to locate specific pages/classes is to use Weblate's advanced
+search feature, and especially the "Location strings" query (which can also be
+used with the ``location:`` token, e.g. ``location:scenes_and_nodes.rst``):
+
+.. image:: img/l10n_05_search_location.png
+
+.. image:: img/l10n_06_browse_by_location.png
+
+.. note::
+
+    When a given source string is used in multiple source locations, they will
+    all be concatenated into one. For example, the above
+    ``location:scenes_and_nodes.rst`` query would land first on the
+    "Introduction" source string which is used in dozens of pages, including
+    some that come before ``scenes_and_nodes.rst`` in the template. Clicking the
+    "Next" button then brings us to the "Scene and nodes" title string displayed
+    above.
+    So it may happen that a given paragraph or section title is not at the
+    location you'd expect it when reading the online version of a page.
+
+Respecting the markup syntax
+----------------------------
+
+Each translation resource originates from a different source code format, and
+having some notions on the markup language used for each resource is important
+to avoid creating syntax errors in your translations.
+
+Editor interface (C++)
+^^^^^^^^^^^^^^^^^^^^^^
+
+The editor translations originate from C++ strings, and may use:
+
+- **C format specifiers** such as ``%s`` (a string) or ``%d`` (a number). These
+  specifiers are replaced by content at runtime, and should be preserved and
+  placed in your translation where necessary for it to be meaningful after
+  substitution. You may need to refer to the source string location to
+  understand what kind of content will be substituted if it's not clear from the
+  sentence. Example (``%s``  will be substituted with a file name or path)::
+
+    # PO file:
+    "There is no '%s' file."
+
+    # Weblate:
+    There is no '%s' file.
+
+- **C escape characters** such as ``\n`` (line break) or ``\t`` (tabulation). In
+  the Weblate editor, the ``\n`` characters are replaced by ``↵`` (return) and
+  ``\t`` by ``↹``. Tabs are not used much, but you should make sure to use line
+  breaks in the same way as the original English string (Weblate will issue a
+  warning if you don't). Line breaks might sometimes be used for vertical
+  spacing, or manual wrapping of long lines which would otherwise be too long
+  especially in the editor translation). Example::
+
+    # PO file:
+    "Scene '%s' is currently being edited.\n"
+    "Changes will only take effect when reloaded."
+
+    # Weblate:
+    Scene '%s' is currently being edited.↵
+    Changes will only take effect when reloaded.
+
+Online documentation (RST)
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The documentation translations originate from reStructuredText (RST) files,
+which also use their own markup syntax to style text, create internal and
+external links, etc. Here are some examples::
+
+    # "development" is styled bold.
+    # "Have a look here" is a link pointing to https://docs.godotengine.org/en/latest.
+    # You should translate "Have a look here", but not the URL, unless there is
+    # a matching URL for the same content in your language.
+    # Note: The `, <, >, and _ characters all have a meaning in the hyperlink
+    # syntax and should be preserved.
+
+    Looking for the documentation of the current **development** branch?
+    `Have a look here <https://docs.godotengine.org/en/latest>`_.
+
+    # "|supported|" is an inline reference to an image and should stay unchanged.
+    # "master" uses the markup for inline code, and will be styled as such.
+    # Note: Inline code in RST uses 2 backticks on each side, unlike Markdown.
+    # Single backticks are used for hyperlinks.
+
+    |supported| Backwards-compatible new features (backported from the ``master``
+    branch) as well as bug, security, and platform support fixes.
+
+    # The :ref: Sphinx "role" is used for internal references to other pages of
+    # the documentation.
+    # It can be used with only the reference name of a page (which should not be
+    # changed), in which case the title of that page will be displayed:
+
+    See :ref:`doc_ways_to_contribute`.
+
+    # Or it can be used with an optional custom title, which should thus be translated:
+
+    See :ref:`how to contribute <doc_ways_to_contribute>`.
+
+    # You may encounter other Sphinx roles, such as :kbd: used for shortcut keys.
+    # You can translate the content between backticks to match the usual key names,
+    # if it's different from the English one.
+
+    Save the scene. Click Scene -> Save, or press :kbd:`Ctrl + S` on Windows/Linux
+    or :kbd:`Cmd + S` on macOS.
+
+.. seealso::
+
+    See Sphinx's `reStructured Text primer <https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`__
+    for a quick overview of the markup language you may find in source strings.
+    You may encounter especially the inline markup (bold, italics, inline code)
+    and the internal and external hyperlink markup.
+
+Class reference (BBCode)
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The class reference is documented in the main Godot repository using XML files,
+and with BBCode-like markup for styling and internal references.
+
+Some of the tags used are from the original BBCode (e.g. ``[b]Bold[/b]`` and
+``[i]Italics[/i]``), while others are Godot-specific and used for advanced
+features such as inline code (e.g. ``[code]true[/code]``), linking to another
+class (e.g. ``[Node2D]``) or to a property in a given class (e.g.
+``[member Node2D.position]``), or for multiline code blocks. Example::
+
+    Returns a color according to the standardized [code]name[/code] with [code]alpha[/code] ranging from 0 to 1.
+    [codeblock]
+    red = ColorN("red", 1)
+    [/codeblock]
+    Supported color names are the same as the constants defined in [Color].
+
+In the above example, ``[code]name[/code]``, ``[code]alpha[/code]``, and
+``[Color]`` should *not* be translated, as they refer respectively to argument
+names and a class of the Godot API. Similarly, the contents of the
+``[codeblock]`` should not be translated, as ``ColorN`` is a function of the
+Godot API and ``"red"`` is one of the named colors it supports. At most, you can
+translate the name of the variable which holds the result (``red = ...``).
+
+Note also that in the XML, each line is a paragraph, so you should not add line
+breaks if they are not part of the original translation.
+
+.. seealso::
+
+    See our documentation for class reference writers for the :ref:`list of
+    BBCode-like tags <doc_updating_the_class_reference_bbcode>` which are used
+    throughout the class reference.
+
+Offline translation and testing
+-------------------------------
+
+While we advise using the Weblate interface to write translations, you also have
+the possibility to download the PO file locally to translate it with your
+preferred PO editing application, such as `Poedit <https://poedit.net/>`__ or
+`Lokalize <https://userbase.kde.org/Lokalize>`__.
+
+To download the PO file locally, browse to the translation overview for your
+language, and select the first item in the "Files" menu:
+
+.. image:: img/l10n_07_download_po_file.png
+
+Once you are done with a series of edits, use the "Upload translation" item in
+that same menu and select your file. Choose "Add as translation" for the file
+upload mode.
+
+.. note::
+
+    If a significant amount of time has passed between your download of the PO
+    file and the upload of the edited version, there is a risk to overwrite the
+    translations authored by other contributors in the meantime. This is why we
+    advise to use the online interface so that you always work on the latest
+    version.
+
+If you want to test changes locally (especially for the editor translation), you
+can use the downloaded PO file and :ref:`compile Godot from source <toc-devel-compiling>`.
+
+Rename the editor translation PO file to ``<lang>.po`` (e.g. ``eo.po`` for
+Esperanto) and place it in the ``editor/translations/`` folder
+(`GitHub <https://github.com/godotengine/godot/tree/master/editor/translations>`__).
+
+You can also test class reference changes the same way by renaming the PO file
+similarly and placing it in the ``doc/translations/`` folder
+(`GitHub <https://github.com/godotengine/godot/tree/master/doc/translations>`__).
+
+Localizing documentation images
+-------------------------------
+
+The online documentation includes many images, which can be screenshots of the
+Godot editor, custom-made graphs, of any other kind of visual content. Some of
+it includes text and might thus be relevant to localize in your language.
+
+This part is not handled via Weblate, but directly on the `godot-docs-l10n
+<https://github.com/godotengine/godot-docs-l10n>`_ Git repository where the
+documentation translations are synced from Weblate.
+
+.. note::
+
+   The workflow is not the most straightforward and requires some knowledge of
+   Git. We plan to work on a simplified Web tool which could be used to manage
+   image localization in a convenient way, abstracting away these steps.
+
+To translate an image, you should first locate it in the original English
+documentation. To do so, browse the relevant page in the docs, e.g.
+:ref:`doc_intro_to_the_editor_interface`. Click the "Edit on GitHub" link in the
+top right corner:
+
+.. image:: img/l10n_08_edit_on_github.png
+
+On GitHub, click on the image you want to translate. If relevant, click on
+"Download" to download it locally and edit it with an image edition tool.
+Note the full path to the image as it will be needed further down (here
+``getting_started/step_by_step/img/project_manager_first_open.png``).
+
+.. image:: img/l10n_09_path_to_image.png
+
+Create your localized version of the image, either by editing the English one,
+or by taking a screenshot of the editor with your language, if it's an editor
+screenshot. Some images may also have source files available in SVG format, so
+you can browse the ``img/`` folder which contains them to check for that.
+
+Name your localized image like the original one, but with the language code
+added before the extension, e.g. ``project_manager_first_open.png`` would become
+``project_manager_first_open.fr.png`` for the French localization.
+
+Finally, on godot-docs-l10n_, recreate the same folder structure as for the
+original image in the ``images`` subfolder
+(`GitHub <https://github.com/godotengine/godot-docs-l10n/tree/master/images>`_),
+and place your translated image there. In our example, the end result should be
+``images/getting_started/step_by_step/img/project_manager_first_open.fr.png``.
+
+Repeat this for other images and :ref:`make a Pull Request <doc_pr_workflow>`.

BIN
community/contributing/img/l10n_01_language_list.png


BIN
community/contributing/img/l10n_02_new_translation.png


BIN
community/contributing/img/l10n_03_translation_overview.png


BIN
community/contributing/img/l10n_04_translation_interface.png


BIN
community/contributing/img/l10n_05_search_location.png


BIN
community/contributing/img/l10n_06_browse_by_location.png


BIN
community/contributing/img/l10n_07_download_po_file.png


BIN
community/contributing/img/l10n_08_edit_on_github.png


BIN
community/contributing/img/l10n_09_path_to_image.png


+ 1 - 0
community/contributing/index.rst

@@ -14,3 +14,4 @@ Contributing
    documentation_guidelines
    docs_writing_guidelines
    updating_the_class_reference
+   editor_and_docs_localization

+ 6 - 5
community/contributing/updating_the_class_reference.rst

@@ -1,7 +1,7 @@
 .. _doc_updating_the_class_reference:
 
-Contribute to the Class Reference
-=================================
+Contributing to the class reference
+===================================
 
 .. highlight:: shell
 
@@ -166,7 +166,7 @@ How to edit class XML
 
 Edit the file for your chosen class in ``doc/classes/`` to update the class reference. The folder contains an XML file for each class. The XML lists the constants and methods you'll find in the class reference. Godot generates and updates the XML automatically.
 
-Edit it using your favorite text editor. If you use a code editor, make sure that it doesn't change the indent style: tabs for the XML, and 4 spaces inside BBcode-style blocks. More on that below.
+Edit it using your favorite text editor. If you use a code editor, make sure that it doesn't change the indent style: tabs for the XML, and 4 spaces inside BBCode-style blocks. More on that below.
 
 If you need to check that the modifications you've made are correct in the generated documentation, build Godot as described :ref:`here <toc-devel-compiling>`, run the editor and open the help for the page you modified.
 
@@ -227,11 +227,12 @@ Here's how a class looks like in XML:
 
 Use a code editor like Vim, Atom, Code, Notepad++ or anything similar to edit the file quickly. Use the search function to find classes fast.
 
+.. _doc_updating_the_class_reference_bbcode:
 
-Improve formatting with BBcode style tags
+Improve formatting with BBCode style tags
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Godot's class reference supports BBcode-like tags. They add nice formatting to the text. Here's the list of available tags:
+Godot's class reference supports BBCode-like tags. They add nice formatting to the text. Here's the list of available tags:
 
 +---------------------------+--------------------------------+-----------------------------------+---------------------------------------------------+
 | Tag                       | Effect                         | Usage                             | Result                                            |

+ 9 - 0
community/contributing/ways_to_contribute.rst

@@ -190,3 +190,12 @@ There are two separate resources referred to as "documentation" in Godot:
    to which you can contribute via pull requests on the
    `godot-docs <https://github.com/godotengine/godot-docs>`_ GitHub repository.
    See :ref:`doc_documentation_guidelines` for more details.
+
+Contributing translations
+-------------------------
+
+To make Godot accessible to everyone, including users who may prefer resources
+in their native language instead of English, our community helps translate both
+the Godot editor and its documentation in many languages.
+
+See :ref:`doc_editor_and_docs_localization` for more details.

+ 1 - 1
conf.py

@@ -14,7 +14,6 @@ needs_sphinx = "1.3"
 sys.path.append(os.path.abspath("_extensions"))
 extensions = [
     "sphinx_tabs.tabs",
-    "sphinx.ext.imgmath",
 ]
 
 # Warning when the Sphinx Tabs extension is used with unknown
@@ -76,6 +75,7 @@ supported_languages = {
     "ru": "Документация Godot Engine (%s) на русском языке",
     "uk": "Документація до Godot Engine (%s) українською мовою",
     "zh_CN": "Godot Engine (%s) 简体中文文档",
+    "zh_TW": "Godot Engine (%s) 正體中文 (台灣) 文件",
 }
 
 language = os.getenv("READTHEDOCS_LANGUAGE", "en")

+ 5 - 0
development/cpp/object_class.rst

@@ -3,6 +3,11 @@
 Object class
 ============
 
+.. seealso::
+
+    This page describes the C++ implementation of objects in Godot.
+    Looking for the Object class reference? :ref:`Have a look here. <class_Object>`
+
 General definition
 ------------------
 

+ 4 - 12
getting_started/scripting/c_sharp/c_sharp_basics.rst

@@ -293,15 +293,7 @@ Configuring VS 2019 for debugging
 Configuring Visual Studio Code for debugging
 --------------------------------------------
 
-To configure Visual Studio Code for debugging open up a project in Godot. Click on Project
-and open the project settings. Scroll down and click on Debugger Agent under the Mono
-category. Then turn on the setting "wait for debugger." Next, copy the port number
-and open up Visual Studio Code.
-
-You need to download the Mono Debug extension from Microsoft. Then open the Godot
-project folder. Go to the run tab and click on create a launch.json file. Select C#
-Mono from the dropdown menu. When the launch.json file is automatically opened,
-change the port number to the number you copied previously and save the file. On the
-run tab, switch the run setting from launch to attach. Whenever you want to debug,
-make sure Wait for Debugger is turned on in Godot, run the project, and run the
-debugger in Visual Studio Code.
+To configure debugging, open Visual Studio Code and download the Mono Debug extension from
+Microsoft and the Godot extension by Ignacio. Then open the Godot project folder in VS Code.
+Go to the Run tab and click on **create a launch.json file**. Select **C# Godot** from the dropdown
+menu. Now, when you start the debugger in VS Code your Godot project will run.

+ 29 - 2
getting_started/scripting/gdscript/gdscript_basics.rst

@@ -354,8 +354,35 @@ PoolRealArray store 32-bit single-precision "float" values.
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 A sequence of characters in `Unicode format <https://en.wikipedia.org/wiki/Unicode>`_.
-Strings can contain
-`standard C escape sequences <https://en.wikipedia.org/wiki/Escape_sequences_in_C>`_.
+Strings can contain the following escape sequences:
+
++---------------------+---------------------------------+
+| **Escape sequence** | **Expands to**                  |
++---------------------+---------------------------------+
+| ``\n``              | Newline (line feed)             |
++---------------------+---------------------------------+
+| ``\t``              | Horizontal tab character        |
++---------------------+---------------------------------+
+| ``\r``              | Carriage return                 |
++---------------------+---------------------------------+
+| ``\a``              | Alert (beep/bell)               |
++---------------------+---------------------------------+
+| ``\b``              | Backspace                       |
++---------------------+---------------------------------+
+| ``\f``              | Formfeed page break             |
++---------------------+---------------------------------+
+| ``\v``              | Vertical tab character          |
++---------------------+---------------------------------+
+| ``\"``              | Double quote                    |
++---------------------+---------------------------------+
+| ``\'``              | Single quote                    |
++---------------------+---------------------------------+
+| ``\\``              | Backslash                       |
++---------------------+---------------------------------+
+| ``\uXXXX``          | Unicode codepoint ``XXXX``      |
+|                     | (hexadecimal, case-insensitive) |
++---------------------+---------------------------------+
+
 GDScript also supports :ref:`doc_gdscript_printf`.
 
 Vector built-in types

+ 9 - 21
getting_started/scripting/gdscript/gdscript_exports.rst

@@ -125,7 +125,7 @@ Examples
     export(Resource) var resource
     # In the Inspector, you can then drag and drop a resource file
     # from the FileSystem dock into the variable slot.
-    
+
     # Opening the inspector dropdown may result in an
     # extremely long list of possible classes to create, however.
     # Therefore, if you specify an extension of Resource such as:
@@ -141,22 +141,16 @@ Exporting bit flags
 -------------------
 
 Integers used as bit flags can store multiple ``true``/``false`` (boolean)
-values in one property. By using the export hint ``int, FLAGS``, they
+values in one property. By using the export hint ``int, FLAGS, ...``, they
 can be set from the editor::
 
-    # Individually edit the bits of an integer.
-    export(int, FLAGS) var spell_elements = ELEMENT_WIND | ELEMENT_WATER
-
-Restricting the flags to a certain number of named flags is also
-possible. The syntax is similar to the enumeration syntax::
-
     # Set any of the given flags from the editor.
     export(int, FLAGS, "Fire", "Water", "Earth", "Wind") var spell_elements = 0
 
-In this example, ``Fire`` has value 1, ``Water`` has value 2, ``Earth``
-has value 4 and ``Wind`` corresponds to value 8. Usually, constants
-should be defined accordingly (e.g. ``const ELEMENT_WIND = 8`` and so
-on).
+You must provide a string description for each flag. In this example, ``Fire``
+has value 1, ``Water`` has value 2, ``Earth`` has value 4 and ``Wind``
+corresponds to value 8. Usually, constants should be defined accordingly (e.g.
+``const ELEMENT_WIND = 8`` and so on).
 
 Export hints are also provided for the physics and render layers defined in the project settings::
 
@@ -165,17 +159,13 @@ Export hints are also provided for the physics and render layers defined in the
     export(int, LAYERS_3D_PHYSICS) var layers_3d_physics
     export(int, LAYERS_3D_RENDER) var layers_3d_render
 
-Using bit flags requires some understanding of bitwise operations. If in
-doubt, boolean variables should be exported instead.
+Using bit flags requires some understanding of bitwise operations.
+If in doubt, use boolean variables instead.
 
 Exporting arrays
 ----------------
 
-Exporting arrays works, but with an important caveat: while regular
-arrays are created local to every class instance, exported arrays are *shared*
-between all instances. This means that editing them in one instance will
-cause them to change in all other instances. Exported arrays can have
-initializers, but they must be constant expressions.
+Exported arrays can have initializers, but they must be constant expressions.
 
 If the exported array specifies a type which inherits from Resource, the array
 values can be set in the inspector by dragging and dropping multiple files
@@ -183,7 +173,6 @@ from the FileSystem dock at once.
 
 ::
 
-    # Exported array, shared between all instances.
     # Default value must be a constant expression.
 
     export var a = [1, 2, 3]
@@ -210,7 +199,6 @@ from the FileSystem dock at once.
     export var vector3s = PoolVector3Array()
     export var strings = PoolStringArray()
 
-    # Regular array, created local for every instance.
     # Default value can include run-time values, but can't
     # be exported.
 

+ 1 - 1
getting_started/step_by_step/exporting.rst

@@ -170,7 +170,7 @@ changed:
             // Move towards the target and stop when close.
             if (Position.DistanceTo(_target) > 10)
             {
-                velocity = _target - Position
+                velocity = _target - Position;
             }
 
             // Remove keyboard controls.

+ 1 - 1
getting_started/step_by_step/scripting.rst

@@ -331,7 +331,7 @@ Also, remember that nodes are referenced by name, not by type.
 
 .. note::
 
-    The right-hand panel of the connect dialogue is for binding specific
+    The 'advanced' panel of the connect dialogue is for binding specific
     values to the connected function's parameters. You can add and remove
     values of different types.
 

+ 2 - 2
getting_started/step_by_step/ui_game_user_interface.rst

@@ -286,13 +286,13 @@ the size of the ``Background``.
 
 Let's change the ``Number``'s align properties to move it to the left
 and center of the ``Background``. Select the ``Number`` node, change its
-``Align`` property to left and the ``Valign`` property to centre. Then
+``Align`` property to left and the ``Valign`` property to center. Then
 resize its left edge a bit to add some padding between the left
 edge of the ``Background`` and the text.
 
 .. figure:: img/ui_gui_step_tutorial_counter_design_3.png
 
-   The Number node aligned to the left and centre
+   The Number node aligned to the left and center
 
 To overlap the Icon and the background, we need a few tweaks. First, our
 background is a bit too tall. It's because it's inside a margin

+ 10 - 0
getting_started/step_by_step/ui_main_menu.rst

@@ -120,6 +120,16 @@ center the illustration with a ``CenterContainer``.
 Prepare the Main Menu scene
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+.. note::
+
+    This tutorial is based on a window size of 1366×768. To change the project's
+    base window size, open **Project > Project Settings** at the top of the
+    editor then change **Display > Window > Size > Width** to ``1366`` and
+    **Display > Window > Size > Height** to ``768``.
+
+    If you forget to change the window size, anchors and containers may not
+    behave as expected.
+
 Let's create the main menu. We'll build it in a single scene. To create
 an empty scene, click on **Scene > New Scene**.
 

+ 5 - 3
getting_started/workflow/assets/importing_scenes.rst

@@ -366,12 +366,14 @@ Remove nodes (-noimp)
 Node names that have this suffix will be removed at import time, no
 matter what their type is. They will not appear in the imported scene.
 
-Create collisions (-col, -colonly, -convcolonly)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Create collisions (-col, -convcol, -colonly, -convcolonly)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Option "-col" will work only for Mesh nodes. If it is detected, a child
 static collision node will be added, using the same geometry as the mesh.
 
+Option "-convcol" will create a :ref:`class_convexpolygonshape` instead of a :ref:`class_concavepolygonshape`.
+
 However, it is often the case that the visual geometry is too complex or
 too un-smooth for collisions, which ends up not working well.
 
@@ -379,7 +381,7 @@ To solve this, the "-colonly" modifier exists, which will remove the mesh upon
 import and create a :ref:`class_staticbody` collision instead.
 This helps the visual mesh and actual collision to be separated.
 
-Option "-convcolonly" will create a :ref:`class_convexpolygonshape` instead of a :ref:`class_concavepolygonshape`.
+Option "-convcolonly" works in a similar way but will create a :ref:`class_convexpolygonshape` instead.
 
 Option "-colonly" can also be used with Blender's empty objects.
 On import, it will create a :ref:`class_staticbody` with

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

@@ -12,7 +12,7 @@ In this guide, you will learn when to use the Autoload feature, and techniques
 you can use to avoid it.
 
 The cutting audio issue
-=======================
+-----------------------
 
 Other engines can encourage the use of creating manager classes, singletons that
 organize a lot of functionality into a globally accessible object. Godot offers
@@ -61,7 +61,7 @@ needs within itself and all these problems go away:
 3. Each scene allocates exactly the amount of resources it needs.
 
 Managing shared functionality or data
-=====================================
+-------------------------------------
 
 Another reason to use an Autoload can be that you want to reuse the same method
 or data across many scenes.
@@ -78,7 +78,7 @@ When it comes to data, you can either:
    the ``owner`` property to access the scene's root node.
 
 When you should use an Autoload
-===============================
+-------------------------------
 
 Auto-loaded nodes can simplify your code in some cases:
 

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

@@ -61,7 +61,7 @@ In that screen, the path to 3 files needs to be set:
   - 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``. On Linux, it typically installs to a dir like ``/usr/bin/jarsigner``. The exact path may vary depending on the OpenJDK update you've installed and your machine's operating system.
+  - On Windows, OpenJDK installs to a directory like ``%PROGRAMFILES%\AdoptOpenJDK\jdk-8.0.252.09-hotspot\bin``. On Linux, it typically installs to a directory like ``/usr/bin/jarsigner``. The exact path may vary depending on the OpenJDK update you've installed and your machine's operating system.
 
 - The debug ``.keystore`` file
   - It can be found in the folder where you put the ``debug.keystore`` file you created above.

+ 17 - 4
getting_started/workflow/export/exporting_for_dedicated_servers.rst

@@ -35,16 +35,29 @@ offers two kinds of binaries with several differences.
 Exporting a PCK file
 --------------------
 
-Once you've downloaded a server binary, you should export a PCK file containing
-your project data. It's recommended to create a Linux export preset for this
-purpose. After creating the export preset, click **Export PCK/ZIP** at the
-bottom of the Export dialog then choose a destination path.
+There are two ways to export a project for a server:
+
+- Create a Linux/X11 export preset, define a custom Release export template
+  that points to the server binary then export the project as usual.
+- Export a PCK file only, preferably from a Linux/X11 export preset.
 
+Both methods should result in identical output. The text below describes the PCK
+file approach.
+
+Once you've downloaded a server binary, you should export a PCK file containing
+your project data. After creating the export preset, click **Export PCK/ZIP** at
+the bottom of the Export dialog then choose a destination path.
 The **Export With Debug** checkbox in the file dialog has no bearing on the
 final PCK file, so you can leave it as-is.
 
 See :ref:`doc_exporting_projects` for more information.
 
+.. note::
+
+    If you're exporting the project from a headless editor, call the headless
+    editor with the `--export-pack` option while in the project folder to export
+    only a PCK file.
+
 .. note::
 
     The PCK file will include resources not normally needed by the server, such

+ 3 - 0
getting_started/workflow/export/exporting_for_ios.rst

@@ -63,6 +63,9 @@ In the following example:
   * **exported_xcode_project_name** is the name of the exported iOS application (as above).
   * **godot_project_to_export** is the name of the Godot project.
 
+.. note:: **godot_project_to_export** must not be the same as **exported_xcode_project_name**
+          to prevent signing issues in Xcode.
+
 Steps to link a Godot project folder to Xcode
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

+ 6 - 0
tutorials/assetlib/uploading_to_assetlib.rst

@@ -63,6 +63,12 @@ library a better place for all users.
   if other people wish to contribute to your asset. See: the
   :ref:`doc_gdscript_styleguide` or the :ref:`doc_c_sharp_styleguide`.
 
+* If you have screenshots in your repo, place them in their own subfolder
+  and add a **.gdignore** file in the same folder (note: **gd**, not **git**).
+  This prevents Godot from importing your screenshots.
+  On Windows, open a command prompt in the project folder and run
+  ``type nul > .gdignore`` to create a file whose name starts with a period.
+
 * If your asset is a library for working with other files,
   consider including example files in the asset.
 

+ 3 - 2
tutorials/audio/recording_with_microphone.rst

@@ -30,11 +30,12 @@ An ``AudioStreamPlayer`` named ``AudioStreamRecord`` is used for recording.
     var effect
     var recording
 
+
     func _ready():
         # We get the index of the "Record" bus.
         var idx = AudioServer.get_bus_index("Record")
-	# And use it to retrieve its first effect, which has been defined
-	# as an "AudioEffectRecord" resource.
+        # And use it to retrieve its first effect, which has been defined
+        # as an "AudioEffectRecord" resource.
         effect = AudioServer.get_bus_effect(idx, 0)
 
 The audio recording is handled by the :ref:`class_AudioEffectRecord` resource

+ 3 - 0
tutorials/audio/sync_with_audio.rst

@@ -40,11 +40,13 @@ Add these two and it's possible to guess almost exactly when sound or music will
     var time_begin
     var time_delay
 
+
     func _ready()
         time_begin = OS.get_ticks_usec()
         time_delay = AudioServer.get_time_to_next_mix() + AudioServer.get_output_latency()
         $Player.play()
 
+
     func _process(delta):
         # Obtain from ticks.
         var time = (OS.get_ticks_usec() - time_begin) / 1000000.0
@@ -92,6 +94,7 @@ Here is the same code as before using this approach:
     func _ready()
         $Player.play()
 
+
     func _process(delta):
         var time = $Player.get_playback_position() + AudioServer.get_time_since_last_mix()
         # Compensate for output latency.

+ 2 - 2
tutorials/content/procedural_geometry/meshdatatool.rst

@@ -3,7 +3,7 @@
 Using the MeshDataTool
 ======================
 
-The MeshDataTool is not used to generate geometry. But it is helpful for dynamically altering geometry, for example
+The :ref:`MeshDataTool <class_meshdatatool>` is not used to generate geometry. But it is helpful for dynamically altering geometry, for example
 if you want to write a script to tessellate, simplify, or deform meshes.
 
 The MeshDataTool is not as fast as altering arrays directly using ArrayMesh. However, it provides more information
@@ -46,7 +46,7 @@ To access information from these arrays you use a function of the form ``get_***
     mdt.get_vertex_count() # Returns number of vertices in vertex array.
     mdt.get_vertex_faces(0) # Returns array of faces that contain vertex[0].
     mdt.get_face_normal(1) # Calculates and returns face normal.
-    mdt.get_edge_vertex(10, 1) # Returns the second vertex comprsing edge at index 10.
+    mdt.get_edge_vertex(10, 1) # Returns the second vertex comprising the edge at index 10.
 
 What you choose to do with these functions is up to you. A common use case is to iterate over all vertices
 and transform them in some way:

+ 26 - 18
tutorials/gui/gui_skinning.rst

@@ -43,6 +43,14 @@ hierarchy, towards the root. If nothing was found, the default theme is
 used. This system allows for flexible overriding of themes in complex
 user interfaces.
 
+.. attention::
+   
+   Don't use the custom theme option in the Project Settings, as there
+   are known bugs with theme propagation. Instead, apply your theme to the
+   root Control node's Theme property. It will propagate to instanced scenes
+   automatically. To get correct theming in the editor for instanced scenes,
+   you can apply the theme resource to the instanced scene's root node as well.
+
 Theme options
 -------------
 
@@ -70,23 +78,23 @@ An example usage:
 .. tabs::
  .. code-tab:: gdscript GDScript
 
-    var t = Theme.new()
-    t.set_color("font_color", "Label", Color(1.0, 1.0, 1.0))
+    var theme = Theme.new()
+    theme.set_color("font_color", "Label", Color.red)
 
-    var l = Label.new()
-    l.set_theme(t)
+    var label = Label.new()
+    label.theme = theme
 
  .. code-tab:: csharp
 
-    var t = new Theme();
-    t.SetColor("fontColor", "Label", new Color(1.0f, 1.0f, 1.0f));
+    var theme = new Theme();
+    theme.SetColor("fontColor", "Label", new Color(1.0f, 0.0f, 0.0f));
 
-    var l = new Label();
-    l.SetTheme(t);
+    var label = new Label();
+    label.Theme = theme;
 
 In the example above, a new theme is created. The "font_color" option
-is changed and then applied to a label. As a result, the label (and all
-children and grandchildren labels) will use that color.
+is changed and then applied to a label. Therefore, the label's text (and all
+children and grandchildren labels) will be red.
 
 It is possible to override those options without using the theme
 directly, and only for a specific control, by using the override API in
@@ -95,15 +103,15 @@ directly, and only for a specific control, by using the override API in
 .. tabs::
  .. code-tab:: gdscript GDScript
 
-    var l = Label.new()
-    l.add_color_override("font_color", Color(1.0, 1.0, 1.0))
+    var label = Label.new()
+    label.add_color_override("font_color", Color.red)
 
  .. code-tab:: csharp
 
-    var l = new Label();
-    l.AddColorOverride("fontColor", new Color(1.0f, 1.0f, 1.0f));
+    var label = new Label();
+    label.AddColorOverride("fontColor", new Color(1.0f, 0.0f, 0.0f));
 
-In the inline help of Godot (in the script tab) you can check which theme options
+In the inline help of Godot (in the Script tab), you can check which theme options
 are overridable, or check the :ref:`Control <class_Control>` class reference.
 
 Customizing a control
@@ -152,9 +160,9 @@ editor, where they can be edited:
 
 From ``Styles``, open the "Normal" drop-down menu next to where it probably
 says "null" and create a "New StyleBoxTexture", then
-edit it. A texture stylebox basically contains a texture and the size of
-the margins that will not stretch when the texture is stretched. This is
-called "3x3" stretching:
+edit it. A texture stylebox contains a texture and the size of the margins
+that will not stretch when the texture is stretched.
+This is called nine-patch or "3x3" stretching:
 
 .. image:: img/sb1.png
 

+ 2 - 0
tutorials/inputs/custom_mouse_cursor.rst

@@ -43,10 +43,12 @@ Create a Node and attach the following script.
 
     extends Node
 
+
     # Load the custom images for the mouse cursor.
     var arrow = load("res://arrow.png")
     var beam = load("res://beam.png")
 
+
     func _ready():
         # Changes only the arrow shape of the cursor.
         # This is similar to changing it in the project settings.

+ 53 - 29
tutorials/inputs/input_examples.rst

@@ -35,6 +35,7 @@ Examples:
         if event.is_action_pressed("jump"):
             jump()
 
+
     func _physics_process(delta):
         if Input.is_action_pressed("move_right"):
             # Move as long as the key/button is pressed.
@@ -78,14 +79,21 @@ attach the following script:
 
     extends Node
 
+
     func _input(event):
         print(event.as_text())
 
  .. code-tab:: csharp
 
-    public override void _Input(InputEvent inputEvent)
+    using Godot;
+    using System;
+
+    public class Node : Godot.Node
     {
-        GD.Print(inputEvent.AsText());
+        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
@@ -94,16 +102,17 @@ event scroll by in the output window. Here's an example of the output:
 ::
 
     A
-    InputEventMouseMotion : button_mask=0, position=(551, 338), relative=(-85, 47), speed=(0, 0)
-    InputEventMouseButton : button_index=BUTTON_LEFT, pressed=true, position=(551, 338), button_mask=1, doubleclick=false
-    InputEventMouseButton : button_index=BUTTON_LEFT, pressed=false, position=(551, 338), button_mask=0, doubleclick=false
+    InputEventMouseMotion : button_mask=0, position=(108, 108), relative=(26, 1), speed=(164.152496, 159.119843), pressure=(0), tilt=(0, 0)
+    InputEventMouseButton : button_index=BUTTON_LEFT, pressed=true, position=(108, 107), button_mask=1, doubleclick=false
+    InputEventMouseButton : button_index=BUTTON_LEFT, pressed=false, position=(108, 107), button_mask=0, doubleclick=false
     S
     F
-    InputEventMouseMotion : button_mask=0, position=(547, 338), relative=(-1, 0), speed=(0, 0)
-    InputEventMouseMotion : button_mask=0, position=(542, 338), relative=(-4, 0), speed=(0, 0)
+    Alt
+    InputEventMouseMotion : button_mask=0, position=(108, 107), relative=(0, -1), speed=(164.152496, 159.119843), pressure=(0), tilt=(0, 0)
 
 As you can see, the results are very different for the different types of
-input. Key events are even printed as their key symbols. For example, let's consider :ref:`InputEventMouseButton <class_InputEventMouseButton>`.
+input. Key events are even printed as their key symbols. For example, let's
+consider :ref:`InputEventMouseButton <class_InputEventMouseButton>`.
 It inherits from the following classes:
 
 - :ref:`InputEvent <class_InputEvent>` - the base class for all input events
@@ -302,17 +311,19 @@ node:
 
     extends Node
 
+
     var dragging = false
-    var click_radius = 32  # Size of the sprite
+    var click_radius = 32 # Size of the sprite.
+
 
     func _input(event):
         if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
             if (event.position - $Sprite.position).length() < click_radius:
                 # Start dragging if the click is on the sprite.
-                if !dragging and event.pressed:
+                if not dragging and event.pressed:
                     dragging = true
             # Stop dragging if the button is released.
-            if dragging and !event.pressed:
+            if dragging and not event.pressed:
                 dragging = false
 
         if event is InputEventMouseMotion and dragging:
@@ -321,32 +332,45 @@ node:
 
  .. code-tab:: csharp
 
-    public override void _Input(InputEvent inputEvent)
+    using Godot;
+    using System;
+
+    public class Node2D : Godot.Node2D
     {
-        var sprite = GetNodeOrNull<Sprite>("Sprite");
-        if (sprite == null)
-            return;// No suitable node was found.
+        private bool dragging = false;
+        private int clickRadius = 32; // Size of the sprite.
 
-        if (inputEvent is InputEventMouseButton mouseEvent && (ButtonList)mouseEvent.ButtonIndex == ButtonList.Left)
+        public override void _Input(InputEvent inputEvent)
         {
-            if ((mouseEvent.Position - sprite.Position).Length() < clickRadius)
+            Sprite sprite = GetNodeOrNull<Sprite>("Sprite");
+            if (sprite == null)
             {
-                // Start dragging if the click is on the sprite.
-                if (!dragging && mouseEvent.Pressed)
-                    dragging = !dragging;
+                return; // No suitable node was found.
             }
-            // Stop dragging if the button is released.
-            if (dragging && !mouseEvent.Pressed)
+
+            if (inputEvent is InputEventMouseButton mouseEvent && (ButtonList)mouseEvent.ButtonIndex == ButtonList.Left)
             {
-                dragging = false;
+                if ((mouseEvent.Position - sprite.Position).Length() < clickRadius)
+                {
+                    // Start dragging if the click is on the sprite.
+                    if (!dragging && mouseEvent.Pressed)
+                    {
+                        dragging = true;
+                    }
+                }
+                // Stop dragging if the button is released.
+                if (dragging && !mouseEvent.Pressed)
+                {
+                    dragging = false;
+                }
             }
-        }
-        else
-        {
-            if (inputEvent is InputEventMouseMotion motionEvent)
+            else
             {
-                // While dragging, move the sprite with the mouse.
-                sprite.Position = motionEvent.Position;
+                if (inputEvent is InputEventMouseMotion motionEvent && dragging)
+                {
+                    // While dragging, move the sprite with the mouse.
+                    sprite.Position = motionEvent.Position;
+                }
             }
         }
     }

+ 6 - 6
tutorials/inputs/inputevent.rst

@@ -44,7 +44,7 @@ You can set up your InputMap under **Project > Project Settings > Input Map** an
 
     func _process(delta):
         if Input.is_action_pressed("ui_right"):
-            # Move right
+            # Move right.
 
  .. code-tab:: csharp
 
@@ -52,7 +52,7 @@ You can set up your InputMap under **Project > Project Settings > Input Map** an
     {
         if (Input.IsActionPressed("ui_right"))
         {
-            // Move right
+            // Move right.
         }
     }
 
@@ -184,19 +184,19 @@ The Input singleton has a method for this:
  .. code-tab:: gdscript GDScript
 
     var ev = InputEventAction.new()
-    # set as move_left, pressed
+    # Set as move_left, pressed.
     ev.action = "move_left"
     ev.pressed = true
-    # feedback
+    # Feedback.
     Input.parse_input_event(ev)
 
  .. code-tab:: csharp
 
     var ev = new InputEventAction();
-    // set as move_left, pressed
+    // Set as move_left, pressed.
     ev.SetAction("move_left");
     ev.SetPressed(true);
-    // feedback
+    // Feedback.
     Input.ParseInputEvent(ev);
 
 InputMap

+ 4 - 4
tutorials/inputs/mouse_and_input_coordinates.rst

@@ -29,26 +29,26 @@ for example:
  .. code-tab:: gdscript GDScript
 
     func _input(event):
-       # Mouse in viewport coordinates
+       # Mouse in viewport coordinates.
        if event is InputEventMouseButton:
            print("Mouse Click/Unclick at: ", event.position)
        elif event is InputEventMouseMotion:
            print("Mouse Motion at: ", event.position)
 
-       # Print the size of the viewport
+       # Print the size of the viewport.
        print("Viewport Resolution is: ", get_viewport_rect().size)
 
  .. code-tab:: csharp
 
     public override void _Input(InputEvent @event)
     {
-        // Mouse in viewport coordinates
+        // Mouse in viewport coordinates.
         if (@event is InputEventMouseButton eventMouseButton)
             GD.Print("Mouse Click/Unclick at: ", eventMouseButton.Position);
         else if (@event is InputEventMouseMotion eventMouseMotion)
             GD.Print("Mouse Motion at: ", eventMouseMotion.Position);
 
-        // Print the size of the viewport
+        // Print the size of the viewport.
         GD.Print("Viewport Resolution is: ", GetViewportRect().Size);
     }
 

+ 25 - 18
tutorials/io/background_loading.rst

@@ -99,6 +99,7 @@ with the main scene of the game:
     var time_max = 100 # msec
     var current_scene
 
+
     func _ready():
         var root = get_tree().get_root()
         current_scene = root.get_child(root.get_child_count() -1)
@@ -111,16 +112,16 @@ progress bar or loading screen.
 
 ::
 
-    func goto_scene(path): # game requests to switch to this scene
+    func goto_scene(path): # Game requests to switch to this scene.
         loader = ResourceLoader.load_interactive(path)
-        if loader == null: # check for errors
+        if loader == null: # Check for errors.
             show_error()
             return
         set_process(true)
 
-        current_scene.queue_free() # get rid of the old scene
+        current_scene.queue_free() # Get rid of the old scene.
 
-        # start your "loading..." animation
+        # Start your "loading..." animation.
         get_node("animation").play("loading")
 
         wait_frames = 1
@@ -145,14 +146,15 @@ precise control over the timings.
             set_process(false)
             return
 
-        if wait_frames > 0: # wait for frames to let the "loading" animation show up
+        # Wait for frames to let the "loading" animation show up.
+        if wait_frames > 0:
             wait_frames -= 1
             return
 
         var t = OS.get_ticks_msec()
-        while OS.get_ticks_msec() < t + time_max: # use "time_max" to control for how long we block this thread
-
-            # poll your loader
+        # Use "time_max" to control for how long we block this thread.
+        while OS.get_ticks_msec() < t + time_max:
+            # Poll your loader.
             var err = loader.poll()
 
             if err == ERR_FILE_EOF: # Finished loading.
@@ -162,7 +164,7 @@ precise control over the timings.
                 break
             elif err == OK:
                 update_progress()
-            else: # error during loading
+            else: # Error during loading.
                 show_error()
                 loader = null
                 break
@@ -181,12 +183,14 @@ loader.
         # Update your progress bar?
         get_node("progress").set_progress(progress)
 
-        # ... or update a progress animation?
+        # ...or update a progress animation?
         var length = get_node("animation").get_current_animation_length()
 
-        # Call this on a paused animation. Use "true" as the second argument to force the animation to update.
+        # Call this on a paused animation. Use "true" as the second argument to
+        # force the animation to update.
         get_node("animation").seek(progress * length, true)
 
+
     func set_new_scene(scene_resource):
         current_scene = scene_resource.instance()
         get_node("/root").add_child(current_scene)
@@ -273,8 +277,10 @@ Example:
     queue = preload("res://resource_queue.gd").new()
     queue.start()
 
-    # Suppose your game starts with a 10 second cutscene, during which the user can't interact with the game.
-    # For that time, we know they won't use the pause menu, so we can queue it to load during the cutscene:
+    # Suppose your game starts with a 10 second cutscene, during which the user
+    # can't interact with the game.
+    # For that time, we know they won't use the pause menu, so we can queue it
+    # to load during the cutscene:
     queue.queue_resource("res://pause_menu.tres")
     start_cutscene()
 
@@ -282,17 +288,18 @@ Example:
     pause_menu = queue.get_resource("res://pause_menu.tres").instance()
     pause_menu.show()
 
-    # when you need a new scene:
-    queue.queue_resource("res://level_1.tscn", true) # Use "true" as the second argument to put it at the front
-                                                     # of the queue, pausing the load of any other resource.
+    # When you need a new scene:
+    queue.queue_resource("res://level_1.tscn", true)
+    # Use "true" as the second argument to put it at the front of the queue,
+    # pausing the load of any other resource.
 
-    # to check progress
+    # To check progress.
     if queue.is_ready("res://level_1.tscn"):
         show_new_level(queue.get_resource("res://level_1.tscn"))
     else:
         update_progress(queue.get_progress("res://level_1.tscn"))
 
-    # when the user walks away from the trigger zone in your Metroidvania game:
+    # When the user walks away from the trigger zone in your Metroidvania game:
     queue.cancel_resource("res://zone_2.tscn")
 
 **Note**: this code, in its current form, is not tested in real world

+ 11 - 10
tutorials/io/saving_games.rst

@@ -137,26 +137,26 @@ way to pull the data out of the file as well.
     # Note: This can be called from anywhere inside the tree. This function is
     # path independent.
     # Go through everything in the persist category and ask them to return a
-    # dict of relevant variables
+    # dict of relevant variables.
     func save_game():
         var save_game = File.new()
         save_game.open("user://savegame.save", File.WRITE)
         var save_nodes = get_tree().get_nodes_in_group("Persist")
         for node in save_nodes:
-            # Check the node is an instanced scene so it can be instanced again during load
+            # Check the node is an instanced scene so it can be instanced again during load.
             if node.filename.empty():
                 print("persistent node '%s' is not an instanced scene, skipped" % node.name)
                 continue
 
-            # Check the node has a save function
+            # Check the node has a save function.
             if !node.has_method("save"):
                 print("persistent node '%s' is missing a save() function, skipped" % node.name)
                 continue
 
-            # Call the node's save function
+            # Call the node's save function.
             var node_data = node.call("save")
 
-            # Store the save dictionary as a new line in the save file
+            # Store the save dictionary as a new line in the save file.
             save_game.store_line(to_json(node_data))
         save_game.close()
 
@@ -165,7 +165,7 @@ way to pull the data out of the file as well.
     // Note: This can be called from anywhere inside the tree. This function is
     // path independent.
     // Go through everything in the persist category and ask them to return a
-    // dict of relevant variables
+    // dict of relevant variables.
     public void SaveGame()
     {
         var saveGame = new File();
@@ -174,24 +174,24 @@ way to pull the data out of the file as well.
         var saveNodes = GetTree().GetNodesInGroup("Persist");
         foreach (Node saveNode in saveNodes)
         {
-            // Check the node is an instanced scene so it can be instanced again during load
+            // Check the node is an instanced scene so it can be instanced again during load.
             if (saveNode.Filename.Empty())
             {
                 GD.Print(String.Format("persistent node '{0}' is not an instanced scene, skipped", saveNode.Name));
                 continue;
             }
 
-            // Check the node has a save function
+            // Check the node has a save function.
             if (!saveNode.HasMethod("Save"))
             {
                 GD.Print(String.Format("persistent node '{0}' is missing a Save() function, skipped", saveNode.Name));
                 continue;
             }
 
-            // Call the node's save function
+            // Call the node's save function.
             var nodeData = saveNode.Call("Save");
 
-            // Store the save dictionary as a new line in the save file
+            // Store the save dictionary as a new line in the save file.
             saveGame.StoreLine(JSON.Print(nodeData));
         }
 
@@ -240,6 +240,7 @@ load function:
                 if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":
                     continue
                 new_object.set(i, node_data[i])
+
         save_game.close()
 
  .. code-tab:: csharp

BIN
tutorials/math/img/vector_cross1.png


+ 0 - 0
tutorials/math/img/tutovec16.png → tutorials/math/img/vector_cross2.png


BIN
tutorials/math/img/vector_dot1.png


BIN
tutorials/math/img/vector_dot2.png


+ 4 - 10
tutorials/math/vector_math.rst

@@ -257,15 +257,11 @@ direction, a scalar value has only magnitude.
 
 The formula for dot product takes two common forms:
 
-.. math::
-
-    A \cdot B = \left \| A \right \|\left \| B \right \|\cos \Theta
+.. image:: img/vector_dot1.png
 
 and
 
-.. math::
-
-    A \cdot B = A_{x}B_{x} + A_{y}B_{y}
+.. image:: img/vector_dot2.png
 
 However, in most cases it is easiest to use the built-in method. Note that
 the order of the two vectors does not matter:
@@ -332,11 +328,9 @@ However, the result of the cross product is a vector with a direction
 that is perpendicular to both. Its magnitude depends on their relative angle.
 If two vectors are parallel, the result of their cross product will be a null vector.
 
-.. math::
-
-    \left \|a \times b  \right \| = \left \| a \right \|\left \| b \right \|\ |\sin(a,b)|
+.. image:: img/vector_cross1.png
 
-.. image:: img/tutovec16.png
+.. image:: img/vector_cross2.png
 
 The cross product is calculated like this:
 

+ 70 - 69
tutorials/misc/binary_serialization_api.rst

@@ -10,13 +10,13 @@ Godot has a simple serialization API based on Variant. It's used for
 converting data types to an array of bytes efficiently. This API is used
 in the functions ``get_var`` and ``store_var`` of :ref:`class_File`
 as well as the packet APIs for :ref:`class_PacketPeer`. This format
-is not used for binary scenes and resources.
+is *not* used for binary scenes and resources.
 
 Packet specification
 --------------------
 
 The packet is designed to be always padded to 4 bytes. All values are
-little endian encoded. All packets have a 4 byte header representing an
+little-endian-encoded. All packets have a 4-byte header representing an
 integer, specifying the type of data:
 
 +--------+--------------------------+
@@ -79,11 +79,12 @@ integer, specifying the type of data:
 | 27     | max                      |
 +--------+--------------------------+
 
-Following this is the actual packet contents, which varies for each type
-of packet. Note that this assumes Godot is compiled with single precision
-floats. If instead doubles are used, the length of "Float" fields within
-data structures should be 8, and the offset should be (offset - 4) * 2 + 4.
-The "float" type itself is always double precision.
+Following this is the actual packet contents, which varies for each type of
+packet. Note that this assumes Godot is compiled with single-precision floats,
+which is the default. If Godot was compiled with double-precision floats, the
+length of "Float" fields within data structures should be 8, and the offset
+should be ``(offset - 4) * 2 + 4``. The "float" type itself always uses double
+precision.
 
 0: null
 ~~~~~~~
@@ -103,7 +104,7 @@ The "float" type itself is always double precision.
 +----------+-------+-----------+--------------------------+
 | Offset   | Len   | Type      | Description              |
 +==========+=======+===========+==========================+
-| 4        | 8     | Integer   | Signed, 64-bit Integer   |
+| 4        | 8     | Integer   | 64-bit signed integer    |
 +----------+-------+-----------+--------------------------+
 
 3: :ref:`float<class_float>`
@@ -121,9 +122,9 @@ The "float" type itself is always double precision.
 +----------+-------+-----------+----------------------------+
 | Offset   | Len   | Type      | Description                |
 +==========+=======+===========+============================+
-| 4        | 4     | Integer   | String Length (in Bytes)   |
+| 4        | 4     | Integer   | String length (in bytes)   |
 +----------+-------+-----------+----------------------------+
-| 8        | X     | Bytes     | UTF-8 Encoded String       |
+| 8        | X     | Bytes     | UTF-8 encoded string       |
 +----------+-------+-----------+----------------------------+
 
 This field is padded to 4 bytes.
@@ -134,9 +135,9 @@ This field is padded to 4 bytes.
 +----------+-------+---------+----------------+
 | Offset   | Len   | Type    | Description    |
 +==========+=======+=========+================+
-| 4        | 4     | Float   | X Coordinate   |
+| 4        | 4     | Float   | X coordinate   |
 +----------+-------+---------+----------------+
-| 8        | 4     | Float   | Y Coordinate   |
+| 8        | 4     | Float   | Y coordinate   |
 +----------+-------+---------+----------------+
 
 6: :ref:`Rect2<class_rect2>`
@@ -145,13 +146,13 @@ This field is padded to 4 bytes.
 +----------+-------+---------+----------------+
 | Offset   | Len   | Type    | Description    |
 +==========+=======+=========+================+
-| 4        | 4     | Float   | X Coordinate   |
+| 4        | 4     | Float   | X coordinate   |
 +----------+-------+---------+----------------+
-| 8        | 4     | Float   | Y Coordinate   |
+| 8        | 4     | Float   | Y coordinate   |
 +----------+-------+---------+----------------+
-| 12       | 4     | Float   | X Size         |
+| 12       | 4     | Float   | X size         |
 +----------+-------+---------+----------------+
-| 16       | 4     | Float   | Y Size         |
+| 16       | 4     | Float   | Y size         |
 +----------+-------+---------+----------------+
 
 7: :ref:`Vector3<class_vector3>`
@@ -160,11 +161,11 @@ This field is padded to 4 bytes.
 +----------+-------+---------+----------------+
 | Offset   | Len   | Type    | Description    |
 +==========+=======+=========+================+
-| 4        | 4     | Float   | X Coordinate   |
+| 4        | 4     | Float   | X coordinate   |
 +----------+-------+---------+----------------+
-| 8        | 4     | Float   | Y Coordinate   |
+| 8        | 4     | Float   | Y coordinate   |
 +----------+-------+---------+----------------+
-| 12       | 4     | Float   | Z Coordinate   |
+| 12       | 4     | Float   | Z coordinate   |
 +----------+-------+---------+----------------+
 
 8: :ref:`Transform2D<class_transform2d>`
@@ -222,17 +223,17 @@ This field is padded to 4 bytes.
 +----------+-------+---------+----------------+
 | Offset   | Len   | Type    | Description    |
 +==========+=======+=========+================+
-| 4        | 4     | Float   | X Coordinate   |
+| 4        | 4     | Float   | X coordinate   |
 +----------+-------+---------+----------------+
-| 8        | 4     | Float   | Y Coordinate   |
+| 8        | 4     | Float   | Y coordinate   |
 +----------+-------+---------+----------------+
-| 12       | 4     | Float   | Z Coordinate   |
+| 12       | 4     | Float   | Z coordinate   |
 +----------+-------+---------+----------------+
-| 16       | 4     | Float   | X Size         |
+| 16       | 4     | Float   | X size         |
 +----------+-------+---------+----------------+
-| 20       | 4     | Float   | Y Size         |
+| 20       | 4     | Float   | Y size         |
 +----------+-------+---------+----------------+
-| 24       | 4     | Float   | Z Size         |
+| 24       | 4     | Float   | Z size         |
 +----------+-------+---------+----------------+
 
 12: :ref:`Basis<class_basis>`
@@ -294,17 +295,17 @@ This field is padded to 4 bytes.
 14: :ref:`Color<class_color>`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-+----------+-------+---------+----------------+
-| Offset   | Len   | Type    | Description    |
-+==========+=======+=========+================+
-| 4        | 4     | Float   | Red (0..1)     |
-+----------+-------+---------+----------------+
-| 8        | 4     | Float   | Green (0..1)   |
-+----------+-------+---------+----------------+
-| 12       | 4     | Float   | Blue (0..1)    |
-+----------+-------+---------+----------------+
-| 16       | 4     | Float   | Alpha (0..1)   |
-+----------+-------+---------+----------------+
++----------+-------+---------+--------------------------------------------------------------+
+| Offset   | Len   | Type    | Description                                                  |
++==========+=======+=========+==============================================================+
+| 4        | 4     | Float   | Red (typically 0..1, can be above 1 for overbright colors)   |
++----------+-------+---------+--------------------------------------------------------------+
+| 8        | 4     | Float   | Green (typically 0..1, can be above 1 for overbright colors) |
++----------+-------+---------+--------------------------------------------------------------+
+| 12       | 4     | Float   | Blue (typically 0..1, can be above 1 for overbright colors)  |
++----------+-------+---------+--------------------------------------------------------------+
+| 16       | 4     | Float   | Alpha (0..1)                                                 |
++----------+-------+---------+--------------------------------------------------------------+
 
 15: :ref:`NodePath<class_nodepath>`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -312,7 +313,7 @@ This field is padded to 4 bytes.
 +----------+-------+-----------+-----------------------------------------------------------------------------------------+
 | Offset   | Len   | Type      | Description                                                                             |
 +==========+=======+===========+=========================================================================================+
-| 4        | 4     | Integer   | String Length, or New Format (val&0x80000000!=0 and NameCount=val&0x7FFFFFFF)           |
+| 4        | 4     | Integer   | String length, or new format (val&0x80000000!=0 and NameCount=val&0x7FFFFFFF)           |
 +----------+-------+-----------+-----------------------------------------------------------------------------------------+
 
 For old format:
@@ -321,7 +322,7 @@ For old format:
 +----------+-------+---------+------------------------+
 | Offset   | Len   | Type    | Description            |
 +==========+=======+=========+========================+
-| 8        | X     | Bytes   | UTF-8 Encoded String   |
+| 8        | X     | Bytes   | UTF-8 encoded string   |
 +----------+-------+---------+------------------------+
 
 Padded to 4 bytes.
@@ -332,7 +333,7 @@ For new format:
 +----------+-------+-----------+-------------------------------------+
 | Offset   | Len   | Type      | Description                         |
 +==========+=======+===========+=====================================+
-| 4        | 4     | Integer   | Sub-Name Count                      |
+| 4        | 4     | Integer   | Sub-name count                      |
 +----------+-------+-----------+-------------------------------------+
 | 8        | 4     | Integer   | Flags (absolute: val&1 != 0 )       |
 +----------+-------+-----------+-------------------------------------+
@@ -342,9 +343,9 @@ For each Name and Sub-Name
 +----------+-------+-----------+------------------------+
 | Offset   | Len   | Type      | Description            |
 +==========+=======+===========+========================+
-| X+0      | 4     | Integer   | String Length          |
+| X+0      | 4     | Integer   | String length          |
 +----------+-------+-----------+------------------------+
-| X+4      | X     | Bytes     | UTF-8 Encoded String   |
+| X+4      | X     | Bytes     | UTF-8 encoded string   |
 +----------+-------+-----------+------------------------+
 
 Every name string is padded to 4 bytes.
@@ -385,7 +386,7 @@ other, using this same format.
 +---------------+-------+-----------+------------------------+
 | Offset        | Len   | Type      | Description            |
 +===============+=======+===========+========================+
-| 4             | 4     | Integer   | Array Length (Bytes)   |
+| 4             | 4     | Integer   | Array length (Bytes)   |
 +---------------+-------+-----------+------------------------+
 | 8..8+length   | 1     | Byte      | Byte (0..255)          |
 +---------------+-------+-----------+------------------------+
@@ -398,9 +399,9 @@ The array data is padded to 4 bytes.
 +------------------+-------+-----------+---------------------------+
 | Offset           | Len   | Type      | Description               |
 +==================+=======+===========+===========================+
-| 4                | 4     | Integer   | Array Length (Integers)   |
+| 4                | 4     | Integer   | Array length (Integers)   |
 +------------------+-------+-----------+---------------------------+
-| 8..8+length\*4   | 4     | Integer   | 32 Bits Signed Integer    |
+| 8..8+length\*4   | 4     | Integer   | 32-bit signed integer     |
 +------------------+-------+-----------+---------------------------+
 
 22: :ref:`PoolRealArray<class_poolrealarray>`
@@ -409,9 +410,9 @@ The array data is padded to 4 bytes.
 +------------------+-------+-----------+---------------------------+
 | Offset           | Len   | Type      | Description               |
 +==================+=======+===========+===========================+
-| 4                | 4     |Integer    | Array Length (Floats)     |
+| 4                | 4     | Integer   | Array length (Floats)     |
 +------------------+-------+-----------+---------------------------+
-| 8..8+length\*4   | 4     |Integer    | 32 Bits IEEE 754 Float    |
+| 8..8+length\*4   | 4     | Integer   | 32-bits IEEE 754 float    |
 +------------------+-------+-----------+---------------------------+
 
 23: :ref:`PoolStringArray<class_poolstringarray>`
@@ -420,7 +421,7 @@ The array data is padded to 4 bytes.
 +----------+-------+-----------+--------------------------+
 | Offset   | Len   | Type      | Description              |
 +==========+=======+===========+==========================+
-| 4        | 4     | Integer   | Array Length (Strings)   |
+| 4        | 4     | Integer   | Array length (Strings)   |
 +----------+-------+-----------+--------------------------+
 
 For each String:
@@ -428,9 +429,9 @@ For each String:
 +----------+-------+-----------+------------------------+
 | Offset   | Len   | Type      | Description            |
 +==========+=======+===========+========================+
-| X+0      | 4     | Integer   | String Length          |
+| X+0      | 4     | Integer   | String length          |
 +----------+-------+-----------+------------------------+
-| X+4      | X     | Bytes     | UTF-8 Encoded String   |
+| X+4      | X     | Bytes     | UTF-8 encoded string   |
 +----------+-------+-----------+------------------------+
 
 Every string is padded to 4 bytes.
@@ -441,11 +442,11 @@ Every string is padded to 4 bytes.
 +-------------------+-------+-----------+----------------+
 | Offset            | Len   | Type      | Description    |
 +===================+=======+===========+================+
-| 4                 | 4     | Integer   | Array Length   |
+| 4                 | 4     | Integer   | Array length   |
 +-------------------+-------+-----------+----------------+
-| 8..8+length\*8    | 4     | Float     | X Coordinate   |
+| 8..8+length\*8    | 4     | Float     | X coordinate   |
 +-------------------+-------+-----------+----------------+
-| 8..12+length\*8   | 4     | Float     | Y Coordinate   |
+| 8..12+length\*8   | 4     | Float     | Y coordinate   |
 +-------------------+-------+-----------+----------------+
 
 25: :ref:`PoolVector3Array<class_poolvector3array>`
@@ -454,28 +455,28 @@ Every string is padded to 4 bytes.
 +--------------------+-------+-----------+----------------+
 | Offset             | Len   | Type      | Description    |
 +====================+=======+===========+================+
-| 4                  | 4     | Integer   | Array Length   |
+| 4                  | 4     | Integer   | Array length   |
 +--------------------+-------+-----------+----------------+
-| 8..8+length\*12    | 4     | Float     | X Coordinate   |
+| 8..8+length\*12    | 4     | Float     | X coordinate   |
 +--------------------+-------+-----------+----------------+
-| 8..12+length\*12   | 4     | Float     | Y Coordinate   |
+| 8..12+length\*12   | 4     | Float     | Y coordinate   |
 +--------------------+-------+-----------+----------------+
-| 8..16+length\*12   | 4     | Float     | Z Coordinate   |
+| 8..16+length\*12   | 4     | Float     | Z coordinate   |
 +--------------------+-------+-----------+----------------+
 
 26: :ref:`PoolColorArray<class_poolcolorarray>`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-+--------------------+-------+-----------+----------------+
-| Offset             | Len   | Type      | Description    |
-+====================+=======+===========+================+
-| 4                  | 4     | Integer   | Array Length   |
-+--------------------+-------+-----------+----------------+
-| 8..8+length\*16    | 4     | Float     | Red (0..1)     |
-+--------------------+-------+-----------+----------------+
-| 8..12+length\*16   | 4     | Float     | Green (0..1)   |
-+--------------------+-------+-----------+----------------+
-| 8..16+length\*16   | 4     | Float     | Blue (0..1)    |
-+--------------------+-------+-----------+----------------+
-| 8..20+length\*16   | 4     | Float     | Alpha (0..1)   |
-+--------------------+-------+-----------+----------------+
++--------------------+-------+-----------+--------------------------------------------------------------+
+| Offset             | Len   | Type      | Description                                                  |
++====================+=======+===========+==============================================================+
+| 4                  | 4     | Integer   | Array length                                                 |
++--------------------+-------+-----------+--------------------------------------------------------------+
+| 8..8+length\*16    | 4     | Float     | Red (typically 0..1, can be above 1 for overbright colors)   |
++--------------------+-------+-----------+--------------------------------------------------------------+
+| 8..12+length\*16   | 4     | Float     | Green (typically 0..1, can be above 1 for overbright colors) |
++--------------------+-------+-----------+--------------------------------------------------------------+
+| 8..16+length\*16   | 4     | Float     | Blue (typically 0..1, can be above 1 for overbright colors)  |
++--------------------+-------+-----------+--------------------------------------------------------------+
+| 8..20+length\*16   | 4     | Float     | Alpha (0..1)                                                 |
++--------------------+-------+-----------+--------------------------------------------------------------+

+ 8 - 8
tutorials/misc/running_code_in_the_editor.rst

@@ -10,7 +10,7 @@ What is ``tool``?
 
 You can use it for doing many things, but it is mostly useful in level design for visually presenting things that are hard to predict ourselves. Here are some use cases:
 
-- If you have a cannon that shoots cannonballs affected by physics (gravity), you can draw cannonball's trajectory in the editor, making level design a lot easier.
+- If you have a cannon that shoots cannonballs affected by physics (gravity), you can draw the cannonball's trajectory in the editor, making level design a lot easier.
 - If you have jumppads with varying jump heights, you can draw the maximum jump height a player would reach if it jumped on one, also making level design easier.
 - If your player doesn't use a sprite, but draws itself using code, you can make that drawing code execute in the editor to see your player.
 
@@ -27,11 +27,11 @@ You can use it for doing many things, but it is mostly useful in level design fo
 How to use it
 -------------
 
-To turn a script into a tool, add ``tool`` keyword at the top of your code.
+To turn a script into a tool, add the keyword ``tool`` at the top of your code.
 
 To check if you are currently in the editor, use: ``Engine.editor_hint``.
 
-For example, if you want to execute some code only in editor, use:
+For example, if you want to execute some code only in the editor, use:
 
 .. tabs::
  .. code-tab:: gdscript GDScript
@@ -39,7 +39,7 @@ For example, if you want to execute some code only in editor, use:
     if Engine.editor_hint:
         # Code to execute when in editor.
 
-On the other hand, if you want to execute code only in game, simply negate previous expression:
+On the other hand, if you want to execute code only in game, simply negate the same statement:
 
 .. tabs::
  .. code-tab:: gdscript GDScript
@@ -47,9 +47,9 @@ On the other hand, if you want to execute code only in game, simply negate previ
     if not Engine.editor_hint:
         # Code to execute when in game.
 
-Pieces of code that are not having any of the 2 conditions above will run both in editor and in game.
+Pieces of code do not have either of the 2 conditions above will run both in-editor and in-game.
 
-Here is how a ``_process()`` function might look like for you:
+Here is how a ``_process()`` function might look for you:
 
 .. tabs::
  .. code-tab:: gdscript GDScript
@@ -63,7 +63,7 @@ Here is how a ``_process()`` function might look like for you:
 
         # Code to execute both in editor and in game.
 
-.. note:: Modifications in editor are permanent. In our case, when we remove the script, the node will keep its rotation direction. Be careful so that you don't make unwanted modifications.
+.. note:: Modifications in editor are permanent. For example, in the following case, when we remove the script, the node will keep its rotation. Be careful to avoid making unwanted modifications.
 
 Try it out
 -----------
@@ -150,4 +150,4 @@ If you are using :ref:`EditorScript<class_EditorScript>`:
         parent.add_child(node)
         node.set_owner(get_scene())
 
-.. warning:: Using ``tool`` improperly can yield many errors. It is advised to first write the code how you want it, and only then add the ``tool`` keyword to the top. Also make sure you divide your code into part that runs in editor and part that runs in game. This way you can find your bug easier.
+.. warning:: Using ``tool`` improperly can yield many errors. It is advised to first write the code how you want it, and only then add the ``tool`` keyword to the top. Also, make sure to separate code that runs in-editor from code that runs in-game. This way, you can find bugs more easily.

+ 12 - 9
tutorials/optimization/using_multimesh.rst

@@ -55,6 +55,7 @@ efficient for millions of objects, but for a few thousands, GDScript should be f
 
     extends MultiMeshInstance
 
+
     func _ready():
         # Create the multimesh.
         multimesh = MultiMesh.new()
@@ -66,6 +67,7 @@ efficient for millions of objects, but for a few thousands, GDScript should be f
         multimesh.instance_count = 10000
         # Maybe not all of them should be visible at first.
         multimesh.visible_instance_count = 1000
+
         # Set the transform of the instances.
         for i in multimesh.visible_instance_count:
             multimesh.set_instance_transform(i, Transform(Basis(), Vector3(i * 20, 0, 0)))
@@ -74,24 +76,25 @@ efficient for millions of objects, but for a few thousands, GDScript should be f
     using Godot;
     using System;
 
-    public class MultiMeshInstance : Godot.MultiMeshInstance
+    public class YourClassName : MultiMeshInstance
     {
         public override void _Ready()
         {
             // Create the multimesh.
-            var multimesh = new MultiMesh();
+            Multimesh = new MultiMesh();
             // Set the format first.
-            multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3d;
-            multimesh.ColorFormat = MultiMesh.ColorFormatEnum.None;
-            multimesh.CustomDataFormat = MultiMesh.CustomDataFormatEnum.None;
+            Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3d;
+            Multimesh.ColorFormat = MultiMesh.ColorFormatEnum.None;
+            Multimesh.CustomDataFormat = MultiMesh.CustomDataFormatEnum.None;
             // Then resize (otherwise, changing the format is not allowed)
-            multimesh.InstanceCount = 1000;
+            Multimesh.InstanceCount = 1000;
             // Maybe not all of them should be visible at first.
-            multimesh.VisibleInstanceCount = 1000;
+            Multimesh.VisibleInstanceCount = 1000;
+
             // Set the transform of the instances.
-            for (int i = 0; i < multimesh.VisibleInstanceCount; i++)
+            for (int i = 0; i < Multimesh.VisibleInstanceCount; i++)
             {
-                multimesh.SetInstanceTransform(i, new Transform(Basis.Identity, new Vector3(i * 20, 0, 0)));
+                Multimesh.SetInstanceTransform(i, new Transform(Basis.Identity, new Vector3(i * 20, 0, 0)));
             }
         }
     }

+ 9 - 3
tutorials/optimization/using_servers.rst

@@ -91,9 +91,11 @@ This is a simple example of how to create a sprite from code and move it using t
 
     extends Node2D
 
-    # VisualServer expects references to be kept around
+
+    # VisualServer expects references to be kept around.
     var sprite
 
+
     func _ready():
         # Create a canvas item, child of this node.
         var ci_rid = VisualServer.canvas_item_create()
@@ -130,9 +132,11 @@ The 3D APIs are different from the 2D ones, so the instantiation API must be use
 
     extends Spatial
 
-    # VisualServer expects references to be kept around
+
+    # VisualServer expects references to be kept around.
     var mesh
 
+
     func _ready():
         # Create a visual instance (for 3D).
         var instance = VisualServer.instance_create()
@@ -157,14 +161,16 @@ and moves a :ref:`CanvasItem <class_CanvasItem>` when the body moves.
 .. tabs::
  .. code-tab:: gdscript GDScript
 
-    # Physics2DServer expects references to be kept around
+    # Physics2DServer expects references to be kept around.
     var body
     var shape
 
+
     func _body_moved(state, index):
         # Created your own canvas item, use it here.
         VisualServer.canvas_item_set_transform(canvas_item, state.transform)
 
+
     func _ready():
         # Create the body.
         body = Physics2DServer.body_create()

+ 1 - 1
tutorials/platform/android_in_app_purchases.rst

@@ -8,7 +8,7 @@ The new plugin uses the `Google Play Billing library <https://developer.android.
 instead of the now deprecated AIDL IAP implementation.
 
 If you learn better by looking at an example, you can find the demo project
-`here <https://github.com/godotengine/godot-demo-projects/tree/master/misc/android_iap>`__.
+`here <https://github.com/godotengine/godot-demo-projects/tree/master/mobile/android_iap>`__.
 
 
 Migrating from Godot 3.2.1 and lower (GodotPaymentsV3)

+ 33 - 1
tutorials/platform/services_for_ios.rst

@@ -176,8 +176,9 @@ Game Center
 Implemented in ``platform/iphone/game_center.mm``.
 
 The Game Center API is available through the "GameCenter" singleton. It
-has 8 methods:
+has 9 methods:
 
+-  ``Error authenticate();``
 -  ``bool is_authenticated();``
 -  ``Error post_score(Variant p_score);``
 -  ``Error award_achievement(Variant p_params);``
@@ -189,6 +190,37 @@ has 8 methods:
 
 plus the standard pending event interface.
 
+authenticate
+~~~~~~~~~~~~
+
+Authenticates a user in Game Center.
+
+Response event
+^^^^^^^^^^^^^^
+
+The response event will be a dictionary with the following fields:
+
+On error:
+
+::
+
+    {
+      "type": "authentication",
+      "result": "error",
+      "error_code": the value from NSError::code,
+      "error_description": the value from NSError::localizedDescription,
+    }
+
+On success:
+
+::
+
+    {
+      "type": "authentication",
+      "result": "ok",
+      "player_id": the value from GKLocalPlayer::playerID,
+    }
+
 post_score
 ~~~~~~~~~~
 

+ 6 - 0
tutorials/plugins/editor/import_plugins.rst

@@ -51,12 +51,15 @@ when needed:
     tool
     extends EditorPlugin
 
+
     var import_plugin
 
+
     func _enter_tree():
         import_plugin = preload("import_plugin.gd").new()
         add_import_plugin(import_plugin)
 
+
     func _exit_tree():
         remove_import_plugin(import_plugin)
         import_plugin = null
@@ -90,6 +93,7 @@ Let's begin to code our plugin, one method at time:
     tool
     extends EditorImportPlugin
 
+
     func get_importer_name():
         return "demos.sillymaterial"
 
@@ -178,8 +182,10 @@ good practice to use an enum so you can refer to them using names.
     tool
     extends EditorImportPlugin
 
+
     enum Presets { DEFAULT }
 
+
     ...
 
 Now that the enum is defined, let's keep looking at the methods of an import

+ 11 - 3
tutorials/plugins/editor/inspector_plugins.rst

@@ -20,16 +20,19 @@ getting a ``plugin.cfg`` file created, and start with our
 .. tabs::
   .. code-tab:: gdscript GDScript
     # MyEditorPlugin.gd
+    tool
+    extends EditorPlugin
 
-    tool extends EditorPlugin
 
-    var plugin: EditorInspectorPlugin
+    var plugin
+
 
     func _enter_tree():
         # EditorInspectorPlugin is a resource, so we use `new()` instead of `instance()`.
         plugin = preload("res://addons/MyPlugin/MyInspectorPlugin.gd").new()
         add_inspector_plugin(plugin)
 
+
     func _exit_tree():
         remove_inspector_plugin(plugin)
 
@@ -53,9 +56,9 @@ overriding or changing existing property editors.
  .. code-tab:: gdscript GDScript
 
     # MyInspectorPlugin.gd
-
     extends EditorInspectorPlugin
 
+
     func can_handle(object):
         # Here you can specify which object types (classes) should be handled by
         # this plugin. For example if the plugin is specific to your player
@@ -64,6 +67,7 @@ overriding or changing existing property editors.
         # In this example we'll support all objects, so:
         return true
 
+
     func parse_property(object, type, path, hint, hint_text, usage):
         # We will handle properties of type integer.
         if type == TYPE_INT:
@@ -91,9 +95,11 @@ the inspector.
     extends EditorProperty
     class_name MyIntEditor
 
+
     var updating = false
     var spin = EditorSpinSlider.new()
 
+
     func _init():
        # We'll add an EditorSpinSlider control, which is the same that the
        # inspector already uses for integer and float edition.
@@ -108,11 +114,13 @@ the inspector.
        spin.set_max(1000)
        spin.connect("value_changed", self, "_spin_changed")
 
+
     func _spin_changed(value):
         if (updating):
             return
         emit_changed(get_edited_property(), value)
 
+
     func update_property():
         var new_value = get_edited_object()[get_edited_property()]
         updating = true

+ 33 - 24
tutorials/plugins/editor/making_plugins.rst

@@ -91,12 +91,14 @@ like this:
     tool
     extends EditorPlugin
 
+
     func _enter_tree():
-        # Initialization of the plugin goes here
+        # Initialization of the plugin goes here.
         pass
 
+
     func _exit_tree():
-        # Clean-up of the plugin goes here
+        # Clean-up of the plugin goes here.
         pass
 
  .. code-tab:: csharp
@@ -110,12 +112,12 @@ like this:
     {
         public override void _EnterTree()
         {
-            // Initialization of the plugin goes here
+            // Initialization of the plugin goes here.
         }
 
         public override void _ExitTree()
         {
-            // Clean-up of the plugin goes here
+            // Clean-up of the plugin goes here.
         }
     }
     #endif
@@ -136,7 +138,7 @@ custom behavior.
   Nodes added via an EditorPlugin are "CustomType" nodes. While they work
   with any scripting language, they have fewer features than
   :ref:`the Script Class system <doc_scripting_continued_class_name>`. If you
-  are writing GDScript or NativeScript, we recommend using them instead.
+  are writing GDScript or NativeScript, we recommend using Script Classes instead.
 
 To create a new node type, you can use the function
 :ref:`add_custom_type() <class_EditorPlugin_method_add_custom_type>` from the
@@ -156,9 +158,11 @@ clicked. For that, we'll need a simple script that extends from
     tool
     extends Button
 
+
     func _enter_tree():
         connect("pressed", self, "clicked")
 
+
     func clicked():
         print("You clicked me!")
 
@@ -198,14 +202,16 @@ dialog. For that, change the ``custom_node.gd`` script to the following:
     tool
     extends EditorPlugin
 
+
     func _enter_tree():
-        # Initialization of the plugin goes here
-        # Add the new type with a name, a parent type, a script and an icon
+        # Initialization of the plugin goes here.
+        # Add the new type with a name, a parent type, a script and an icon.
         add_custom_type("MyButton", "Button", preload("my_button.gd"), preload("icon.png"))
 
+
     func _exit_tree():
-        # Clean-up of the plugin goes here
-        # Always remember to remove it from the engine when deactivated
+        # Clean-up of the plugin goes here.
+        # Always remember to remove it from the engine when deactivated.
         remove_custom_type("MyButton")
 
  .. code-tab:: csharp
@@ -219,8 +225,8 @@ dialog. For that, change the ``custom_node.gd`` script to the following:
     {
         public override void _EnterTree()
         {
-            // Initialization of the plugin goes here
-            // Add the new type with a name, a parent type, a script and an icon
+            // Initialization of the plugin goes here.
+            // Add the new type with a name, a parent type, a script and an icon.
             var script = GD.Load<Script>("MyButton.cs");
             var texture = GD.Load<Texture>("icon.png");
             AddCustomType("MyButton", "Button", script, texture);
@@ -228,8 +234,8 @@ dialog. For that, change the ``custom_node.gd`` script to the following:
 
         public override void _ExitTree()
         {
-            // Clean-up of the plugin goes here
-            // Always remember to remove it from the engine when deactivated
+            // Clean-up of the plugin goes here.
+            // Always remember to remove it from the engine when deactivated.
             RemoveCustomType("MyButton");
         }
     }
@@ -312,23 +318,26 @@ The script could look like this:
     tool
     extends EditorPlugin
 
-    # A class member to hold the dock during the plugin life cycle
+
+    # A class member to hold the dock during the plugin life cycle.
     var dock
 
+
     func _enter_tree():
-        # Initialization of the plugin goes here
-        # Load the dock scene and instance it
+        # Initialization of the plugin goes here.
+        # Load the dock scene and instance it.
         dock = preload("res://addons/my_custom_dock/my_dock.tscn").instance()
 
-        # Add the loaded scene to the docks
+        # Add the loaded scene to the docks.
         add_control_to_dock(DOCK_SLOT_LEFT_UL, dock)
-        # Note that LEFT_UL means the left of the editor, upper-left dock
+        # Note that LEFT_UL means the left of the editor, upper-left dock.
+
 
     func _exit_tree():
-        # Clean-up of the plugin goes here
-        # Remove the dock
+        # Clean-up of the plugin goes here.
+        # Remove the dock.
         remove_control_from_docks(dock)
-         # Erase the control from the memory
+        # Erase the control from the memory.
         dock.free()
 
  .. code-tab:: csharp
@@ -350,10 +359,10 @@ The script could look like this:
 
         public override void _ExitTree()
         {
-            // Clean-up of the plugin goes here
-            // Remove the dock
+            // Clean-up of the plugin goes here.
+            // Remove the dock.
             RemoveControlFromDocks(dock);
-            // Erase the control from the memory
+            // Erase the control from the memory.
             dock.Free();
         }
     }

+ 26 - 8
tutorials/plugins/editor/spatial_gizmos.rst

@@ -29,9 +29,9 @@ This would be a basic setup:
 ::
 
     # MyCustomGizmoPlugin.gd
-
     extends EditorSpatialGizmoPlugin
 
+
     func get_name():
         return "CustomNode"
 
@@ -39,17 +39,19 @@ This would be a basic setup:
 ::
 
     # MyCustomEditorPlugin.gd
-
     tool
     extends EditorPlugin
 
+
     const MyCustomGizmoPlugin = preload("res://addons/my-addon/MyCustomGizmoPlugin.gd")
 
     var gizmo_plugin = MyCustomGizmoPlugin.new()
 
+
     func _enter_tree():
         add_spatial_gizmo_plugin(gizmo_plugin)
 
+
     func _exit_tree():
         remove_spatial_gizmo_plugin(gizmo_plugin)
 
@@ -69,8 +71,11 @@ method so that it returns ``true`` when the spatial parameter is of our target t
 
     # ...
 
+
     func has_gizmo(spatial):
         return spatial is MyCustomSpatial
+
+
     # ...
 
 Then we can override methods like :ref:`redraw()<class_EditorSpatialGizmoPlugin_method_redraw>`
@@ -80,10 +85,12 @@ or all the handle related ones.
 
     # ...
 
+
     func _init():
         create_material("main", Color(1, 0, 0))
         create_handle_material("handles")
 
+
     func redraw(gizmo):
         gizmo.clear()
 
@@ -102,6 +109,7 @@ or all the handle related ones.
         gizmo.add_lines(lines, get_material("main", gizmo), false)
         gizmo.add_handles(handles, get_material("handles", gizmo))
 
+
     # ...
 
 Note that we created a material in the `_init` method, and retrieved it in the `redraw`
@@ -115,15 +123,19 @@ So the final plugin would look somewhat like this:
 
     extends EditorSpatialGizmoPlugin
 
+
     const MyCustomSpatial = preload("res://addons/my-addon/MyCustomSpatial.gd")
 
+
     func _init():
         create_material("main", Color(1,0,0))
         create_handle_material("handles")
 
+
     func has_gizmo(spatial):
         return spatial is MyCustomSpatial
 
+
     func redraw(gizmo):
         gizmo.clear()
 
@@ -142,8 +154,9 @@ So the final plugin would look somewhat like this:
         gizmo.add_lines(lines, get_material("main", gizmo), false)
         gizmo.add_handles(handles, get_material("handles", gizmo))
 
-    # you should implement the rest of handle-related callbacks
-    # (get_handle_name(), get_handle_value(), commit_handle()...)
+
+    # You should implement the rest of handle-related callbacks
+    # (get_handle_name(), get_handle_value(), commit_handle()...).
 
 Note that we just added some handles in the redraw method, but we still need to implement
 the rest of handle-related callbacks in :ref:`EditorSpatialGizmoPlugin <class_EditorSpatialGizmoPlugin>`
@@ -165,13 +178,16 @@ for the Spatial nodes we want to target.
     # MyCustomGizmoPlugin.gd
     extends EditorSpatialGizmoPlugin
 
+
     const MyCustomSpatial = preload("res://addons/my-addon/MyCustomSpatial.gd")
     const MyCustomGizmo = preload("res://addons/my-addon/MyCustomGizmo.gd")
 
+
     func _init():
         create_material("main", Color(1, 0, 0))
         create_handle_material("handles")
 
+
     func create_gizmo(spatial):
         if spatial is MyCustomSpatial:
             return MyCustomGizmo.new()
@@ -184,12 +200,13 @@ This way all the gizmo logic and drawing methods can be implemented in a new cla
 ::
 
     # MyCustomGizmo.gd
-
     extends EditorSpatialGizmo
 
-    # You can store data in the gizmo itself (more useful when working with handles)
+
+    # You can store data in the gizmo itself (more useful when working with handles).
     var gizmo_size = 3.0
 
+
     func redraw():
         clear()
 
@@ -211,8 +228,9 @@ This way all the gizmo logic and drawing methods can be implemented in a new cla
         var handles_material = get_plugin().get_material("handles", self)
         add_handles(handles, handles_material)
 
-    # you should implement the rest of handle-related callbacks
-    # (get_handle_name(), get_handle_value(), commit_handle()...)
+
+    # You should implement the rest of handle-related callbacks
+    # (get_handle_name(), get_handle_value(), commit_handle()...).
 
 Note that we just added some handles in the redraw method, but we still need to implement
 the rest of handle-related callbacks in :ref:`EditorSpatialGizmo<class_EditorSpatialGizmo>`

+ 13 - 2
tutorials/plugins/editor/visual_shader_plugins.rst

@@ -33,26 +33,31 @@ all you need to initialize your plugin.
 ::
 
     # PerlinNoise3D.gd
-
     tool
     extends VisualShaderNodeCustom
     class_name VisualShaderNodePerlinNoise3D
 
+
     func _get_name():
         return "PerlinNoise3D"
 
+
     func _get_category():
         return "MyShaderNodes"
 
+
     func _get_description():
         return "Classic Perlin-Noise-3D function (by Curly-Brace)"
 
+
     func _get_return_icon_type():
         return VisualShaderNode.PORT_TYPE_SCALAR
 
+
     func _get_input_port_count():
         return 4
 
+
     func _get_input_port_name(port):
         match port:
             0:
@@ -64,6 +69,7 @@ all you need to initialize your plugin.
             3:
                 return "time"
 
+
     func _get_input_port_type(port):
         match port:
             0:
@@ -75,15 +81,19 @@ all you need to initialize your plugin.
             3:
                 return VisualShaderNode.PORT_TYPE_SCALAR
 
+
     func _get_output_port_count():
         return 1
 
+
     func _get_output_port_name(port):
         return "result"
 
+
     func _get_output_port_type(port):
         return VisualShaderNode.PORT_TYPE_SCALAR
 
+
     func _get_global_code(mode):
         return """
             vec3 mod289_3(vec3 x) {
@@ -106,7 +116,7 @@ all you need to initialize your plugin.
                 return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
             }
 
-            // Classic Perlin noise
+            // Classic Perlin noise.
             float cnoise(vec3 P) {
                 vec3 Pi0 = floor(P); // Integer part for indexing.
                 vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1.
@@ -176,6 +186,7 @@ all you need to initialize your plugin.
             }
         """
 
+
     func _get_code(input_vars, output_vars, mode, type):
         return output_vars[0] + " = cnoise(vec3((%s.xy + %s.xy) * %s, %s)) * 0.5 + 0.5" % [input_vars[0], input_vars[1], input_vars[2], input_vars[3]]
 

+ 2 - 2
tutorials/shading/shading_reference/shading_language.rst

@@ -663,7 +663,7 @@ When vec_type (float), vec_int_type, vec_uint_type, vec_bool_type nomenclature i
 +------------------------------------------------------------------------+---------------------------------------------------------------+
 | vec_type **clamp** (vec_type x, vec_type min, vec_type max)            | Clamp to ``min..max``                                         |
 +------------------------------------------------------------------------+---------------------------------------------------------------+
-| vec_type **mix** (float a, float b, float c)                           | Linear interpolate                                            |
+| float **mix** (float a, float b, float c)                              | Linear interpolate                                            |
 +------------------------------------------------------------------------+---------------------------------------------------------------+
 | vec_type **mix** (vec_type a, vec_type b, float c)                     | Linear interpolate (scalar coefficient)                       |
 +------------------------------------------------------------------------+---------------------------------------------------------------+
@@ -697,7 +697,7 @@ When vec_type (float), vec_int_type, vec_uint_type, vec_bool_type nomenclature i
 +------------------------------------------------------------------------+---------------------------------------------------------------+
 | float **dot** (vec_type a, vec_type b)                                 | Dot product                                                   |
 +------------------------------------------------------------------------+---------------------------------------------------------------+
-| vec3 **cross** (vec3 a, vec3 b)                                        | Cross croduct                                                 |
+| vec3 **cross** (vec3 a, vec3 b)                                        | Cross product                                                 |
 +------------------------------------------------------------------------+---------------------------------------------------------------+
 | vec_type **normalize** (vec_type x)                                    | Normalize to unit length                                      |
 +------------------------------------------------------------------------+---------------------------------------------------------------+

+ 9 - 0
tutorials/threads/using_multiple_threads.rst

@@ -30,6 +30,7 @@ Creating a thread is very simple, just use the following code:
         # Third argument is optional userdata, it can be any variable.
         thread.start(self, "_thread_function", "Wafflecopter")
 
+
     # Run here and exit.
     # The argument is the userdata passed from start().
     # If no argument was passed, this one still needs to
@@ -76,6 +77,7 @@ Here is an example of using a Mutex:
     var mutex
     var thread
 
+
     # The thread will start here.
     func _ready():
         mutex = Mutex.new()
@@ -87,12 +89,14 @@ Here is an example of using a Mutex:
         counter += 1
         mutex.unlock()
 
+
     # Increment the value from the thread, too.
     func _thread_function(userdata):
         mutex.lock()
         counter += 1
         mutex.unlock()
 
+
     # Thread must be disposed (or "joined"), for portability.
     func _exit_tree():
         thread.wait_to_finish()
@@ -120,6 +124,7 @@ ready to be processed:
     var thread
     var exit_thread = false
 
+
     # The thread will start here.
     func _ready():
         mutex = Mutex.new()
@@ -129,6 +134,7 @@ ready to be processed:
         thread = Thread.new()
         thread.start(self, "_thread_function")
 
+
     func _thread_function(userdata):
         while true:
             semaphore.wait() # Wait until posted.
@@ -144,9 +150,11 @@ ready to be processed:
             counter += 1 # Increment counter, protect with Mutex.
             mutex.unlock()
 
+
     func increment_counter():
         semaphore.post() # Make the thread process.
 
+
     func get_counter():
         mutex.lock()
         # Copy counter, protect with Mutex.
@@ -154,6 +162,7 @@ ready to be processed:
         mutex.unlock()
         return counter_value
 
+
     # Thread must be disposed (or "joined"), for portability.
     func _exit_tree():
         # Set exit condition to true.

+ 4 - 4
tutorials/viewports/custom_postprocessing.rst

@@ -58,14 +58,14 @@ shader resource to it. You can access your rendered ``Viewport`` with the built-
 
     .. code-block:: glsl
 
-      // Inside the Shader
+      // Inside the Shader.
       uniform sampler2D ViewportTexture;
 
     And you can pass the texture into the shader from GDScript like so:
 
     ::
 
-      # In GDScript
+      # In GDScript.
       func _ready():
         $Sprite.material.set_shader_param("ViewportTexture", $Viewport.get_texture())
 
@@ -133,7 +133,7 @@ does not matter:
 
   shader_type canvas_item;
 
-  //Blurs the screen in the X-direction.
+  // Blurs the screen in the X-direction.
   void fragment() {
       vec3 col = texture(TEXTURE, SCREEN_UV).xyz * 0.16;
       col += texture(TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15;
@@ -151,7 +151,7 @@ does not matter:
 
   shader_type canvas_item;
 
-  //Blurs the screen in the Y-direction.
+  // Blurs the screen in the Y-direction.
   void fragment() {
       vec3 col = texture(TEXTURE, SCREEN_UV).xyz * 0.16;
       col += texture(TEXTURE, SCREEN_UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz * 0.15;

+ 24 - 8
tutorials/viewports/multiple_resolutions.rst

@@ -231,25 +231,22 @@ From scripts
 ^^^^^^^^^^^^
 
 To configure stretching at runtime from a script, use the
-``get_tree().set_screen_stretch()`` function (see
+``get_tree().set_screen_stretch()`` method (see
 :ref:`SceneTree.set_screen_stretch() <class_SceneTree_method_set_screen_stretch>`).
 
 Reducing aliasing on downsampling
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+---------------------------------
 
 If the game has a very high base resolution (e.g. 3840×2160), aliasing might
 appear when downsampling to something considerably lower like 1280×720.
 Aliasing can be made less visible by shrinking all images by a factor of 2
 upon loading. This can be done by calling the method below before
-the game data is loaded:
-
-::
+the game data is loaded::
 
     VisualServer.texture_set_shrink_all_x2_on_set_data(true)
 
-
 Handling aspect ratios
-^^^^^^^^^^^^^^^^^^^^^^
+----------------------
 
 Once scaling for different resolutions is accounted for, make sure that
 your *user interface* also scales for different aspect ratios. This can be
@@ -257,7 +254,7 @@ done using :ref:`anchors <doc_size_and_anchors>` and/or :ref:`containers
 <doc_gui_containers>`.
 
 Field of view scaling
-^^^^^^^^^^^^^^^^^^^^^
+---------------------
 
 The 3D Camera node's **Keep Aspect** property defaults to the **Keep Height**
 scaling mode (also called *Hor+*). This is usually the best value for desktop
@@ -268,3 +265,22 @@ However, if your 3D game is intended to be played in portrait mode, it may make
 more sense to use **Keep Width** instead (also called *Vert-*). This way,
 smartphones with an aspect ratio taller than 16:9 (e.g. 19:9) will use a
 *taller* field of view, which is more logical here.
+
+Scaling 2D and 3D elements differently using Viewports
+------------------------------------------------------
+
+Using multiple Viewport nodes, you can have different scales for various
+elements. For instance, you can use this to render the 3D world at a low
+resolution while keeping 2D elements at the native resolution. This can improve
+performance significantly while keeping the HUD and other 2D elements crisp.
+
+This is done by using the root Viewport node only for 2D elements, then creating
+a Viewport node to display the 3D world and displaying it using a
+ViewportContainer or TextureRect node. There will effectively be two viewports
+in the final project. One upside of using TextureRect over ViewportContainer is
+that it allows enable linear filtering. This makes scaled 3D viewports look
+better in many cases.
+
+See the
+`3D viewport scaling demo <https://github.com/godotengine/godot-demo-projects/tree/master/viewport/3d_scaling>`__
+for examples.

+ 2 - 2
tutorials/viewports/viewports.rst

@@ -97,7 +97,7 @@ different from the one specified in size, by calling:
 
 ::
 
-    viewport.set_size_override(true, Vector2(width, height)) # Custom size for 2D
+    viewport.set_size_override(true, Vector2(width, height)) # Custom size for 2D.
     viewport.set_size_override_stretch(true) # Enable stretch for custom size.
 
 The root :ref:`Viewport <class_Viewport>` uses this for the stretch options in the project
@@ -155,7 +155,7 @@ it using (for example):
 
 ::
 
-   # Wait until the frame has finished before getting the texture
+   # Wait until the frame has finished before getting the texture.
    yield(VisualServer, "frame_post_draw")
    # You can get the image after this.
 

+ 4 - 1
tutorials/vr/developing_for_oculus_quest.rst

@@ -50,11 +50,14 @@ Now add a script to the main node and add the following code:
 
     extends Spatial
 
+
     var perform_runtime_config = false
 
+
     onready var ovr_init_config = preload("res://addons/godot_ovrmobile/OvrInitConfig.gdns").new()
     onready var ovr_performance = preload("res://addons/godot_ovrmobile/OvrPerformance.gdns").new()
 
+
     func _ready():
         var interface = ARVRServer.find_interface("OVRMobile")
         if interface:
@@ -65,7 +68,7 @@ Now add a script to the main node and add the following code:
 
 
     func _process(_delta):
-        if !perform_runtime_config:
+        if not perform_runtime_config:
             ovr_performance.set_clock_levels(1, 1)
             ovr_performance.set_extra_latency_mode(1)
             perform_runtime_config = true

+ 3 - 2
tutorials/vr/vr_primer.rst

@@ -120,7 +120,8 @@ need a plugin for the specific SDK you want to use. There are several official p
 in the `GodotVR Repository <https://github.com/GodotVR>`_.
 
 * `Godot Oculus Mobile <https://github.com/GodotVR/godot_oculus_mobile>`_ provides support for
-  the Oculus Go and Oculus Quest. The Quest will require additional setup documented `here <doc_developing_for_oculus_quest>`_.
+  the Oculus Go and Oculus Quest. The Quest will require additional setup documented in
+  :ref:`doc_developing_for_oculus_quest`.
 * `Godot OpenVR <https://github.com/GodotVR/godot_openvr>`_ (not to be confused with OpenXR)
   supports the OpenVR SDK used by Steam.
 * `Godot Oculus <https://github.com/GodotVR/godot_oculus>`_ supports the Oculus SDK
@@ -137,7 +138,7 @@ In addition to the plugins, there are several official demos.
 
 * `Godot Oculus Demo <https://github.com/GodotVR/godot-oculus-demo>`_.
 * `Godot OpenVR FPS <https://github.com/GodotVR/godot_openvr_fps>`_ (the tutorial for this project
-  is `here <doc_vr_starter_tutorial_part_one>`_)
+  is :ref:`doc_vr_starter_tutorial_part_one`).
 * `Godot XR tools <https://github.com/GodotVR/godot-xr-tools>`_, which shows implementations for VR
   features such as movement and picking up objects.