From 48596bc9edcf40c6b2bf512455daa110d073a6ea Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 14 Nov 2023 11:53:28 +0100 Subject: [PATCH] Document using EditorScript in Running code in the editor EditorScript is useful for one-off operations such as: - Use as a playground for GDScript or C# scripting without having to run a project. - Scale all light nodes in the currently edited scene. - Replace nodes that were copy-pasted with scene instances. --- ..._in_the_editor_creating_editor_script.webp | Bin 0 -> 4840 bytes .../plugins/running_code_in_the_editor.rst | 103 +++++++++++++++++- 2 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 tutorials/plugins/img/running_code_in_the_editor_creating_editor_script.webp diff --git a/tutorials/plugins/img/running_code_in_the_editor_creating_editor_script.webp b/tutorials/plugins/img/running_code_in_the_editor_creating_editor_script.webp new file mode 100644 index 0000000000000000000000000000000000000000..151546b54ed1a363083c369cf82e7950e402a798 GIT binary patch literal 4840 zcmV23wlwrv~tPD6qu z*`{r)T8*`io^9LboagsG`tOKs8%Lrid%gF$3+`|E`u}sXod0FE*0pWhwr$(CZQHi~ zru(a3{i;*dllt8lV{>~~gV;Me`NX#EjIF-0ZQHA^8@tZw3}f~;x~kY7#Yty1j5%7~ zIwwx&^vQS^JL%nccJVu2-81Z6Y}?6rrh?wZwvFAG3j=A}_?P^(J&N15jbo4aY|{Qa zV%s*7n3>(p&Xw059R&R=sH{qD6t<<}XV87SspfM5K<&pcO#=gngEYS^yO_E6Hago} zKU3V~=QcLZSr;=8dy0d!J+8VRe_=iKMrU*PXL#&S?2gNbdla^*=5tW|p9-o>A02t> zPb?Bo{n5N9>&Icq)#rTk`O+`mT|^u za}?^Bp=l}o>+CIGvl8aP6-6ggbmqqUWg_wqyh^xq(cUD9=wN0PmYgUfk#~?%qO%>- z)Lf>as4|eKx>AI(LVb?onD;+N&eHqG&>y?G{bPxl-#b#&q{#GnxrpL`z~Tk*O^*_; z5LTgpL~;pa{8`?mryWy(AM1352yINM|L~?hz%i~~La@f??|+W&k3Oot7u-%fu>mKa z66_yE+c@*pANkJgHNoDI9J}KWATkvY$Z9VGKbaUwOlMN@i8sM4{fJD#fomDS2%T;C zzD)LpJ{kg9^qqwldXm)i{= zfKMyN_6Zwm{_X}g`p)SnK03(tX5IJL%Y9RdOfQo}A)rb_ln6vLZBtsAGO4x?Ws=W9 zBQu&gwF62v8w2#x&9A+VAsQlx^6sS1i%jGcATl=P!&q9%Jkd?^zjG<1rKIvL(tQrb z5UQAn3J~`@kuN5V%pb=jSFSUY)P8QGK39K^_qfL$S6%fvNK7v0_d!jEIywx0zT>?+ z<#f6A`pYvc^k>c=gPaIuj3)n6kaYljNW?S^HEh&Aaz?T@ib(+E9`HA8bQypzk(`Vi zZ)B@%;KN##R@SiVhyVa@kxat}01!kS6Vz17KMi9b8>IRWppYRfKDtw){i85V2K(wm zEZle-owGgLNyXkU^4BjlEkfyJlBX$l1%O(KY#Bi6=Vk=E@@zAggOHyXrM67UL!?gq zA^8cAXktb%Ner_GGAYWB1QZ_vKq-lALMaIUxmx(o`4VF*+riJ+3(E$YdhCp450+zD z5ek~QN@E$7nx{5$oE~NiEu1{Tj5&w1L$f@&1%(FyHSC&&(E=~Z%0Nkhz^EYGEXtQf zMQQ={mCwa9p(UcD3{rm(^0{E|#f0+wp|))j->zqSzLU+_Zt&TAmJPRf6M5xoo>N)& z*Q`%>QzgD#`#^LWmoyVdJiOa+QM${rkJyoqyWpp8NM_+4_M}~T?tjjMFX7nps zrX9+E1J6-;1i{Q2LyPji!2YCLr_va`(90rpK^;n_fR9KdbB1d~(q|q3005yK5h(xd z+|1v}CEPuUyM4y`?!V;wxSDY1FiBsjj@gghX{k0^v;+m7uoVez8E=h;%R0 zDgg*;U6rCXfNru2b}crsyy%~!044urbN#~W=p1C~A@|#jT&_2Bx!O#!cf_*tPcJp( zLLb@OxY!G%)!Z)w(n~Zyueg|b^xB<$bjRELjX(1~*q#Zu{k^Tr=?Bd(D+(&5S*byq ziMsbi3wy_ICmy|yPArmp=Werq5c7bdrd0g&TAo&ooNt>wIJCHX^3Wc;T=Bz`P|d7S z-YizFIlZriqu(m%99|eLB%;{r|p=*X#KlL8D zqirgK{UxRnlty~P9Rl=LlZ>MznNGG8{jFs~jYk;dYIZ{c;$WInw=ur2H0KUuh6ayBBxjCA0l$0YWy?p67-0p%tfuaE@=HS7RKX>N zBAIINV~r9&7OwRmA_|6oZFivzGJBNzs7S2pK3e`%47L|5w9SvrrD)K4#(qtshA6pA zAd@J~krJoA)|ERm#*U!Wd2{-g6}BzkY8QERVza*=oqD`=zMoT-NgQ=*<8kL_yQ^dd z_U=!gUwPX7yFwg8fKX-G^r?MsJ@0CdXw7+Gak)qiXyU8IcUC`ppq2yx!P8;Yll}_l2F2z?#0tN`>&qHR+%7 zwD^gyzUGb0lvoknN7+AI6h8`X^M<0fts}iZTc8br*rpFoorm4~z=?|_1lilC^E)8m zmI)B3%<*08pH9H`&oCE~o1zIo;gnI!GeHi&5W}di7C8evHdf{t6FqyNfd+C+q|jNC zCtCT9x^(hMM0eHt#YDu3u84?ddKJ+TJ|zOIR!8~}_9d6}nZ6DM)nRk9%c85ry1`V- zxe$POc3YThTFD2#5P{03WUh7qHk=Cu)qN(Ocw%h7@p72wNe3>tnJv9I)chWj( z1uFBlWv=c3>|-tzOnKD&TsXgzr-f{?vJ5%y4z<;)t2S=LahZoBEW}TA3lkC9Sp+<9 z_dg*bqRT!kgnkyYweUSkT7f`Bi?M!I2@$aH3!BqBwmJ}n3JSJ&pECl!ww!RZK>!ff zY6U8Dyg$(O0sHqgb0H<((C&Td|FsI(WekRrOtEt4ca`Do+RG9z%7qEP_iNu+rrM2) zD6+2G5FN}1Cgs1h+ip_~mXW5Ma!Rkaf7iqz@UW{M1ns9z$f4ct-c&qsJZ;Aaz6Z_grWkYvFda9w=vXcrSC~~o!ClqRr zcOow&og65PCW?vzU{~ajv6R+`GRta@#T-%p`g?-jzg=UG&Y;`r zN9B1KW0h41B3T_9^LA}1Su)EkhLUl=(^;$8c?LNrEzHJPQK2pc}*&^?8X=|3cybNYA5DaD&J1=^dxOVyZPK`-Kx zu&c-0+vQdDgTwm@z1Nl$E(5-Z_Wvh$zON_e+|cA$ipY38B;-F^i!DTgF# zgst`F4ZDWHmTW(%%zg35GEyJNobKajk*M2TK*V5}Qv_U4f7Xn@I3|RZ7q*{2uvbkyv4*`G zh8=}@+HP3)nSh*8k>V>de%O;F?o_QIBAPxtdK9}V5xuRwBMfwc6P!S|d$IU1rId;J zd~8{l`MJ0Z4CfLCyZ1x#&i0O%D-<1Jebu`!Ku6%&XK3x5Fq;dfQZT2tcYYriJ;lb` zl^d&S!%+Z$kY&#X@LrUPw^l4w>G+dT1QHMAu48z|M5FH9oVNJ&Wr>JHDtzb~uN-;x zxdesfZSN1)MP%x8Yc}Ol4@KFO+9(k9GTrzBq$(3;ak4liQ2gGyl*r0*v*BhsLe^+bWMf@r_XivQz+!6`acNE;U(|?RR8zeCex@3p z^@c@G2>N?@af_t)u~hx?|5e4xBHD(|bi8i_pLtC@_`iBe<_|VIYya3tn)k|y^@9nj zr_E_tHgw30Zsrm^(!PD>2tu&qp~8_o?Y>F#PucvM6DT=LF<$IXjxy_GD$4vcGU@*C z*5Xi6UA&M(64$(ek&K?-<`8hPq7fvc=XbeDjW6jJztiM= zLZYb05|Q4lqRare`iTJ?y+GRDr&5^xz^u*BPpigOKd)K0<27{o)T%HW!#7(cs#oj6 z*QHpx#Tt~fZQxcf~k4w#iyQw+l}X>$NL+bUu9{9b4w z`wL%2Nko)hRt=mGdKC5Ej3|}74`a)b8&W8I>Qz6oLdhXv?<0C1b4MgrVT|RD%3}^y zT>BY6i*~*1vYUhiW~@r^yXSFNS~d)Y)J~pr4M`Cz`DcHymvgwf+pvCtK*9f!95nYw=xSqk#KP>GRilB5pEWt&xgxT}!4{vO55#(fHhok^_rhEQ9 zzA_z_CM*$%=yR4m7p?I4r3`e1Un-M1RB;7j&v6-`W7Q`o5(UEY*!;lX@+eLu9&nlA z<`PJfn~`_~T72c5WH9(Iv;G&gusl*Iq9>G!w&ik82)XB1kZO$E(HAEqdcwmj`G|;? z%^hV^CUdCb+GL=KC!TnF8cr7=DDMmaPP}V=5h#(;8J^Wgs`x;eH zEcdU;V&VfWf#nnkvFBH&=Z!HGX?D(4G)6?kH+Jqg%DZ261=*Cz9ICkD5{vn{=mj%2 zCFe!b&JJLllt!Z0_7ad6BN>q*-Qp`}nfAWR{_RdFuc_ltDgJSTUzi&jMOkBU5iBA0 z{L1ts=4_#dT}V>V(mXwN(NRAu#Z^+47NA7tP{nrrfvyVxvPGf5D2FV~XQlf4*u4*2 zj-y@xkZ$pncanMkv(8iag==0ehafHAH#r5I4V4gkeq~YRjzg-bWK6Ayh=|88R;!3^ zb_F_UyPwYyO+=ADCREB}4pn^nG2H3D4HgK^lkL?0*z4YM$m4wPjPVCt--I(t7VZ4b z*}im(uiM*;%qibpG8_AyWRXaztk953itns{*@G&*6S=(0l{M-OPbk~r zs)W|fwC|xul$bOO4Z;!;SI%i_h5O7U)#58TOwMBznfAZY!knW}-nOwr4oQrtCq{@p zze0yGrky^GG$tbY$dFpo+>xKq+SfSJEI~ELBbjQrN)NaiWn3z#Pp*u|4mnS+^ncE*}J9HFDgX3mLaB3U+BNv-q1W^79RMEl3aX>@b?3u%8}7i3O9X_o%I*H$GD O0NdaSsy6i>ssI4kj(ukU literal 0 HcmV?d00001 diff --git a/tutorials/plugins/running_code_in_the_editor.rst b/tutorials/plugins/running_code_in_the_editor.rst index 032ebf0637b..b957d704753 100644 --- a/tutorials/plugins/running_code_in_the_editor.rst +++ b/tutorials/plugins/running_code_in_the_editor.rst @@ -33,8 +33,8 @@ use cases: :ref:`Node.queue_free`, as it can cause crashes if you free a node while the editor runs logic involving it. -How to use it -------------- +How to use ``@tool`` +-------------------- To turn a script into a tool, add the ``@tool`` annotation at the top of your code. @@ -118,8 +118,8 @@ Here is how a ``_process()`` function might look for you: behavior from the super class. Therefore the extending script should also specify the ``@tool`` annotation. -Try it out ------------ +Try ``@tool`` 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: @@ -286,6 +286,97 @@ By default, the warning only updates when closing and reopening the scene. # Returning an empty array means "no warning". return warnings +Running one-off scripts using EditorScript +------------------------------------------ + +Sometimes, you need to run code just one time to automate a certain task that is +not available in the editor out of the box. Some examples might be: + +- Use as a playground for GDScript or C# scripting without having to run a project. + ``print()`` output is displayed in the editor Output panel. +- Scale all light nodes in the currently edited scene, as you noticed your level + ends up looking too dark or too bright after placing lights where desired. +- Replace nodes that were copy-pasted with scene instances to make them easier + to modify later. + +This is available in Godot by extending :ref:`class_EditorScript` in a script. +This provides a way to run individual scripts in the editor without having to +create an editor plugin. + +To create an EditorScript, right-click a folder or empty space in the FileSystem +dock then choose **New > Script...**. In the script creation dialog, click the +tree icon to choose an object to extend from (or enter ``EditorScript`` directly +in the field on the left, though note this is case-sensitive): + +.. figure:: img/running_code_in_the_editor_creating_editor_script.webp + :align: center + :alt: Creating an editor script in the script editor creation dialog + + Creating an editor script in the script editor creation dialog + +This will automatically select a script template that is suited for +EditorScripts, with a ``_run()`` method already inserted: + +:: + + @tool + extends EditorScript + + # Called when the script is executed (using File -> Run in Script Editor). + func _run(): + pass + +This ``_run()`` method is executed when you use **File > Run** or the keyboard +shortcut :kbd:`Ctrl + Shift + X` while the EditorScript is the currently open +script in the script editor. This keyboard shortcut is only effective when +currently focused on the script editor. + +Scripts that extend EditorScript must be ``@tool`` scripts to function. + +.. warning:: + + EditorScripts have no undo/redo functionality, so **make sure to save your + scene before running one** if the script is designed to modify any data. + +To access nodes in the currently edited scene, use the +:ref:`EditorScript.get_scene ` method which +returns the root Node of the currently edited scene. Here's an example that +recursively gets all nodes in the currently edited scene and doubles the range +of all OmniLight3D nodes: + +:: + + @tool + extends EditorScript + + func _run(): + for node in get_all_children(get_scene()): + if node is OmniLight3D: + # Don't operate on instanced subscene children, as changes are lost + # when reloading the scene. + # See the "Instancing scenes" section below for a description of `owner`. + var is_instanced_subscene_child = node != get_scene() and node.owner != get_scene() + if not is_instanced_subscene_child: + node.omni_range *= 2.0 + + # This function is recursive: it calls itself to get lower levels of child nodes as needed. + # `children_acc` is the accumulator parameter that allows this function to work. + # It should be left to its default value when you call this function directly. + func get_all_children(in_node, children_acc = []): + children_acc.push_back(in_node) + for child in in_node.get_children(): + children_acc = get_all_children(child, children_acc) + + return children_acc + +.. tip:: + + You can change the currently edited scene at the top of the editor even + while the Script view is open. This will affect the return value of + :ref:`EditorScript.get_scene `, so make + sure you've selected the scene you intend to iterate upon before running + the script. + Instancing scenes ----------------- @@ -308,7 +399,7 @@ If you are using ``@tool``: # 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) + node.owner = get_tree().edited_scene_root .. code-tab:: csharp @@ -335,7 +426,7 @@ If you are using :ref:`EditorScript`: # 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()) + node.owner = get_scene() .. code-tab:: csharp