Bladeren bron

Merge branch 'master' into 3.2

Rémi Verschelde 5 jaren geleden
bovenliggende
commit
31a288783c

+ 117 - 0
_extensions/godot_descriptions.py

@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+"""
+    godot_descriptions
+    ~~~~~~~~~~~~~~~~~~
+
+    Sphinx extension to automatically generate HTML meta description tags
+    for all pages. Also comes with some special support for Godot class docs.
+
+    :copyright: Copyright 2020 by The Godot Engine Community
+    :license: MIT.
+
+    based on the work of Takayuki Shimizukawa on OpenGraph support for Sphinx,
+    see: https://github.com/sphinx-contrib/ogp
+"""
+
+import re
+from docutils import nodes
+from sphinx import addnodes
+
+
+class DescriptionGenerator:
+    def __init__(self, document, pagename="", n_sections_max=3, max_length=220):
+        self.document = document
+        self.text_list = []
+        self.max_length = max_length
+        self.current_length = 0
+        self.n_sections = 0
+        self.n_sections_max = n_sections_max
+        self.pagename = pagename
+        self.is_class = pagename.startswith("classes/")
+        self.stop_word_reached = False
+
+    def dispatch_visit(self, node):
+        if (
+            self.stop_word_reached
+            or self.current_length > self.max_length
+            or self.n_sections > self.n_sections_max
+        ):
+            return
+
+        if isinstance(node, addnodes.compact_paragraph) and node.get("toctree"):
+            raise nodes.SkipChildren
+
+        add = True
+
+        if isinstance(node, nodes.paragraph):
+            text = node.astext()
+
+            if self.is_class:
+                # Skip OOP hierarchy info for description
+                if (
+                    text.startswith("Inherits:")
+                    or text.startswith("Inherited By:")
+                    or text.strip() == "Example:"
+                ):
+                    add = False
+
+                # If we're in a class doc and reached the first table,
+                # stop adding to the description
+                if text.strip() == "Properties":
+                    self.stop_word_reached = True
+                    add = False
+
+            if add:
+                self.text_list.append(text)
+                self.current_length = self.current_length + len(text)
+
+        if add and isinstance(node, nodes.section):
+            self.n_sections += 1
+
+    def dispatch_departure(self, node):
+        pass
+
+    def format_description(self, desc):
+        # Replace newlines with spaces
+        desc = re.sub("\r|\n", " ", desc)
+
+        # Replace multiple spaces with single spaces
+        desc = re.sub("\\s+", " ", desc)
+
+        return desc
+
+    def create_description(self, cutoff_suffix="..."):
+        text = " ".join(self.text_list)
+
+        text = self.format_description(text)
+
+        # Cut to self.max_length, add cutoff_suffix at end
+        if len(text) > self.max_length:
+            text = text[: self.max_length - len(cutoff_suffix)].strip() + cutoff_suffix
+
+        return text
+
+
+def generate_description(app, pagename, templatename, context, doctree):
+    if not doctree:
+        return
+
+    generator = DescriptionGenerator(doctree, pagename)
+    doctree.walkabout(generator)
+
+    description = (
+        '<meta name="description" content="' + generator.create_description() + '">\n'
+    )
+
+    context["metatags"] += description
+
+
+def setup(app):
+    # Hook into Sphinx for all pages to
+    # generate meta description tag and add to meta tag list
+    app.connect("html-page-context", generate_description)
+
+    return {
+        "parallel_read_safe": True,
+        "parallel_write_safe": True,
+    }

+ 7 - 1
_templates/layout.html

@@ -2,7 +2,9 @@
 {% block linktags -%}
   {% if godot_inject_language_links -%}
   {% for alternate_lang in godot_docs_supported_languages -%}
