From f71d2c3dd5a2d859a71d6c70daa054b7ff96d133 Mon Sep 17 00:00:00 2001 From: "Andrii Doroshenko (Xrayez)" Date: Sat, 20 Jul 2019 13:33:07 +0300 Subject: [PATCH 01/18] Elaborate on yielding to `completed` signal in GDScript basics Also mention that one can get the signal's argument via yield once emitted. --- .../scripting/gdscript/gdscript_basics.rst | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/getting_started/scripting/gdscript/gdscript_basics.rst b/getting_started/scripting/gdscript/gdscript_basics.rst index 0a47e87e2..4e3faea42 100644 --- a/getting_started/scripting/gdscript/gdscript_basics.rst +++ b/getting_started/scripting/gdscript/gdscript_basics.rst @@ -1714,6 +1714,39 @@ into an invalid state, for example: ``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 ~~~~~~~~~~~~~~~ From cc17b4ca0924c2ca8df3fcb6a174732151325ef4 Mon Sep 17 00:00:00 2001 From: abe Date: Mon, 27 Apr 2020 10:32:57 -0400 Subject: [PATCH 02/18] Include how to preview animations (#3456) * Include how to preview animations As a Godot newbie, it wasn't very clear running through this tutorial how to actually preview animations when I got to the "scrubbing the timeline" part. * Apply Calinou's suggestion Co-Authored-By: Hugo Locurcio Co-authored-by: Max Hilbrunner --- tutorials/3d/fps_tutorial/part_two.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tutorials/3d/fps_tutorial/part_two.rst b/tutorials/3d/fps_tutorial/part_two.rst index f62c1ef31..1b30079c6 100644 --- a/tutorials/3d/fps_tutorial/part_two.rst +++ b/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 ` 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 From 75f6f8997c6418583bdcff6a5b882c2411103bd5 Mon Sep 17 00:00:00 2001 From: Lee Matos Date: Mon, 27 Apr 2020 11:39:16 -0400 Subject: [PATCH 03/18] Clarify that "right side" means Advanced menu in Signal interface (#3453) Co-Authored-By: Hugo Locurcio --- getting_started/step_by_step/signals.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting_started/step_by_step/signals.rst b/getting_started/step_by_step/signals.rst index bb5efb848..bb93e6381 100644 --- a/getting_started/step_by_step/signals.rst +++ b/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. From 8bd9da0ca012f072faea3e255b2519e03260c5c4 Mon Sep 17 00:00:00 2001 From: Clay John Date: Mon, 27 Apr 2020 09:56:10 -0700 Subject: [PATCH 04/18] Initial Sky shader reference page (#3416) * Initial Sky shader reference page --- tutorials/shading/shading_reference/index.rst | 1 + .../shading/shading_reference/shaders.rst | 1 + .../shading/shading_reference/sky_shader.rst | 161 ++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 tutorials/shading/shading_reference/sky_shader.rst diff --git a/tutorials/shading/shading_reference/index.rst b/tutorials/shading/shading_reference/index.rst index 82740796d..dcea634d7 100644 --- a/tutorials/shading/shading_reference/index.rst +++ b/tutorials/shading/shading_reference/index.rst @@ -10,3 +10,4 @@ Shading reference spatial_shader canvas_item_shader particle_shader + sky_shader diff --git a/tutorials/shading/shading_reference/shaders.rst b/tutorials/shading/shading_reference/shaders.rst index 1f3ce087f..c9aa1d5c2 100644 --- a/tutorials/shading/shading_reference/shaders.rst +++ b/tutorials/shading/shading_reference/shaders.rst @@ -41,6 +41,7 @@ Valid types are: * :ref:`spatial `: For 3D rendering. * :ref:`canvas_item `: For 2D rendering. * :ref:`particles `: For particle systems. +* :ref:`sky `: For rendering :ref:`Skies `. For detailed information on each shading type, see the corresponding reference document. diff --git a/tutorials/shading/shading_reference/sky_shader.rst b/tutorials/shading/shading_reference/sky_shader.rst new file mode 100644 index 000000000..54201aaef --- /dev/null +++ b/tutorials/shading/shading_reference/sky_shader.rst @@ -0,0 +1,161 @@ +.. _doc_sky_shader: + +Sky shaders +=========== + +Sky shaders are a special type of shader used for drawing sky backgrounds +and for updating radiance cubemaps which are used for image-based lighting +(IBL). Sky shaders only have one processing function, the ``fragment()`` +function. + +There are three places the sky shader is used. + +* First the sky shader is used to draw the sky when you have selected to use + a Sky as the background in your scene. +* Second, the sky shader is used to update the radiance cubemap + when using the Sky for ambient color or reflections. +* Third, the sky shader is used to draw the lower res subpasses which can be + used in the high-res background or cubemap pass. + +In total, this means the sky shader can run up +to six times per frame, however, in practice it will be much less than that +because the radiance cubemap does not need to be updated every frame, and +not all subpasses will be used. You can change the behavior of the shader +based on where it is called by checking the ``AT_*_PASS`` booleans. For +example: + +.. code-block:: glsl + + shader_type sky; + + void fragment() { + if (AT_CUBEMAP_PASS) { + // Sets the radiance cubemap to a nice shade of blue instead of doing + // expensive sky calculations + COLOR = vec3(0.2, 0.6, 1.0); + } else { + // Do expensive sky calculations for background sky only + COLOR = get_sky_color(EYEDIR); + } + } + + +When using the sky shader to draw a background, the shader will be called for +all non-occluded fragments on the screen. However, for the background's +subpasses, the shader will be called for every pixel of the subpass. + +When using the sky shader to update the radiance cubemap, the sky shader +will be called for every pixel in the cubemap. On the other hand, the shader +will only be called when the radiance cubemap needs to be updated. The radiance +cubemap needs to be updated when any of the shader parameters are updated. +For example, if ``TIME`` is used in the shader, then the radiance cubemap +will update every frame. The following list of changes force an update of +the radiance cubemap: + +* ``TIME`` is used. +* ``POSITION`` is used and the camera position changes. +* If any ``LIGHTX_*`` properties are used and any + :ref:`DirectionalLight3D ` changes. +* If any uniform is changed in the shader. +* If the screen is resized and either of the subpasses are used. + +Try to avoid updating the radiance cubemap needlessly. If you do need to +update the radiance cubemap each frame, make sure your +:ref:`Sky process mode ` is set to +:ref:`REALTIME `. + +Render modes +^^^^^^^^^^^^ + +Subpasses allow you to do more expensive calculations at a lower resolution +to speed up your shaders. For example the following code renders clouds at +a lower resolution than the rest of the sky: + +.. code-block:: glsl + + shader_type sky; + render_mode use_half_res_pass; + + void fragment() { + if (AT_HALF_RES_PASS) { + // Run cloud calculation for 1/4 of the pixels + vec4 color = generate_clouds(EYEDIR); + COLOR = color.rgb; + ALPHA = color.a; + } else { + // At full resolution pass, blend sky and clouds together + vec3 color = generate_sky(EYEDIR); + COLOR = color + HALF_RES_COLOR.rgb * HALF_RES_COLOR.a; + } + } + ++---------------------------------+----------------------------------------------------------------------+ +| Render mode | Description | ++=================================+======================================================================+ +| **use_half_res_pass** | Allows the shader to write to and access the half resolution pass. | ++---------------------------------+----------------------------------------------------------------------+ +| **use_quarter_res_pass** | Allows the shader to write to and access the quarter resolution pass.| ++---------------------------------+----------------------------------------------------------------------+ + +Built-ins +^^^^^^^^^ + +Values marked as "in" are read-only. Values marked as "out" are for optional writing and will +not necessarily contain sensible values. Values marked as "inout" provide a sensible default +value, and can optionally be written to. Samplers are not subjects of writing and they are +not marked. + +Global built-ins +^^^^^^^^^^^^^^^^ + +Global built-ins are available everywhere, including custom functions. + +There are 4 ``LIGHTX`` lights, accessed as ``LIGHT0``, ``LIGHT1``, ``LIGHT2``, and ``LIGHT3``. + + ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| Built-in | Description | ++=================================+==========================================================================================================================+ +| in float **TIME** | Global time, in seconds. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in vec3 **POSITION** | Camera position in world space | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in SamplerCube **RADIANCE** | Radiance cubemap. Can only be read from during background pass. Check ``!AT_CUBEMAP_PASS`` before using. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in bool **AT_HALF_RES_PASS** | Currently rendering to half resolution pass. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in bool **AT_QUARTER_RES_PASS** | Currently rendering to quarter resolution pass. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in bool **AT_CUBEMAP_PASS** | Currently rendering to radiance cubemap. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in bool **LIGHTX_ENABLED** | ``LightX`` is visible and in the scene. If ``false``, other light properties may be garbage. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in float **LIGHTX_ENERGY** | Energy multiplier for ``LIGHTX``. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in vec3 **LIGHTX_DIRECTION** | Direction that ``LIGHTX`` is facing. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in vec3 **LIGHTX_COLOR** | Color of ``LIGHTX``. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ +| in float **LIGHTX_SIZE** | Angular diameter of ``LIGHTX`` in the sky. Expressed in degrees. For reference, the sun from earth is about 0.5 degrees. | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------+ + +Fragment built-ins +^^^^^^^^^^^^^^^^^^ + ++---------------------------------+-------------------------------------------------------------------------------------------------+ +| Built-in | Description | ++=================================+=================================================================================================+ +| out vec3 **COLOR** | Output color | ++---------------------------------+-------------------------------------------------------------------------------------------------+ +| out float **ALPHA** | Output alpha value, can only be used in subpasses. | ++---------------------------------+-------------------------------------------------------------------------------------------------+ +| in vec3 **EYEDIR** | Normalized direction of current pixel. Use this as your basic direction for procedural effects. | ++---------------------------------+-------------------------------------------------------------------------------------------------+ +| in vec2 **SCREEN_UV** | Screen UV coordinate for current pixel. Used to map a texture to the full screen. | ++---------------------------------+-------------------------------------------------------------------------------------------------+ +| in vec2 **SKY_COORDS** | Sphere UV. Used to map a panorama texture to the sky. | ++---------------------------------+-------------------------------------------------------------------------------------------------+ +| in vec4 **HALF_RES_COLOR** | Color value of corresponding pixel from half resolution pass. Uses linear filter. | ++---------------------------------+-------------------------------------------------------------------------------------------------+ +| in vec4 **QUARTER_RES_COLOR** | Color value of corresponding pixel from quarter resolution pass. Uses linear filter. | ++---------------------------------+-------------------------------------------------------------------------------------------------+ From 3c79f3e3218bff53a6303e7b85ebe2089c09c4b6 Mon Sep 17 00:00:00 2001 From: Max Hilbrunner Date: Mon, 27 Apr 2020 19:48:52 +0200 Subject: [PATCH 05/18] Fix locale names AGAIN :) this time formatting to ISO 639-1 dynamically --- _templates/layout.html | 4 +++- conf.py | 14 +------------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/_templates/layout.html b/_templates/layout.html index a10061e6d..92323784d 100644 --- a/_templates/layout.html +++ b/_templates/layout.html @@ -2,7 +2,9 @@ {% block linktags -%} {% if godot_inject_language_links -%} {% for alternate_lang in godot_docs_supported_languages -%} - + {# Convert to ISO 639-1 format, e.g. zh_CN -> zh-cn -#} + {% set alternate_lang_href = alternate_lang.lower().replace("_", "-") -%} + {% endfor -%} diff --git a/conf.py b/conf.py index af12b245d..2b11170a2 100644 --- a/conf.py +++ b/conf.py @@ -66,17 +66,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 +98,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,7 +121,7 @@ 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", From 30230b297168db17a8c56d08df67ab1207305200 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 28 Apr 2020 09:38:51 +0200 Subject: [PATCH 06/18] Clarify that NetworkedMultiplayerPeer cannot be extended via GDScript See #3460. --- tutorials/networking/high_level_multiplayer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/networking/high_level_multiplayer.rst b/tutorials/networking/high_level_multiplayer.rst index fb438bc36..485aa3259 100644 --- a/tutorials/networking/high_level_multiplayer.rst +++ b/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 `. -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 `, 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. From 0b6d26e33d7955590f1d75a816caff8cde251c42 Mon Sep 17 00:00:00 2001 From: Max Hilbrunner Date: Mon, 27 Apr 2020 20:00:25 +0200 Subject: [PATCH 07/18] Prepend "(DEV)" to HTML titles if build locally/not on RTD --- _templates/layout.html | 4 ++++ conf.py | 3 +++ 2 files changed, 7 insertions(+) diff --git a/_templates/layout.html b/_templates/layout.html index 92323784d..5274db8cf 100644 --- a/_templates/layout.html +++ b/_templates/layout.html @@ -12,3 +12,7 @@ {% endif -%} {{ super() }} {% endblock -%} + +{% block htmltitle -%} +{{ godot_title_prefix }}{{ title|striptags|e }}{{ titlesuffix }} +{% endblock -%} diff --git a/conf.py b/conf.py index 2b11170a2..f693f1457 100644 --- a/conf.py +++ b/conf.py @@ -126,6 +126,9 @@ html_context = { "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" From b99bcb2bbdf8b7b7a169d1b588c95d16d951c78a Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Wed, 29 Apr 2020 18:02:48 +0200 Subject: [PATCH 08/18] Document BMP loading limitations in Importing images --- getting_started/workflow/assets/importing_images.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/getting_started/workflow/assets/importing_images.rst b/getting_started/workflow/assets/importing_images.rst index 6c949a5ac..8e3d9d25e 100644 --- a/getting_started/workflow/assets/importing_images.rst +++ b/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. From a56bfcad1fef5eb8dd486cf1ced789690880ba9e Mon Sep 17 00:00:00 2001 From: VardenTheOne <57115583+VardenTheOne@users.noreply.github.com> Date: Thu, 30 Apr 2020 18:32:10 +0300 Subject: [PATCH 09/18] Fix method name --- tutorials/plugins/editor/spatial_gizmos.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tutorials/plugins/editor/spatial_gizmos.rst b/tutorials/plugins/editor/spatial_gizmos.rst index f94828175..00b245dc0 100644 --- a/tutorials/plugins/editor/spatial_gizmos.rst +++ b/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: From a492d292b9be18129b140ce3717f10d950759d80 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Thu, 30 Apr 2020 20:10:48 +0200 Subject: [PATCH 10/18] Mention the lack of support for cross-language script inheritance See https://github.com/godotengine/godot/issues/38352. --- .../scripting/cross_language_scripting.rst | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/getting_started/scripting/cross_language_scripting.rst b/getting_started/scripting/cross_language_scripting.rst index 8663db6e3..32f0500c0 100644 --- a/getting_started/scripting/cross_language_scripting.rst +++ b/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() `. :: @@ -83,15 +83,15 @@ with :ref:`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() `. 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() `. The first arguments is the +:ref:`Object.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 `__ +for more information. From 63a97f6d8ad7e04826d2bc59dfdf1c3a6b42defb Mon Sep 17 00:00:00 2001 From: tanchar Date: Fri, 1 May 2020 22:21:01 +0200 Subject: [PATCH 11/18] Replace `Meta` keyboard shortcut with explicit key (#3477) --- getting_started/step_by_step/ui_game_user_interface.rst | 4 ++-- getting_started/step_by_step/ui_main_menu.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/getting_started/step_by_step/ui_game_user_interface.rst b/getting_started/step_by_step/ui_game_user_interface.rst index 5f3e744fa..97e6feb68 100644 --- a/getting_started/step_by_step/ui_game_user_interface.rst +++ b/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. diff --git a/getting_started/step_by_step/ui_main_menu.rst b/getting_started/step_by_step/ui_main_menu.rst index 0ecff9920..c92cacebf 100644 --- a/getting_started/step_by_step/ui_main_menu.rst +++ b/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 From 726fe7ca1fd2375e96e6f22a22dff2e56156c903 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sat, 2 May 2020 01:12:09 +0200 Subject: [PATCH 12/18] Use `network_peer` as a property instead of using the setter method --- tutorials/networking/high_level_multiplayer.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tutorials/networking/high_level_multiplayer.rst b/tutorials/networking/high_level_multiplayer.rst index 485aa3259..440f1bc75 100644 --- a/tutorials/networking/high_level_multiplayer.rst +++ b/tutorials/networking/high_level_multiplayer.rst @@ -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.) From b844c946d9d2741b1546ba5599bd0b072824429a Mon Sep 17 00:00:00 2001 From: mechPenSketch Date: Sat, 2 May 2020 20:03:24 +0800 Subject: [PATCH 13/18] Expand NodePath hints, added Resource hints to GDScript exports (#3473) --- .../scripting/gdscript/gdscript_exports.rst | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/getting_started/scripting/gdscript/gdscript_exports.rst b/getting_started/scripting/gdscript/gdscript_exports.rst index 03ec056e3..eae601e9c 100644 --- a/getting_started/scripting/gdscript/gdscript_exports.rst +++ b/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 From 2927a912a52f7d4c72428918265dae42e7e89e7c Mon Sep 17 00:00:00 2001 From: Max Hilbrunner Date: Sat, 2 May 2020 16:24:50 +0200 Subject: [PATCH 14/18] Create Sphinx extension to generate HTML meta description tags --- _extensions/godot_descriptions.py | 117 ++++++++++++++++++++++++++++++ conf.py | 1 + 2 files changed, 118 insertions(+) create mode 100644 _extensions/godot_descriptions.py diff --git a/_extensions/godot_descriptions.py b/_extensions/godot_descriptions.py new file mode 100644 index 000000000..96434af58 --- /dev/null +++ b/_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 = ( + '\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, + } diff --git a/conf.py b/conf.py index f693f1457..24def6f1c 100644 --- a/conf.py +++ b/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", From 8ea31de5efe1a36ba923c97d2b4aa168a56f12b7 Mon Sep 17 00:00:00 2001 From: Eric M <41730826+EricEzaM@users.noreply.github.com> Date: Sun, 3 May 2020 06:32:02 +1000 Subject: [PATCH 15/18] Added documentation for drag-and-drop support for exported arrays (#3480) * Added documentation for drag-and-drop support for exported arrays * Apply suggestions from code review Co-authored-by: Hugo Locurcio Co-authored-by: Max Hilbrunner Co-authored-by: Hugo Locurcio --- .../scripting/gdscript/gdscript_exports.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/getting_started/scripting/gdscript/gdscript_exports.rst b/getting_started/scripting/gdscript/gdscript_exports.rst index eae601e9c..9f7be333b 100644 --- a/getting_started/scripting/gdscript/gdscript_exports.rst +++ b/getting_started/scripting/gdscript/gdscript_exports.rst @@ -163,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. @@ -181,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 = PackedVector3Array() From fdf4c98a69784f70f85de1dc70aaad9908acc29a Mon Sep 17 00:00:00 2001 From: abe Date: Sat, 2 May 2020 19:41:36 -0400 Subject: [PATCH 16/18] FPS Tutorial Part 5 typo fix --- tutorials/3d/fps_tutorial/part_five.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/3d/fps_tutorial/part_five.rst b/tutorials/3d/fps_tutorial/part_five.rst index 2b776256c..0736be8ed 100644 --- a/tutorials/3d/fps_tutorial/part_five.rst +++ b/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 From e4f643026289b23ce4102b3d02cd6813617d508d Mon Sep 17 00:00:00 2001 From: Michael Alexsander Date: Sun, 3 May 2020 10:22:42 -0300 Subject: [PATCH 17/18] Make more snippets in GDScript basics page follow the styleguide (#3487) --- .../scripting/gdscript/gdscript_basics.rst | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/getting_started/scripting/gdscript/gdscript_basics.rst b/getting_started/scripting/gdscript/gdscript_basics.rst index 6bd5648c5..868e8d0fa 100644 --- a/getting_started/scripting/gdscript/gdscript_basics.rst +++ b/getting_started/scripting/gdscript/gdscript_basics.rst @@ -987,7 +987,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 @@ -1000,11 +999,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")) @@ -1093,9 +1095,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 @@ -1103,6 +1107,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 @@ -1138,9 +1143,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() @@ -1162,6 +1170,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() @@ -1194,9 +1203,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. @@ -1238,6 +1249,7 @@ placed at the top of the file:: tool extends Button + func _ready(): print("Hello") @@ -1276,6 +1288,7 @@ to. To create custom signals for a class, use the ``signal`` keyword. extends Node + # A signal named health_depleted. signal health_depleted @@ -1301,6 +1314,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() @@ -1320,6 +1334,7 @@ the :ref:`Object.connect() ` method:: ... signal health_changed + func take_damage(amount): var old_health = health health -= amount @@ -1433,6 +1448,7 @@ an example:: yield() print("world") + func _ready(): var y = my_func() # Function state saved in 'y'. @@ -1454,6 +1470,7 @@ for example:: print(yield()) return "cheers!" + func _ready(): var y = my_func() # Function state saved in 'y'. @@ -1473,6 +1490,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(): @@ -1502,6 +1520,7 @@ 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") @@ -1512,7 +1531,7 @@ 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 + # 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 @@ -1528,10 +1547,11 @@ multiple times, you can yield to the ``completed`` signal conditionally: return result + func make(): var result = generate() - if result is GDScriptFunctionState: # still working + if result is GDScriptFunctionState: # Still working. result = yield(result, "completed") return result @@ -1553,6 +1573,7 @@ be obtained when a call to ``Node._ready()`` is made. var my_label + func _ready(): my_label = get_node("MyLabel") From 53eedbfdd08e7d0edf3f58943e2eb10f5dc5f6e5 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sun, 3 May 2020 21:11:32 +0200 Subject: [PATCH 18/18] Mention the normal map coordinate system expected by Godot --- .../workflow/assets/importing_images.rst | 11 +++++++++++ tutorials/3d/spatial_material.rst | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/getting_started/workflow/assets/importing_images.rst b/getting_started/workflow/assets/importing_images.rst index 8e3d9d25e..7823dbb36 100644 --- a/getting_started/workflow/assets/importing_images.rst +++ b/getting_started/workflow/assets/importing_images.rst @@ -128,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 `__. + Flags ----- diff --git a/tutorials/3d/spatial_material.rst b/tutorials/3d/spatial_material.rst index 895ddd911..3ea07e135 100644 --- a/tutorials/3d/spatial_material.rst +++ b/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 `__. + Rim ~~~