mirror of
https://github.com/godotengine/godot-docs.git
synced 2025-12-31 17:49:03 +03:00
353 lines
10 KiB
ReStructuredText
353 lines
10 KiB
ReStructuredText
.. _doc_running_code_in_the_editor:
|
|
|
|
Running code in the editor
|
|
==========================
|
|
|
|
What is ``@tool``?
|
|
------------------
|
|
|
|
``@tool`` is a powerful line of code that, when added at the top of your script,
|
|
makes it execute in the editor. You can also decide which parts of the script
|
|
execute in the editor, which in game, and which in both.
|
|
|
|
You can use it for doing many things, but it is mostly useful in level design
|
|
for visually presenting things that are hard to predict ourselves. Here are some
|
|
use cases:
|
|
|
|
- If you have a cannon that shoots cannonballs affected by physics (gravity),
|
|
you can draw the cannonball's trajectory in the editor, making level design a
|
|
lot easier.
|
|
- If you have jumppads with varying jump heights, you can draw the maximum jump
|
|
height a player would reach if it jumped on one, also making level design
|
|
easier.
|
|
- If your player doesn't use a sprite, but draws itself using code, you can make
|
|
that drawing code execute in the editor to see your player.
|
|
|
|
.. DANGER::
|
|
|
|
``@tool`` scripts run inside the editor, and let you access the scene tree
|
|
of the currently edited scene. This is a powerful feature which also comes
|
|
with caveats, as the editor does not include protections for potential
|
|
misuse of ``@tool`` scripts.
|
|
Be **extremely** cautious when manipulating the scene tree, especially via
|
|
:ref:`Node.queue_free<class_Node_method_queue_free>`, as it can cause
|
|
crashes if you free a node while the editor runs logic involving it.
|
|
|
|
How to use it
|
|
-------------
|
|
|
|
To turn a script into a tool, add the ``@tool`` annotation at the top of your code.
|
|
|
|
To check if you are currently in the editor, use: ``Engine.is_editor_hint()``.
|
|
|
|
For example, if you want to execute some code only in the editor, use:
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
if Engine.is_editor_hint():
|
|
# Code to execute when in editor.
|
|
|
|
.. code-tab:: csharp
|
|
|
|
if (Engine.IsEditorHint())
|
|
{
|
|
// Code to execute when in editor.
|
|
}
|
|
|
|
On the other hand, if you want to execute code only in game, simply negate the
|
|
same statement:
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
if not Engine.is_editor_hint():
|
|
# Code to execute when in game.
|
|
|
|
.. code-tab:: csharp
|
|
|
|
if (!Engine.IsEditorHint())
|
|
{
|
|
// Code to execute when in game.
|
|
}
|
|
|
|
Pieces of code that do not have either of the 2 conditions above will run both
|
|
in-editor and in-game.
|
|
|
|
Here is how a ``_process()`` function might look for you:
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
func _process(delta):
|
|
if Engine.is_editor_hint():
|
|
# Code to execute in editor.
|
|
|
|
if not Engine.is_editor_hint():
|
|
# Code to execute in game.
|
|
|
|
# Code to execute both in editor and in game.
|
|
|
|
.. code-tab:: csharp
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
if (Engine.IsEditorHint())
|
|
{
|
|
// Code to execute in editor.
|
|
}
|
|
|
|
if (!Engine.IsEditorHint())
|
|
{
|
|
// Code to execute in game.
|
|
}
|
|
|
|
// Code to execute both in editor and in game.
|
|
}
|
|
|
|
.. note::
|
|
|
|
Modifications in the editor are permanent. For example, in the following
|
|
case, when we remove the script, the node will keep its rotation. Be careful
|
|
to avoid making unwanted modifications.
|
|
|
|
Try it out
|
|
-----------
|
|
|
|
Add a ``Sprite2D`` node to your scene and set the texture to Godot icon. Attach
|
|
and open a script, and change it to this:
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
@tool
|
|
extends Sprite2D
|
|
|
|
func _process(delta):
|
|
rotation += PI * delta
|
|
|
|
.. code-tab:: csharp
|
|
|
|
using Godot;
|
|
|
|
[Tool]
|
|
public partial class MySprite : Sprite2D
|
|
{
|
|
public override void _Process(double delta)
|
|
{
|
|
Rotation += Mathf.Pi * (float)delta;
|
|
}
|
|
}
|
|
|
|
Save the script and return to the editor. You should now see your object rotate.
|
|
If you run the game, it will also rotate.
|
|
|
|
.. image:: img/rotating_in_editor.gif
|
|
|
|
.. note::
|
|
|
|
If you don't see the changes, reload the scene (close it and open it again).
|
|
|
|
Now let's choose which code runs when. Modify your ``_process()`` function to
|
|
look like this:
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
func _process(delta):
|
|
if Engine.is_editor_hint():
|
|
rotation += PI * delta
|
|
else:
|
|
rotation -= PI * delta
|
|
|
|
.. code-tab:: csharp
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
if (Engine.IsEditorHint())
|
|
{
|
|
Rotation += Mathf.Pi * (float)delta;
|
|
}
|
|
else
|
|
{
|
|
Rotation -= Mathf.Pi * (float)delta;
|
|
}
|
|
}
|
|
|
|
Save the script. Now the object will spin clockwise in the editor, but if you
|
|
run the game, it will spin counter-clockwise.
|
|
|
|
Editing variables
|
|
-----------------
|
|
|
|
Add and export a variable speed to the script. To update the speed and also reset the rotation
|
|
angle add a setter ``set(new_speed)`` which is executed with the input from the inspector. Modify
|
|
``_process()`` to include the rotation speed.
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
@tool
|
|
extends Sprite2D
|
|
|
|
|
|
@export var speed = 1:
|
|
# Update speed and reset the rotation.
|
|
set(new_speed):
|
|
speed = new_speed
|
|
rotation = 0
|
|
|
|
|
|
func _process(delta):
|
|
rotation += PI * delta * speed
|
|
|
|
.. code-tab:: csharp
|
|
|
|
using Godot;
|
|
|
|
[Tool]
|
|
public partial class MySprite : Sprite2D
|
|
{
|
|
private float _speed = 1;
|
|
|
|
[Export]
|
|
public float Speed
|
|
{
|
|
get => _speed;
|
|
set
|
|
{
|
|
// Update speed and reset the rotation.
|
|
_speed = value;
|
|
Rotation = 0;
|
|
}
|
|
}
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
Rotation += Mathf.Pi * (float)delta * speed;
|
|
}
|
|
}
|
|
|
|
.. note::
|
|
|
|
Code from other nodes doesn't run in the editor. Your access to other nodes
|
|
is limited. You can access the tree and nodes, and their default properties,
|
|
but you can't access user variables. If you want to do so, other nodes have
|
|
to run in the editor too. Autoload nodes cannot be accessed in the editor at
|
|
all.
|
|
|
|
Reporting node configuration warnings
|
|
-------------------------------------
|
|
|
|
Godot uses a *node configuration warning* system to warn users about incorrectly
|
|
configured nodes. When a node isn't configured correctly, a yellow warning sign
|
|
appears next to the node's name in the Scene dock. When you hover or click on
|
|
the icon, a warning message pops up. You can use this feature in your scripts to
|
|
help you and your team avoid mistakes when setting up scenes.
|
|
|
|
When using node configuration warnings, when any value that should affect or
|
|
remove the warning changes, you need to call
|
|
:ref:`update_configuration_warnings<class_Node_method_update_configuration_warnings>` .
|
|
By default, the warning only updates when closing and reopening the scene.
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
# Use setters to update the configuration warning automatically.
|
|
@export var title = "":
|
|
set(p_title):
|
|
if p_title != title:
|
|
title = p_title
|
|
update_configuration_warnings()
|
|
|
|
@export var description = "":
|
|
set(p_description):
|
|
if p_description != description:
|
|
description = p_description
|
|
update_configuration_warnings()
|
|
|
|
|
|
func _get_configuration_warnings():
|
|
var warnings = []
|
|
|
|
if title == "":
|
|
warnings.append("Please set `title` to a non-empty value.")
|
|
|
|
if description.length() >= 100:
|
|
warnings.append("`description` should be less than 100 characters long.")
|
|
|
|
# Returning an empty array means "no warning".
|
|
return warnings
|
|
|
|
Instancing scenes
|
|
-----------------
|
|
|
|
You can instantiate packed scenes normally and add them to the scene currently
|
|
opened in the editor. By default, nodes or scenes added with
|
|
:ref:`Node.add_child(node) <class_Node_method_add_child>` are **not** visible
|
|
in the Scene tree dock and are **not** persisted to disk. If you wish the node
|
|
or scene to be visible in the scene tree dock and persisted to disk when saving
|
|
the scene, you need to set the child node's :ref:`owner <class_Node_property_owner>`
|
|
property to the currently edited scene root.
|
|
|
|
If you are using ``@tool``:
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
func _ready():
|
|
var node = Node3D.new()
|
|
add_child(node) # Parent could be any node in the scene
|
|
|
|
# The line below is required to make the node visible in the Scene tree dock
|
|
# and persist changes made by the tool script to the saved scene file.
|
|
node.set_owner(get_tree().edited_scene_root)
|
|
|
|
.. code-tab:: csharp
|
|
|
|
public override void _Ready()
|
|
{
|
|
var node = new Node3D();
|
|
AddChild(node); // Parent could be any node in the scene
|
|
|
|
// The line below is required to make the node visible in the Scene tree dock
|
|
// and persist changes made by the tool script to the saved scene file.
|
|
node.Owner = GetTree().EditedSceneRoot;
|
|
}
|
|
|
|
If you are using :ref:`EditorScript<class_EditorScript>`:
|
|
|
|
.. tabs::
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
func _run():
|
|
# `parent` could be any node in the scene.
|
|
var parent = get_scene().get_node("Parent")
|
|
var node = Node3D.new()
|
|
parent.add_child(node)
|
|
|
|
# The line below is required to make the node visible in the Scene tree dock
|
|
# and persist changes made by the tool script to the saved scene file.
|
|
node.set_owner(get_scene())
|
|
|
|
.. code-tab:: csharp
|
|
|
|
public override void _Run()
|
|
{
|
|
// `parent` could be any node in the scene.
|
|
var parent = GetScene().GetNode("Parent");
|
|
var node = new Node3D();
|
|
parent.AddChild(node);
|
|
|
|
// The line below is required to make the node visible in the Scene tree dock
|
|
// and persist changes made by the tool script to the saved scene file.
|
|
node.Owner = GetScene();
|
|
}
|
|
|
|
.. warning::
|
|
|
|
Using ``@tool`` improperly can yield many errors. It is advised to first
|
|
write the code how you want it, and only then add the ``@tool`` annotation to
|
|
the top. Also, make sure to separate code that runs in-editor from code that
|
|
runs in-game. This way, you can find bugs more easily.
|