-  <link rel="alternate" hreflang="{{ alternate_lang }}" href="{{ godot_docs_basepath }}{{ alternate_lang }}/{{ godot_canonical_version }}/{{ pagename }}{{ godot_docs_suffix }}" />
+  {# Convert to ISO 639-1 format, e.g. zh_CN -> zh-cn -#}
+  {% set alternate_lang_href = alternate_lang.lower().replace("_", "-") -%}
+  <link rel="alternate" hreflang="{{ alternate_lang_href }}" href="{{ godot_docs_basepath }}{{ alternate_lang }}/{{ godot_canonical_version }}/{{ pagename }}{{ godot_docs_suffix }}" />
   {% endfor -%}
   <link rel="alternate" hreflang="x-default" href="{{ godot_docs_basepath }}{{ godot_default_lang }}/{{ godot_canonical_version }}/{{ pagename }}{{ godot_docs_suffix }}" />
   
@@ -10,3 +12,7 @@
   {% endif -%}
   {{ super() }}
 {% endblock -%}
+
+{% block htmltitle -%}
+<title>{{ godot_title_prefix }}{{ title|striptags|e }}{{ titlesuffix }}</title>
+{% endblock -%}

+ 5 - 13
conf.py

@@ -14,6 +14,7 @@ needs_sphinx = "1.3"
 sys.path.append(os.path.abspath("_extensions"))
 extensions = [
     "gdscript",
+    "godot_descriptions",
     "sphinx_search.extension",
     "sphinx_tabs.tabs",
     "sphinx.ext.imgmath",
@@ -66,17 +67,6 @@ supported_languages = {
     "zh_CN": "Godot Engine (%s) 简体中文文档",
 }
 
-# Some language codes used on Weblate/RTD and in the docs URL differ,
-# so we need to remap them.
-languages_remap = {
-    "pt_BR": "pt-br",
-    "zh_CN": "zh-cn",
-}
-languages_url = sorted(
-    [l for l in supported_languages.keys() if l not in languages_remap.keys()]
-    + list(languages_remap.values())
-)
-
 language = os.getenv("READTHEDOCS_LANGUAGE", "en")
 if not language in supported_languages.keys():
     print("Unknown language: " + language)
@@ -109,7 +99,6 @@ highlight_language = "gdscript"
 # on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org
 on_rtd = os.environ.get("READTHEDOCS", None) == "True"
 
-
 html_theme = "sphinx_rtd_theme"
 html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
 if on_rtd:
@@ -133,11 +122,14 @@ html_context = {
     "github_version": "master",  # Version
     "conf_py_path": "/",  # Path in the checkout to the docs root
     "godot_inject_language_links": True,
-    "godot_docs_supported_languages": languages_url,
+    "godot_docs_supported_languages": list(supported_languages.keys()),
     "godot_docs_basepath": "https://docs.godotengine.org/",
     "godot_docs_suffix": ".html",
     "godot_default_lang": "en",
     "godot_canonical_version": "stable",
+    # Distinguish local development website from production website.
+    # This prevents people from looking for changes on the production website after making local changes :)
+    "godot_title_prefix": "" if on_rtd else "(DEV) ",
 }
 
 html_logo = "img/docs_logo.png"

+ 20 - 11
getting_started/scripting/cross_language_scripting.rst

@@ -72,7 +72,7 @@ Instantiating C# nodes from GDScript
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Using C# from GDScript doesn't need much work. Once loaded
-(see :ref:`doc_gdscript_classes_as_resources`) the script can be instantiated
+(see :ref:`doc_gdscript_classes_as_resources`), the script can be instantiated
 with :ref:`new() <class_CSharpScript_method_new>`.
 
 ::
@@ -83,15 +83,15 @@ with :ref:`new() <class_CSharpScript_method_new>`.
 
 .. warning::
 
-    When creating .cs scripts you should always keep in mind that the class
-    Godot will use is the one named like the .cs file itself. If that class
+    When creating ``.cs`` scripts, you should always keep in mind that the class
+    Godot will use is the one named like the ``.cs`` file itself. If that class
     does not exist in the file, you'll see the following error:
     ``Invalid call. Nonexistent function `new` in base``.
 
     For example, MyCoolNode.cs should contain a class named MyCoolNode.
 
-    You also need to check your .cs file is referenced in the project's .csproj
-    file. Otherwise, the same error will occur.
+    You also need to check your ``.cs`` file is referenced in the project's
+    ``.csproj`` file. Otherwise, the same error will occur.
 
 Instantiating GDScript nodes from C#
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -104,7 +104,7 @@ be instantiated with :ref:`GDScript.New() <class_GDScript_method_new>`.
     GDScript MyGDScript = (GDScript) GD.Load("res://path_to_gd_file.gd");
     Object myGDScriptNode = (Godot.Object) MyGDScript.New(); // This is a Godot.Object
 
-Here we are using an :ref:`class_Object` but you can use type conversion like
+Here we are using an :ref:`class_Object`, but you can use type conversion like
 explained in :ref:`doc_c_sharp_features_type_conversion_and_casting`.
 
 Accessing fields
@@ -126,8 +126,8 @@ anything to worry about.
     # my_csharp_node.str2 = "BARBAR" # This line will hang and crash
 
 Note that it doesn't matter if the field is defined as a property or an
-attribute, but trying to set a value on a property that does not define a
-setter will result in a crash.
+attribute. However, trying to set a value on a property that does not define
+a setter will result in a crash.
 
 Accessing GDScript fields from C#
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -158,7 +158,7 @@ Calling C# methods from GDScript
 Again, calling C# methods from GDScript should be straightforward. The
 marshalling process will do its best to cast your the arguments to match
 function signatures.
-If that's impossible you'll see the following error: ``Invalid call. Nonexistent function `FunctionName```.
+If that's impossible, you'll see the following error: ``Invalid call. Nonexistent function `FunctionName```.
 
 ::
 
@@ -174,7 +174,7 @@ Calling GDScript methods from C#
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 To call GDScript methods from C# you'll need to use
-:ref:`Object.Call() <class_Object_method_call>`. The first arguments is the
+:ref:`Object.Call() <class_Object_method_call>`. The first argument is the
 name of the method you want to call. The following arguments will be passed
 to said method.
 
@@ -197,5 +197,14 @@ to said method.
 
     As you can see, if the first argument of the called method is an array,
     you'll need to cast it as ``object``.
-    Otherwise each element of your array will be treated as a single argument
+    Otherwise, each element of your array will be treated as a single argument
     and the function signature won't match.
+
+Inheritance
+-----------
+
+A GDScript file may not inherit from a C# script. Likewise, a C# script may not
+inherit from a GDScript file. Due to how complex this would be to implement,
+this limitation is unlikely to be lifted in the future. See
+`this GitHub issue <https://github.com/godotengine/godot/issues/38352>`__
+for more information.

+ 55 - 1
getting_started/scripting/gdscript/gdscript_basics.rst

@@ -985,7 +985,6 @@ will then appear with its new icon in the editor::
    # Item.gd
 
    extends Node
-
    class_name Item, "res://interface/icons/item.png"
 
 .. image:: img/class_name_editor_register_example.png
@@ -998,11 +997,14 @@ Here's a class file example:
 
     class_name Character
 
+
     var health = 5
 
+
     func print_health():
         print(health)
 
+
     func print_this_script_three_times():
         print(get_script())
         print(ResourceLoader.load("res://character.gd"))
@@ -1091,9 +1093,11 @@ This is better explained through examples. Consider this scenario::
     var entity = null
     var message = null
 
+
     func _init(e=null):
         entity = e
 
+
     func enter(m):
         message = m
 
@@ -1101,6 +1105,7 @@ This is better explained through examples. Consider this scenario::
     # Idle.gd (inheriting class)
     extends "State.gd"
 
+
     func _init(e=null, m=null).(e):
         # Do something with 'e'.
         message = m
@@ -1136,9 +1141,12 @@ function.
     # An inner class in this class file.
     class SomeInnerClass:
         var a = 5
+
+
         func print_value_of_a():
             print(a)
 
+
     # This is the constructor of the class file's main class.
     func _init():
         var c = SomeInnerClass.new()
@@ -1160,6 +1168,7 @@ class resource is done by calling the ``new`` function on the class object::
     # Preload the class only once at compile time.
     const MyClass = preload("myclass.gd")
 
+
     func _init():
         var a = MyClass.new()
         a.some_function()
@@ -1192,9 +1201,11 @@ with the new value. Vice versa, when ``variable`` is accessed, the *getter* func
 
     var my_var setget my_var_set, my_var_get
 
+
     func my_var_set(new_value):
         my_var = new_value
 
+
     func my_var_get():
         return my_var # Getter must return a value.
 
@@ -1236,6 +1247,7 @@ placed at the top of the file::
     tool
     extends Button
 
+
     func _ready():
         print("Hello")
 
@@ -1274,6 +1286,7 @@ to. To create custom signals for a class, use the ``signal`` keyword.
 
    extends Node
 
+
    # A signal named health_depleted.
    signal health_depleted
 
@@ -1299,6 +1312,7 @@ signal, the game node's ``_on_Character_health_depleted`` is called::
         var character_node = get_node('Character')
         character_node.connect("health_depleted", self, "_on_Character_health_depleted")
 
+
     func _on_Character_health_depleted():
         get_tree().reload_current_scene()
 
@@ -1318,6 +1332,7 @@ the :ref:`Object.connect() <class_Object_method_connect>` method::
     ...
     signal health_changed
 
+
     func take_damage(amount):
         var old_health = health
         health -= amount
@@ -1431,6 +1446,7 @@ an example::
         yield()
         print("world")
 
+
     func _ready():
         var y = my_func()
         # Function state saved in 'y'.
@@ -1452,6 +1468,7 @@ for example::
         print(yield())
         return "cheers!"
 
+
     func _ready():
         var y = my_func()
         # Function state saved in 'y'.
@@ -1471,6 +1488,7 @@ Remember to save the new function state, when using multiple ``yield``\s::
             print("Turn %d" % i)
             yield();
 
+
     func _ready():
         var co = co_func();
         while co is GDScriptFunction && co.is_valid():
@@ -1500,12 +1518,47 @@ into an invalid state, for example::
         yield(button_func(), "completed")
         print("All buttons were pressed, hurray!")
 
+
     func button_func():
         yield($Button0, "pressed")
         yield($Button1, "pressed")
 
 ``my_func`` will only continue execution once both buttons have been pressed.
 
+You can also get the signal's argument once it's emitted by an object:
+
+::
+
+    # Wait for when any node is added to the scene tree.
+    var node = yield(get_tree(), "node_added")
+
+If you're unsure whether a function may yield or not, or whether it may yield
+multiple times, you can yield to the ``completed`` signal conditionally:
+
+::
+
+    func generate():
+        var result = rand_range(-1.0, 1.0)
+
+        if result < 0.0:
+            yield(get_tree(), "idle_frame")
+
+        return result
+
+
+    func make():
+        var result = generate()
+
+        if result is GDScriptFunctionState: # Still working.
+            result = yield(result, "completed")
+
+        return result
+
+This ensures that the function returns whatever it was supposed to return
+irregardless of whether coroutines were used internally. Note that using
+``while`` would be redundant here as the ``completed`` signal is only emitted
+when the function didn't yield anymore.
+
 Onready keyword
 ~~~~~~~~~~~~~~~
 
@@ -1518,6 +1571,7 @@ be obtained when a call to ``Node._ready()`` is made.
 
     var my_label
 
+
     func _ready():
         my_label = get_node("MyLabel")
 

+ 24 - 4
getting_started/scripting/gdscript/gdscript_exports.rst

@@ -111,10 +111,20 @@ Examples
     export(Color, RGB) var col
     # Color given as red-green-blue-alpha value.
     export(Color, RGBA) var col
-
-    # Another node in the scene can be exported, too.
-
-    export(NodePath) var node
+    
+    # Nodes
+    
+    # Another node in the scene can be exported as a NodePath.
+    export(NodePath) var node_path
+    # Do take note that the node itself isn't being exported -
+    # there is one more step to call the true node:
+    var node = get_node(node_path)
+    
+    # Resources
+    
+    export(Resource) var resource
+    # In the Inspector, you can then drag and drop a resource file
+    # from the FileSystem dock into the variable slot.
 
 It must be noted that even if the script is not being run while in the
 editor, the exported properties are still editable. This can be used
@@ -153,6 +163,10 @@ 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.
 
+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 
+from the FileSystem dock at once.
+
 ::
 
     # Exported array, shared between all instances.
@@ -171,6 +185,12 @@ initializers, but they must be constant expressions.
     export(Array) var b
     export(Array, PackedScene) var scenes
 
+    # Arrays with specified types which inherit from resource can be set by
+    # drag-and-dropping multiple files from the FileSystem dock.
+
+    export(Array, Texture) var textures
+    export(Array, PackedScene) var scenes
+
     # Typed arrays also work, only initialized empty:
 
     export var vector3s = PoolVector3Array()

+ 1 - 1
getting_started/step_by_step/signals.rst

@@ -63,7 +63,7 @@ node.
 .. warning:: The target node *must* have a script attached or you'll receive
              an error message.
 
-On the right side, you can bind an arbitrary number of arguments of (possibly) different
+If you toggle the Advanced menu, you'll see on the right side that you can bind an arbitrary number of arguments of (possibly) different
 types. This can be useful when you have more than one signal connected to the same method,
 as each signal propagation will result in different values for those extra call arguments.
 

+ 2 - 2
getting_started/step_by_step/ui_game_user_interface.rst

@@ -408,7 +408,7 @@ Inherit the Bar Scene to build the LifeBar
 Go to ``Scene -> New Inherited Scene`` to create a new type of ``Bar``.
 Select the Bar scene and open it. You should see a new [unsaved] tab,
 that's like your ``Bar``, but with all nodes except the root in grey.
-Press :kbd:`Meta + S` to save the new inherited scene and name it
+Press :kbd:`Ctrl + S` (:kbd:`Cmd + S` on macOS) to save the new inherited scene and name it
 ``LifeBar``.
 
 .. figure:: img/ui_gui_step_tutorial_inherited_scene_parent.png
@@ -474,7 +474,7 @@ all the resources this node uses and create unique copies for us.
 .. tip::
 
     When you duplicate a node from the Scene tree, with
-    :kbd:`Meta + D`, it shares its resources with the original node. You
+    :kbd:`Ctrl + D` (:kbd:`Cmd + D` on macOS), it shares its resources with the original node. You
     need to use ``Make Sub-Resources Unique`` before you can tweak the
     resources without affecting the source node.
 

+ 4 - 4
getting_started/step_by_step/ui_main_menu.rst

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

+ 12 - 0
getting_started/workflow/assets/importing_images.rst

@@ -36,6 +36,7 @@ Supported image formats
 Godot can import the following image formats:
 
 - BMP (``.bmp``)
+  - No support for 16-bit per pixel images. Only 1-bit, 4-bit, 8-bit, 24-bit, and 32-bit per pixel images are supported.
 - DirectDraw Surface (``.dds``)
   - If mipmaps are present in the texture, they will be loaded directly.
   This can be used to achieve effects using custom mipmaps.
@@ -127,6 +128,17 @@ reimported automatically.
 
 Note that RGTC compression affects the resulting normal map image. You will have to adjust custom shaders that use the normal map to take this into account.
 
+.. note::
+
+  Godot requires the normal map to use the X+, Y- and Z+ coordinates. In other
+  words, if you've imported a material made to be used with another engine, you
+  may have to convert the normal map so its Y axis is flipped. Otherwise, the
+  normal map direction may appear to be inverted on the Y axis.
+
+  More information about normal maps (including a coordinate order table for
+  popular engines) can be found
+  `here <http://wiki.polycount.com/wiki/Normal_Map_Technical_Details>`__. 
+
 Flags
 -----
 

+ 1 - 1
tutorials/3d/fps_tutorial/part_five.rst

@@ -475,7 +475,7 @@ With that done, all we need to do is add some code to ``process_input``:
     # ----------------------------------
     # Grabbing and throwing objects
 
-    if Input.is_action_just_pressed("fire") and current_weapon_name == "UNARMED":
+    if Input.is_action_just_pressed("fire_grenade") and current_weapon_name == "UNARMED":
         if grabbed_object == null:
             var state = get_world().direct_space_state
 

+ 4 - 0
tutorials/3d/fps_tutorial/part_two.rst

@@ -291,6 +291,10 @@ reach the point where the muzzle starts to flash.
 
 .. note:: The timeline is the window where all the points in our animation are stored. Each of the little
           points represents a point of animation data.
+          
+          To actually preview the "Pistol_fire" animation, select the :ref:`Camera <class_Camera>` node
+          underneath Rotation Helper and check the "Preview" box underneath Perspective in the top-left corner.
+            
 
           Scrubbing the timeline means moving ourselves through the animation. So when we say "scrub the timeline
           until you reach a point", what we mean is move through the animation window until you reach the point

+ 15 - 3
tutorials/3d/spatial_material.rst

@@ -354,15 +354,27 @@ lighting in the scene.
 
 .. image:: img/spatial_material15.png
 
-Normalmap
-~~~~~~~~~
+Normal map
+~~~~~~~~~~
 
 Normal mapping allows you to set a texture that represents finer shape detail.
 This does not modify geometry, only the incident angle for light. In Godot,
-only the red and green channels of normal maps are used for wider compatibility.
+only the red and green channels of normal maps are used for better compression
+and wider compatibility.
 
 .. image:: img/spatial_material16.png
 
+.. note::
+
+  Godot requires the normal map to use the X+, Y- and Z+ coordinates. In other
+  words, if you've imported a material made to be used with another engine, you
+  may have to convert the normal map so its Y axis is flipped. Otherwise, the
+  normal map direction may appear to be inverted on the Y axis.
+
+  More information about normal maps (including a coordinate order table for
+  popular engines) can be found
+  `here <http://wiki.polycount.com/wiki/Normal_Map_Technical_Details>`__. 
+
 Rim
 ~~~
 

+ 4 - 4
tutorials/networking/high_level_multiplayer.rst

@@ -57,7 +57,7 @@ Mid level abstraction
 Before going into how we would like to synchronize a game across the network, it can be helpful to understand how the base network API for synchronization works.
 
 Godot uses a mid-level object :ref:`NetworkedMultiplayerPeer <class_NetworkedMultiplayerPeer>`.
-This object is not meant to be created directly, but is designed so that several implementations can provide it.
+This object is not meant to be created directly, but is designed so that several C++ implementations can provide it.
 
 This object extends from :ref:`PacketPeer <class_PacketPeer>`, so it inherits all the useful methods for serializing, sending and receiving data. On top of that, it adds methods to set a peer, transfer mode, etc. It also includes signals that will let you know when peers connect or disconnect.
 
@@ -85,7 +85,7 @@ Initializing as a server, listening on the given port, with a given maximum numb
 
     var peer = NetworkedMultiplayerENet.new()
     peer.create_server(SERVER_PORT, MAX_PLAYERS)
-    get_tree().set_network_peer(peer)
+    get_tree().network_peer = peer
 
 Initializing as a client, connecting to a given IP and port:
 
@@ -93,7 +93,7 @@ Initializing as a client, connecting to a given IP and port:
 
     var peer = NetworkedMultiplayerENet.new()
     peer.create_client(SERVER_IP, SERVER_PORT)
-    get_tree().set_network_peer(peer)
+    get_tree().network_peer = peer
 
 Get the previously set network peer:
 
@@ -111,7 +111,7 @@ Terminating the networking feature:
 
 ::
 
-    get_tree().set_network_peer(null)
+    get_tree().network_peer = null
 
 (Although it may make sense to send a message first to let the other peers know you're going away instead of letting the connection close or timeout, depending on your game.)
 

+ 3 - 3
tutorials/plugins/editor/spatial_gizmos.rst

@@ -82,7 +82,7 @@ or all the handle related ones.
 
     func _init():
         create_material("main", Color(1, 0, 0))
-        create_handles_material("handles")
+        create_handle_material("handles")
 
     func redraw(gizmo):
         gizmo.clear()
@@ -119,7 +119,7 @@ So the final plugin would look somewhat like this:
 
     func _init():
         create_material("main", Color(1,0,0))
-        create_handles_material("handles")
+        create_handle_material("handles")
 
     func has_gizmo(spatial):
         return spatial is MyCustomSpatial
@@ -170,7 +170,7 @@ for the Spatial nodes we want to target.
 
     func _init():
         create_material("main", Color(1, 0, 0))
-        create_handles_material("handles")
+        create_handle_material("handles")
 
     func create_gizmo(spatial):
         if spatial is MyCustomSpatial: