mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-03 05:48:42 +03:00
Merge branch 'master' into 3.2
This commit is contained in:
117
_extensions/godot_descriptions.py
Normal file
117
_extensions/godot_descriptions.py
Normal file
@@ -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,
|
||||
}
|
||||
@@ -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 -%}
|
||||
|
||||
18
conf.py
18
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"
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
-----
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
~~~
|
||||
|
||||
|
||||
@@ -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.)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user