running_code_in_the_editor.rst 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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, 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.
  7. 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:
  8. - 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.
  9. - 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.
  10. - 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.
  11. .. DANGER::
  12. ``tool`` scripts run inside the editor, and let you access the scene tree
  13. of the currently edited scene. This is a powerful feature which also comes
  14. with caveats, as the editor does not include protections for potential
  15. misuse of ``tool`` scripts.
  16. Be **extremely** cautious when manipulating the scene tree, especially via
  17. :ref:`Node.queue_free<class_Node_method_queue_free>`, as it can cause
  18. crashes if you free a node while the editor runs logic involving it.
  19. How to use it
  20. -------------
  21. To turn a script into a tool, add the keyword ``tool`` at the top of your code.
  22. To check if you are currently in the editor, use: ``Engine.editor_hint``.
  23. For example, if you want to execute some code only in the editor, use:
  24. .. tabs::
  25. .. code-tab:: gdscript GDScript
  26. if Engine.editor_hint:
  27. # Code to execute when in editor.
  28. .. code-tab:: csharp
  29. if (Engine.EditorHint)
  30. {
  31. // Code to execute when in editor.
  32. }
  33. On the other hand, if you want to execute code only in game, simply negate the same statement:
  34. .. tabs::
  35. .. code-tab:: gdscript GDScript
  36. if not Engine.editor_hint:
  37. # Code to execute when in game.
  38. .. code-tab:: csharp
  39. if (!Engine.EditorHint)
  40. {
  41. // Code to execute when in game.
  42. }
  43. Pieces of code do not have either of the 2 conditions above will run both in-editor and in-game.
  44. Here is how a ``_process()`` function might look for you:
  45. .. tabs::
  46. .. code-tab:: gdscript GDScript
  47. func _process(delta):
  48. if Engine.editor_hint:
  49. # Code to execute in editor.
  50. if not Engine.editor_hint:
  51. # Code to execute in game.
  52. # Code to execute both in editor and in game.
  53. .. code-tab:: csharp
  54. public override void _Process(float delta)
  55. {
  56. if (Engine.EditorHint)
  57. {
  58. // Code to execute in editor.
  59. }
  60. if (!Engine.EditorHint)
  61. {
  62. // Code to execute in game.
  63. }
  64. // Code to execute both in editor and in game.
  65. }
  66. .. note:: Modifications in 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.
  67. Try it out
  68. -----------
  69. Add a ``Sprite`` node to your scene and set the texture to Godot icon. Attach and open a script, and change it to this:
  70. .. tabs::
  71. .. code-tab:: gdscript GDScript
  72. tool
  73. extends Sprite
  74. func _process(delta):
  75. rotation_degrees += 180 * delta
  76. .. code-tab:: csharp
  77. using Godot;
  78. using System;
  79. [Tool]
  80. public class MySprite : Sprite
  81. {
  82. public override void _Process(float delta)
  83. {
  84. RotationDegrees += 180 * delta;
  85. }
  86. }
  87. Save the script and return to the editor. You should now see your object rotate. If you run the game, it will also rotate.
  88. .. image:: img/rotating_in_editor.gif
  89. .. note:: If you don't see the changes, reload the scene (close it and open it again).
  90. Now let's choose which code runs when. Modify your ``_process()`` function to look like this:
  91. .. tabs::
  92. .. code-tab:: gdscript GDScript
  93. func _process(delta):
  94. if Engine.editor_hint:
  95. rotation_degrees += 180 * delta
  96. else:
  97. rotation_degrees -= 180 * delta
  98. .. code-tab:: csharp
  99. public override void _Process(float delta)
  100. {
  101. if (Engine.EditorHint)
  102. {
  103. RotationDegrees += 180 * delta;
  104. }
  105. else
  106. {
  107. RotationDegrees -= 180 * delta;
  108. }
  109. }
  110. Save the script. Now the object will spin clockwise in the editor, but if you run the game, it will spin counter-clockwise.
  111. Editing variables
  112. -----------------
  113. Add and export a variable speed to the script. The function set_speed after "setget" is executed with your input to change the variable.
  114. Modify ``_process()`` to include the rotation speed.
  115. .. tabs::
  116. .. code-tab:: gdscript GDScript
  117. tool
  118. extends Sprite
  119. export var speed = 1 setget set_speed
  120. # Update speed and reset the rotation.
  121. func set_speed(new_speed):
  122. speed = new_speed
  123. rotation_degrees = 0
  124. func _process(delta):
  125. rotation_degrees += 180 * delta * speed
  126. .. code-tab:: csharp
  127. using Godot;
  128. using System;
  129. [Tool]
  130. public class MySprite : Sprite
  131. {
  132. private float speed = 1;
  133. [Export]
  134. public float Speed {
  135. get => speed;
  136. set => SetSpeed(value);
  137. }
  138. // Update speed and reset the rotation.
  139. private void SetSpeed(float newSpeed)
  140. {
  141. speed = newSpeed;
  142. RotationDegrees = 0;
  143. }
  144. public override void _Process(float delta)
  145. {
  146. RotationDegrees += 180 * delta * speed;
  147. }
  148. }
  149. .. 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.
  150. Instancing scenes
  151. -----------------
  152. You can instantiate packed scenes normally and add them to the scene currently
  153. opened in the editor. By default, nodes or scenes added with
  154. :ref:`Node.add_child(node) <class_Node_method_add_child>` are **not** visible
  155. in the Scene tree dock and are **not** persisted to disk. If you wish the node
  156. or scene to be visible in the scene tree dock and persisted to disk when saving
  157. the scene, you need to set the child node's :ref:`owner <class_Node_property_owner>`
  158. property to the currently edited scene root.
  159. If you are using ``tool``:
  160. .. tabs::
  161. .. code-tab:: gdscript GDScript
  162. func _ready():
  163. var node = Spatial.new()
  164. add_child(node) # Parent could be any node in the scene
  165. # The line below is required to make the node visible in the Scene tree dock
  166. # and persist changes made by the tool script to the saved scene file.
  167. node.set_owner(get_tree().edited_scene_root)
  168. .. code-tab:: csharp
  169. public override void _Ready()
  170. {
  171. var node = new Spatial();
  172. AddChild(node); // Parent could be any node in the scene
  173. // The line below is required to make the node visible in the Scene tree dock
  174. // and persist changes made by the tool script to the saved scene file.
  175. node.Owner = GetTree().EditedSceneRoot;
  176. }
  177. If you are using :ref:`EditorScript<class_EditorScript>`:
  178. .. tabs::
  179. .. code-tab:: gdscript GDScript
  180. func _run():
  181. var parent = get_scene().find_node("Parent") # Parent could be any node in the scene
  182. var node = Spatial.new()
  183. parent.add_child(node)
  184. # The line below is required to make the node visible in the Scene tree dock
  185. # and persist changes made by the tool script to the saved scene file.
  186. node.set_owner(get_scene())
  187. .. code-tab:: csharp
  188. public override void _Run()
  189. {
  190. var parent = GetScene().FindNode("Parent"); // Parent could be any node in the scene
  191. var node = new Spatial();
  192. parent.AddChild(node);
  193. // The line below is required to make the node visible in the Scene tree dock
  194. // and persist changes made by the tool script to the saved scene file.
  195. node.Owner = GetScene();
  196. }
  197. .. 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`` keyword 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.