running_code_in_the_editor.rst 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. .. _doc_running_code_in_the_editor:
  2. Running code in the editor
  3. ==========================
  4. What is ``@tool``?
  5. ------------------
  6. ``@tool`` is a powerful line of code that, when added at the top of your script,
  7. makes it execute in the editor. You can also decide which parts of the script
  8. execute in the editor, which in game, and which in both.
  9. You can use it for doing many things, but it is mostly useful in level design
  10. for visually presenting things that are hard to predict ourselves. Here are some
  11. use cases:
  12. - If you have a cannon that shoots cannonballs affected by physics (gravity),
  13. you can draw the cannonball's trajectory in the editor, making level design a
  14. lot easier.
  15. - If you have jumppads with varying jump heights, you can draw the maximum jump
  16. height a player would reach if it jumped on one, also making level design
  17. easier.
  18. - If your player doesn't use a sprite, but draws itself using code, you can make
  19. that drawing code execute in the editor to see your player.
  20. .. DANGER::
  21. ``@tool`` scripts run inside the editor, and let you access the scene tree
  22. of the currently edited scene. This is a powerful feature which also comes
  23. with caveats, as the editor does not include protections for potential
  24. misuse of ``@tool`` scripts.
  25. Be **extremely** cautious when manipulating the scene tree, especially via
  26. :ref:`Node.queue_free<class_Node_method_queue_free>`, as it can cause
  27. crashes if you free a node while the editor runs logic involving it.
  28. How to use it
  29. -------------
  30. To turn a script into a tool, add the keyword ``@tool`` at the top of your code.
  31. To check if you are currently in the editor, use: ``Engine.editor_hint``.
  32. For example, if you want to execute some code only in the editor, use:
  33. .. tabs::
  34. .. code-tab:: gdscript GDScript
  35. if Engine.editor_hint:
  36. # Code to execute when in editor.
  37. .. code-tab:: csharp
  38. if (Engine.EditorHint)
  39. {
  40. // Code to execute when in editor.
  41. }
  42. On the other hand, if you want to execute code only in game, simply negate the
  43. same statement:
  44. .. tabs::
  45. .. code-tab:: gdscript GDScript
  46. if not Engine.editor_hint:
  47. # Code to execute when in game.
  48. .. code-tab:: csharp
  49. if (!Engine.EditorHint)
  50. {
  51. // Code to execute when in game.
  52. }
  53. Pieces of code do not have either of the 2 conditions above will run both
  54. in-editor and in-game.
  55. Here is how a ``_process()`` function might look for you:
  56. .. tabs::
  57. .. code-tab:: gdscript GDScript
  58. func _process(delta):
  59. if Engine.editor_hint:
  60. # Code to execute in editor.
  61. if not Engine.editor_hint:
  62. # Code to execute in game.
  63. # Code to execute both in editor and in game.
  64. .. code-tab:: csharp
  65. public override void _Process(float delta)
  66. {
  67. if (Engine.EditorHint)
  68. {
  69. // Code to execute in editor.
  70. }
  71. if (!Engine.EditorHint)
  72. {
  73. // Code to execute in game.
  74. }
  75. // Code to execute both in editor and in game.
  76. }
  77. .. note::
  78. Modifications in the editor are permanent. For example, in the following
  79. case, when we remove the script, the node will keep its rotation. Be careful
  80. to avoid making unwanted modifications.
  81. Try it out
  82. -----------
  83. Add a ``Sprite2D`` node to your scene and set the texture to Godot icon. Attach
  84. and open a script, and change it to this:
  85. .. tabs::
  86. .. code-tab:: gdscript GDScript
  87. @tool
  88. extends Sprite2D
  89. func _process(delta):
  90. rotation_degrees += 180 * delta
  91. .. code-tab:: csharp
  92. using Godot;
  93. using System;
  94. [Tool]
  95. public class MySprite : Sprite2D
  96. {
  97. public override void _Process(float delta)
  98. {
  99. RotationDegrees += 180 * delta;
  100. }
  101. }
  102. Save the script and return to the editor. You should now see your object rotate.
  103. If you run the game, it will also rotate.
  104. .. image:: img/rotating_in_editor.gif
  105. .. note::
  106. If you don't see the changes, reload the scene (close it and open it again).
  107. Now let's choose which code runs when. Modify your ``_process()`` function to
  108. look like this:
  109. .. tabs::
  110. .. code-tab:: gdscript GDScript
  111. func _process(delta):
  112. if Engine.editor_hint:
  113. rotation_degrees += 180 * delta
  114. else:
  115. rotation_degrees -= 180 * delta
  116. .. code-tab:: csharp
  117. public override void _Process(float delta)
  118. {
  119. if (Engine.EditorHint)
  120. {
  121. RotationDegrees += 180 * delta;
  122. }
  123. else
  124. {
  125. RotationDegrees -= 180 * delta;
  126. }
  127. }
  128. Save the script. Now the object will spin clockwise in the editor, but if you
  129. run the game, it will spin counter-clockwise.
  130. Editing variables
  131. -----------------
  132. Add and export a variable speed to the script. The function set_speed after
  133. ``setget`` is executed with your input to change the variable. Modify
  134. ``_process()`` to include the rotation speed.
  135. .. tabs::
  136. .. code-tab:: gdscript GDScript
  137. @tool
  138. extends Sprite2D
  139. export var speed = 1 setget set_speed
  140. # Update speed and reset the rotation.
  141. func set_speed(new_speed):
  142. speed = new_speed
  143. rotation_degrees = 0
  144. func _process(delta):
  145. rotation_degrees += 180 * delta * speed
  146. .. code-tab:: csharp
  147. using Godot;
  148. using System;
  149. [Tool]
  150. public class MySprite : Sprite2D
  151. {
  152. private float speed = 1;
  153. [Export]
  154. public float Speed {
  155. get => speed;
  156. set => SetSpeed(value);
  157. }
  158. // Update speed and reset the rotation.
  159. private void SetSpeed(float newSpeed)
  160. {
  161. speed = newSpeed;
  162. RotationDegrees = 0;
  163. }
  164. public override void _Process(float delta)
  165. {
  166. RotationDegrees += 180 * delta * speed;
  167. }
  168. }
  169. .. note::
  170. Code from other nodes doesn't run in the editor. Your access to other nodes
  171. is limited. You can access the tree and nodes, and their default properties,
  172. but you can't access user variables. If you want to do so, other nodes have
  173. to run in the editor too. AutoLoad nodes cannot be accessed in the editor at
  174. all.
  175. Reporting node configuration warnings
  176. -------------------------------------
  177. Godot uses a *node configuration warning* system to warn users about incorrectly
  178. configured nodes. When a node isn't configured correctly, a yellow warning sign
  179. appears next to the node's name in the Scene dock. When you hover or click on
  180. the icon, a warning message pops up. You can use this feature in your scripts to
  181. help you and your team avoid mistakes when setting up scenes.
  182. When using node configuration warnings, when any value that should affect or
  183. remove the warning changes, you need to call
  184. :ref:`update_configuration_warning<class_Node_method_update_configuration_warning>` .
  185. By default, the warning only updates when closing and reopening the scene.
  186. .. tabs::
  187. .. code-tab:: gdscript GDScript
  188. # Use setters to update the configuration warning automatically.
  189. export var title = "" setget set_title
  190. export var description = "" setget set_description
  191. func set_title(p_title):
  192. if p_title != title:
  193. title = p_title
  194. update_configuration_warning()
  195. func set_description(p_description):
  196. if p_description != description:
  197. description = p_description
  198. update_configuration_warning()
  199. func _get_configuration_warning():
  200. var warning = ""
  201. if title == "":
  202. warning += "Please set `title` to a non-empty value."
  203. if description.size() >= 100:
  204. # Add a blank line between each warning to distinguish them individually.
  205. if warning != "":
  206. warning += "\n"
  207. warning += "`description` should be less than 100 characters long."
  208. # Returning an empty string means "no warning".
  209. return warning
  210. Instancing scenes
  211. -----------------
  212. You can instantiate packed scenes normally and add them to the scene currently
  213. opened in the editor. By default, nodes or scenes added with
  214. :ref:`Node.add_child(node) <class_Node_method_add_child>` are **not** visible
  215. in the Scene tree dock and are **not** persisted to disk. If you wish the node
  216. or scene to be visible in the scene tree dock and persisted to disk when saving
  217. the scene, you need to set the child node's :ref:`owner <class_Node_property_owner>`
  218. property to the currently edited scene root.
  219. If you are using ``@tool``:
  220. .. tabs::
  221. .. code-tab:: gdscript GDScript
  222. func _ready():
  223. var node = Spatial.new()
  224. add_child(node) # Parent could be any node in the scene
  225. # The line below is required to make the node visible in the Scene tree dock
  226. # and persist changes made by the tool script to the saved scene file.
  227. node.set_owner(get_tree().edited_scene_root)
  228. .. code-tab:: csharp
  229. public override void _Ready()
  230. {
  231. var node = new Spatial();
  232. AddChild(node); // Parent could be any node in the scene
  233. // The line below is required to make the node visible in the Scene tree dock
  234. // and persist changes made by the tool script to the saved scene file.
  235. node.Owner = GetTree().EditedSceneRoot;
  236. }
  237. If you are using :ref:`EditorScript<class_EditorScript>`:
  238. .. tabs::
  239. .. code-tab:: gdscript GDScript
  240. func _run():
  241. # `parent` could be any node in the scene.
  242. var parent = get_scene().find_node("Parent")
  243. var node = Spatial.new()
  244. parent.add_child(node)
  245. # The line below is required to make the node visible in the Scene tree dock
  246. # and persist changes made by the tool script to the saved scene file.
  247. node.set_owner(get_scene())
  248. .. code-tab:: csharp
  249. public override void _Run()
  250. {
  251. // `parent` could be any node in the scene.
  252. var parent = GetScene().FindNode("Parent");
  253. var node = new Spatial();
  254. parent.AddChild(node);
  255. // The line below is required to make the node visible in the Scene tree dock
  256. // and persist changes made by the tool script to the saved scene file.
  257. node.Owner = GetScene();
  258. }
  259. .. warning::
  260. Using ``@tool`` improperly can yield many errors. It is advised to first
  261. write the code how you want it, and only then add the ``@tool`` keyword to
  262. the top. Also, make sure to separate code that runs in-editor from code that
  263. runs in-game. This way, you can find bugs more easily.