From 246f87f1da5966c770afa58447a67e253ecd5c70 Mon Sep 17 00:00:00 2001 From: Matthew Ehrenhofler Date: Tue, 29 Oct 2019 04:59:02 -0400 Subject: [PATCH] update bbcode in RichTextLabel page for Godot 3.2 (#2846) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update bbcode in RichTextLabel page for Godot 3.2 * Reorder content, improve language and fix invalid code Co-authored-by: Rémi Verschelde --- tutorials/gui/bbcode_in_richtextlabel.rst | 226 +++++++++++++++++++++- tutorials/gui/img/bbcodeDemo.png | Bin 0 -> 2353 bytes tutorials/gui/img/bbcodeText.png | Bin 0 -> 10643 bytes tutorials/gui/img/fade.png | Bin 0 -> 2432 bytes tutorials/gui/img/rainbow.png | Bin 0 -> 1598 bytes tutorials/gui/img/rtl_setup.png | Bin 7707 -> 0 bytes tutorials/gui/img/shake.png | Bin 0 -> 1313 bytes tutorials/gui/img/tornado.png | Bin 0 -> 1539 bytes tutorials/gui/img/wave.png | Bin 0 -> 1982 bytes 9 files changed, 220 insertions(+), 6 deletions(-) create mode 100644 tutorials/gui/img/bbcodeDemo.png create mode 100644 tutorials/gui/img/bbcodeText.png create mode 100644 tutorials/gui/img/fade.png create mode 100644 tutorials/gui/img/rainbow.png delete mode 100644 tutorials/gui/img/rtl_setup.png create mode 100644 tutorials/gui/img/shake.png create mode 100644 tutorials/gui/img/tornado.png create mode 100644 tutorials/gui/img/wave.png diff --git a/tutorials/gui/bbcode_in_richtextlabel.rst b/tutorials/gui/bbcode_in_richtextlabel.rst index 22cabaebe..9ee8cc8d3 100644 --- a/tutorials/gui/bbcode_in_richtextlabel.rst +++ b/tutorials/gui/bbcode_in_richtextlabel.rst @@ -6,19 +6,43 @@ BBCode in RichTextLabel Introduction ------------ -:ref:`class_RichTextLabel` allows the display of complex text markup in a control. +Label nodes are great for displaying basic text but they have limits. If you want +to change the color of the text, or its alignment, that change affects all of the +text in the Label node. You can't have only one part of the text be one color, or +only one part of the text be centered. To get around this limitation you would use +a :ref:`class_RichTextLabel`. + +:ref:`class_RichTextLabel` allows the display of complex text markup in a Control. It has a built-in API for generating the markup, but can also parse a BBCode. Note that the BBCode tags can also be used, to some extent, in the :ref:`XML source of the class reference `. -Setting up ----------- +Using BBCode +------------ -For a ``RichTextLabel`` to work properly, it must be set up. That means loading -the intended fonts in the relevant properties: +For uniformly formatted text you can write in the "Text" property, but if you want +to use BBCode markup you should use the "Text" property in the "Bb Code" section +instead (``bbcode_text``). Writing to this property will trigger the parsing of your +markup to format the text as requested. Before this happens, you need to toggle the +"Enabled" checkbox in the "Bb Code" section (``bbcode_enabled``). -.. image:: img/rtl_setup.png +.. image:: img/bbcodeText.png + +For example, ``BBCode [color=blue]blue[/color]`` would render the word "blue" with +a blue color. + +.. iamge:: img/bbcodeDemo.png + +You'll notice that after writing in the BBCode "Text" property the regular "Text" +property now has the text without the BBCode. While the text property will be updated +by the BBCode property, you can't edit the text property or you'll lose the BBCode +markup. All changes to the text must be done in the BBCode parameter. + +.. node:: + + For BBCode tags such as ``[b]`` (bold) or ``[i]`` (italics) to work you must + set up custom fonts for the RichTextLabel node first. Reference --------- @@ -83,3 +107,193 @@ For opaque RGB colors, any valid 6-digit hexadecimal code is supported, e.g. ``[ For transparent RGB colors, any 8-digit hexadecimal code can be used, e.g. ``[color=#88ffffff]translucent white[/color]``. In this case, note that the alpha channel is the **first** component of the color code, not the last one. + +Animation effects +----------------- + +BBCode can also be used to create different text animation effects. Five customizable +effects are provided out of the box, and you can easily create your own. + +Wave +++++ + +.. image:: img/wave.png + +Wave makes the text go up and down. Its tag format is ``[wave amp=50 freq=2][/wave]``. +``amp`` controls how high and low the effect goes, and ``freq`` controls how fast the +text goes up and down. + +Tornado ++++++++ + +.. image:: img/tornado.png + +Tornao makes the text move around in a circle. Its tag format is +``[tornado radius=5 freq=2][/tornado]``. +``radius`` is the radius of the circle that controls the offset, ``freq`` is how +fast the text moves in a circle. + +Shake ++++++ + +.. image:: img/shake.png + +Shake makes the text shake. Its tag format is ``[shake rate=5 level=10][/shake]``. +``rate`` controls how fast the text shakes, ``level`` controls how far the text is +offset from the origin. + +Fade +++++ + +.. image:: img/fade.png + +Fade creates a fade effect over the text that is not animated. Its tag format is +``[fade start=4 length=14][/fade]``. +``start`` controls the starting position of the falloff relative to where the fade +command is inserted, ``length`` controls over how many characters should the fade +out take place. + +Rainbow ++++++++ + +.. image:: img/rainbow.png + +Rainbow gives the text a rainbow color that changes over time. Its tag format is +``[rainbow freq=0.2 sat=10 val=20][/rainbow]. +``freq`` is the number of full rainbow cycles per second, ``sat`` is the saturation +of the rainbow, ``val`` is the value of the rainbow. + +Custom BBCode tags and text effects +----------------------------------- + +You can extend the :ref:`class_RichTextEffect` resource type to create your own custom +BBCode tags. You begin by extending the :ref:`class_RichTextEffect` resource type. Add +the ``tool`` prefix to your GDScript file if you wish to have these custom effects run +within the editor itself. The RichTextLabel does not need to have a script attached, +nor does it need to be running in ``tool`` mode. + +There is only one function that you need to extend: ``_process_custom_fx(char_fx)``. +Optionally, you can also provide a custom BBCode identifier simply by adding a member +name ``bbcode``. The code will check the ``bbcode`` property automatically or will +use the name of the file to determine what the BBCode tag should be. + +_process_custom_fx +++++++++++++++++++ + +This is where the logic of each effect takes place and is called once per character +during the draw phase of text rendering. This passes in a :ref:`class_CharFXTransform` +object, which holds a few variables to control how the associated character is rendered: + +- ``identity`` specifies which custom effect is being processed. You should use that for + code flow control. +- ``relative_index`` tells you how far into a given custom effect block you are in as an + index. +- ``absolute_index`` tells you how far into the entire text you are as an index. +- ``elapsed_time`` is the total amount of time the text effect has been running. +- ``visible`` will tell you whether the character is visible or not and will also allow you + to hide a given portion of text. +- ``offset`` is an offset position relative to where the given character should render under + normal circumstances. +- ``color`` is the color of a given character. +- Finally, ``env`` is a :ref:`class_Dictionary` of parameters assigned to a given custom + effect. You can use `:ref:`class_Dictionary_method_get` with an optional default value + to retrieve each parameter, if specified by the user. For example ``[custom_fx spread=0.5 + color=#FFFF00]test[/custom_fx]`` would have a float ``spread`` and Color ``color`` + parameters in its ` `env`` Dictionary. See below for more usage examples. + +The last thing to note about this function is that it is necessary to return a boolean +``true`` value to verify that the effect processed correctly. This way, if there's a problem +with rendering a given character, it will back out of rendering custom effects entirely until +the user fixes whatever error cropped up in their custom effect logic. + +Here are some examples of custom effects: + +Ghost ++++++ + +:: + + tool + extends RichTextEffect + + # Syntax: [ghost freq=5.0 span=10.0][/ghost] + + # Define the tag name. + var bbcode = "ghost" + + func _process_custom_fx(char_fx): + # Get parameters, or use the provided default value if missing. + var speed = char_fx.env.get("freq", 5.0) + var span = char_fx.env.get("span", 10.0) + + var alpha = sin(char_fx.elapsed_time * speed + (char_fx.absolute_index / span)) * 0.5 + 0.5 + char_fx.color.a = alpha + return true + +Pulse ++++++ + +:: + + tool + extends RichTextEffect + + # Syntax: [pulse color=#00FFAA height=0.0 freq=2.0][/pulse] + + # Define the tag name. + var bbcode = "pulse" + + func _process_custom_fx(char_fx): + # Get parameters, or use the provided default value if missing. + var color = char_fx.env.get("color", char_fx.color) + var height = char_fx.env.get("height", 0.0) + var freq = char_fx.env.get("freq", 2.0) + + var sined_time = (sin(char_fx.elapsed_time * freq) + 1.0) / 2.0 + var y_off = sined_time * height + color.a = 1.0 + char_fx.color = char_fx.color.linear_interpolate(color, sined_time) + char_fx.offset = Vector2(0, -1) * y_off + return true + +Matrix +++++++ + +:: + + tool + extends RichTextEffect + + # Syntax: [matrix clean=2.0 dirty=1.0 span=50][/matrix] + + # Define the tag name. + var bbcode = "matrix" + + func _process_custom_fx(char_fx): + # Get parameters, or use the provided default value if missing. + var clear_time = char_fx.env.get("clean", 2.0) + var dirty_time = char_fx.env.get("dirty", 1.0) + var text_span = char_fx.env.get("span", 50) + + var value = char_fx.character + + var matrix_time = fmod(char_fx.elapsed_time + (char_fx.absolute_index / float(text_span)), \ + clear_time + dirty_time) + + matrix_time = 0.0 if matrix_time < clear_time else \ + (matrix_time - clear_time) / dirty_time + + if value >= 65 && value < 126 && matrix_time > 0.0: + value -= 65 + value = value + int(1 * matrix_time * (126 - 65)) + value %= (126 - 65) + value += 65 + char_fx.character = value + return true + +This will add a few new BBCode commands, which can be used like so: + +:: + + [center][ghost]This is a custom [matrix]effect[/matrix][/ghost] made in + [pulse freq=5.0 height=2.0][pulse color=#00FFAA freq=2.0]GDScript[/pulse][/pulse].[/center] diff --git a/tutorials/gui/img/bbcodeDemo.png b/tutorials/gui/img/bbcodeDemo.png new file mode 100644 index 0000000000000000000000000000000000000000..c2f0ccbc96f002cf40d24345745d3e081fec3f1e GIT binary patch literal 2353 zcmah}`9BkkA0J&0a%ClJ?u|T%M?=nGn{&*u9FwO=ZHu|DwJF8pK5`_vwH(W8$Y!~c zW4Re}EJt}z$W>CF!qfNr4?LeA-q-8>>-&@B=wKx(3=#$a0HQY5NM`^*0QO5~{C4OU zBA^q@UvwC6Zf_0%)MkkM^gi;-3xqmbSpc35f|mh+LjXrK7G-a5zqGW3!C>s{?AF%S z{QUe*pXQ>`=$9{F8X1L)iE(Uf?6kD9PxVYx#W`BQwUtiyjj*iI4NH&}8;oLBSukwzk8=!>+EbBO@baWn~Ty4(aLXF)=ZN zgM$_pZr$D80s?#e{r!1)dF}1(nVFe(b{JXNCPBenA0MCA*4BZ6fz;I0h=_>e#}{6` zdgbWo7#0>56cps<=Jx#g^RBKg5U5>Etr!Gq+uhx*sHkXbYa^4%0RaI`O-(g5H4P07 z85tQNAt8&4i!fNYu<+9Q`Z|R|;c~g}-n|0?%RN0k@p!zYC1!PXH76$r3Z*M3)MsU7 z5eS5ml9K7^>9n-8&CSi&*jN`Am+b89(9qDwj~^3>#EFTCq@*N${o7kxTlx9CDUw5I78lRtX6$tEiMC5EwX|^y$;5g@pweDI~NiE#0H8eo0X=EIK-Rd3hNE34uUT&YmS*xNucp zKY&W5B9Rz#bFaC%xwB^zWMn$6tuZjzH53Z1to&?pa?-%yhOseLTDm(iG4b3vsU1)ON$^SH6kiHf96cSxj8{mG4t55H3;O%`ST<_y&xkayopKh z{QSJR`NiLVFN8viw6(8_iOuTh+%hvGg28#RvdxN$PY?*Kib|!fZY&(`DkD>_tsMvi zKGD^U0s`q~W>_ec0)gCy!>=t`u5AMVM}};W=GZ9y+GM0-b|m=qR-OX63V1v&H%>w! zUew%7LG472m!*5}(IdV4HxUV@+8V26 zR(JNp*E#*3(4mBFDY?bOr9QoZ zp&B_9Z3>kg>=bq7luR{P%y2QP!17|$+x>mB%jfT-S}B8^soRny>V~R(5ud#B-FsaY zIKWNrn-4M2b(n&I=Hk-J2aftO#PhN{mc;gRihStW+NTr4QMH|Tcz0K^He6ByJVA3J@T&!4$k~saXqUiV~hDLvi3}##Uo9_TDptJSm7#-GG+fs z%$Acc5jgorU>sr2f0n&>!)hy?S+R_P9pC~zYfHNwmTYOH8%|Tned@dIH*`J=`n~9Y zKb@!CU;L2rbmrq1O_NfO9QpaiLd)})R8lkw&*jx zUVcaT%zNx5vAs!%HZCJg^f?m7k7qT<$arjQQH8rNs1hIO;m84a^#^`9ND6e6Y$X1b z1Xh0B@Bv$(B=o?qy8n%r7FRXEpm&Q}{cTA~8QBER2}789}9;+h4a4qh$MO3Q3wz$skjGivg=3g+!>63f&MN_)9aZU zLd$C6EafAgmn(^-{JoB70FR4n6{Gm88Sx4W@SiJQOym3T(fNxPY& zFwbm@I5sqmjh0%Y`oD#=uWTS!^Bf*U&v|8CL4V{~n6bec zxs@0B`R_FoZZd*bl&=!9?Ye?=;V5WQZno{Wmgo_|@OoD_P@0fG@tRa?Bai(O5in%O z{5W0w#k7?7IpXwz;lq(8f(kLZ!RpK!@>}B@+~^Rzl)5HW@Mex5Ueu6 zx_;8E{HCHpSP5};=gFZp^7B>pU+;P+Mp3FguCJ}B9<5F*1$qV-^Lnl~*y=WAa)vjB*~AxcFO&PJH44cC>B%D|uR2fS z=d?7Y3nve<^l+GAmX`PioXEM4Gz#;69a$|bBI33-Q9`KmQe>Y}(G>lY2+JSNOl9p$ zeXRQ2gUecXUpbd7hOf0P7q@kBzApCLk!>aH;U)KrQw%TkBh=gN@LsEe#Kj|qs+>yI z)_|`~=3ZT2SiC=H$NjeHP85uGQiT7H@hqkrQ}4;!YB;a1ogt$F%b`0|@GM2sbLCpFJAr@Q3+yB|UugI`aJ*&2-Sua;%Bpo)M$-Cul6P>=U;CB( z)#6dh)!%Tu1M-i_@W6WntBiWpbDuEiOLVx%D@O2*TvOXSC!)k$PY=- zhp=}K35unpiX;Gh{)l~RjQSvhTwcpb0hJ@v+W>$Js3}8a7}-QjES&D8rC-Xa^S+Ry zpkdZCdP~Q^%`5T>Eb}HhCQ%=1v%I`qR9q@0_qy<~Tv$TI!zbM8t?SUpINu9753hi{ z{Gx#12qq3OQAt%ELD`!6=G3&T>e{CKf?{{C5N5U)T>R2+?cLQNP$4lTFTe2Dn#S+F zgUYMwv$FGGf#FheZ_KQmZ0y{O%^lczBr~#dS-B(xL=@69a+K8c)ig{v`J`0T4eXsf zHFV5aIK-`O-E#8^pRw?ZNGQ5_!o**yNh@f&dWOD~hxqx2eTa-p$;fwbexI3@E32fX zrDtL5=$Vj`-`dt45*BS?@qGiMsp;7Tg(YvaOe3S?!y^;B`-Tfkss%(9Gct2OL?tC8rDx}ry;Rh9^$0LD zvDGoK92)xmoExnA+OV#^QBwA`tB2p0uWd;w8U2H!!C|pUsks^1#qf^ar;L33!t!7l zb$JzC32F7-{*mgMMk!e}-@s@E743-V6faY>ccUz)#lLUiBi8d`@(#3;Seb$0VNwe~0}tI02_NJ!4s z*0)l5WB#qZM=zwOzVRE>%D^R zaI~z7;m6oSZ9{uUS6_2$XC6T*AHR^+Z|!aHjrBGaZdAN;ZuC&Txt{V%_C)GXy(eqC7rWb{INeJZ9Xq{B+bs* zf9%J&fP#&rUa(Qr7}Ube*w4Wtc~uM6Y8*4kE&>sgdZnnLXO^&_Y@015r(v7u0urD;DH9x&`1S{F2t)r(I!LbZKkQ8<9o_WDFC1Y6r?2~9<%!knEJ$W--M1f ztBlc7b>u>Bu!NAq=sf6>b7Itq30`avATj6YKMi-5MKwX;?qT-GStbmW6aC3+!)K%1 z5=Xwon{KvrU{PiEeXnNbOY`CWP1_~n{?oUjW=pj91R?&{la^n$D-W`ieTvIIdHHJM z9?x?<>t|N%a{2M()pvz3Nrs0_`iHoT-!qBc(nO%iyE@8Ka|64uSab|BAVWpt;458I zg5?r1YL3l$kDuG8VFGY5R>m93V{T4T>=~1b;5PbJ-A+Cz<7K%n{v1(PWQS(i z6$i>PwS{@1uBjVPntUKSBFxm9`fht-v1-h1ZBgV`4TnM@ZR_P!u;4(!kKx{LzPsg+ z-)P^EG|vs2u6=h{O63kyTQ`1#R?`D4)PN^U7Vq74E1p1@?7hn32*H-g?pD&dUo}7< zZ>-e!=zVTiO?k%G_;kD2lfbhE&Kix)UhUrH7m?+F40AvQWa2gm47(+8*)MMR zqH{unBk1uPz-dAu1i*-ThlkWSj4VV5Ze*N8&tJE-*MOnMC~{8P$G&IlnJd9E%Vaox zTz8*!s~1Aqhd%7FU^fl`FAUNY`I~k~8kbA3meFF%k$fy>utx!hOm>NS7EHkpA30i% z2m}KZ#K| zzS<91eTJBD5kRYdEW5u*IgdNivjDYJI~h@R@grSM9!APW?coA979wkVlfWE;{_;m) z2y6K(p?oKZEA7$W8UK9M6l58;KeV^b2HS5JCnYa9&m;Y$?dp=Q24%z7Xmuj zs|5wMUg-=<+_%ibF^l7z`x9IhiD8By3Pa^~Ib{lR=#L{!*hll?^9`f4GkHIT>9_>F z^OBZZbq)I;N&X<5XEVUzKoDSQM(Z$^?DvZbIT8BWe$vU>zVggNYLt5`d!wu6U}Kg`mk)&Eyz2C!%l+Y zTe1)esP^NK<(vOl-+v1c$SLwnb-%~6qd&)G#b?GV9=a+OULJ;luC}|v?=WyoaQqKm z1bW6=%G(RYd{$&k9MB9eL6YdkNr0Oa*7V`F{akf$UA*CDNF~L7#Uz)+X=v*UESbO@ zWa>d?Vss!%dvV`fQW8XPukhhr$8h?qgQb>IqA+dS5Wr}S^{Aq}xL5+vw`sy1MOt?5 z;#YG>p?tw{J`I`5kd7kd^rhw8j@@W;_{Nf$#IHs_Xbo$1C@8d`{e{<-FPEE64vXB& zYG3-5MS%j>GM}I-l8g2#5NAEKmMBJr$|iAgBwZ9FzWJk;F18`KFxnue`|3JhcZB&Y z7HAx2k3av3u~UH*QRqHGlF6{d#p|3wt?C62{iCb&ioqxAOnv|vzOACaST(BH;70sA z3|Qtw$Sk5;fo3CS-_WYROQI0k_a9V^;$#G+#BRK{#&5c~2E3@=dr>Xrd|!!_5>x_4 ze1I>6qL-_NAUL)ZU}N^ehUKlh!wM*Y%;%fTZ$^BW_*5OB-1n9MD50i37ti?wh&k(H zz$4j`4Viz>+7a>BWT0*JOKEW2;Hr{9qxt0kWINbd`)9#YLFJFsWJp}}gNMX^3=8S! zr2IABPBVJUVwwoVgkUK--8tI=#*h5bVajEPE8(m32C}QBJMQa{?btP8;H>Y2%yIpE z=zx8_&v~ALb*?a-GGg^T7x)#oA90g4Nc`o-y)uL(NBp*pdxQ3QDJrOr97K0FH_h61 zmeBhK{}vy)NZG&F_}`B7hgk;X*?62l7}&~xXOp5VdtI)5JpBCu-NW}{n)N=Km1lp8 zmd=wz@m<#j7Z%j?C&6uUKUsT~P@aOuxw*T7!ez3?Cj{sqF(ILx$>KRPY&{pCGeT)w z4J#`7WPe-S%=*a>rg?E9ci;Q-<BrggKvAY^O<`&g!UlpXi!V-!G_w1R&qEz`em9?rZrrAp>tb19IV0c&Ao z-0iAJIcI7JwyC|gjNuG0iWF>M=`anNA>n!i|N3$O~*G~jK1FzI^T{Q+cVoqF6t4VzU@ zH%bp@_S^tN7M0DrH+2uwBX1rKEuKvNzzQVS2NQ0eLP)0j z5XI@5LLa-L)bj7c7pVRHL2kY~QL~LI$6pLAPJtaMeU0ZPDdj}sK3^(!rRryHdHcwo zP)V{j7mV`@8IQ}q3ten3EAogybFAo7V$67zVf1+$1)t7XXOWTQhEPOre1R^0SR&Ay zu!gFjMu~N2r^x_=mw^1N7JkZVS~JY<`9=S^rzUKs$1FV?jA=Xrd`Ae`9s@_g7(k>X zpoAX@wj}@ncnv74wyz7dy377Sg5g7XH;LXj*Vot2=7Gv9%A43|;FLfJ0gS>XSo0p? zK8SX8^9P+8ugULcg@55}$|!51BBCjn{cS}zsoQ=cXYaJQzaR3?&|9H2-3ZVg9QZ4&7C}kULZT>39;AP(hIj%3O(6v9iPYlF&{w3VNu^j`TFWj;rA==u>UyKoSP3kN zMs;0Ny*rQV!zU&q1~1k{u?d!1h8?W^nbwt;ySnro?mNJ=t$3Vv<9P38Ao96@NNtnt z!IzRxV}&l{g&gK4eZ_yUsOA%rV8GeuP23|>Z<<@}IqV_pFN{l$x4CuYNdyMK@Fsn| zLb{!IwCn8j{N?D-V&)|5FehQaExoBOFT|Xj?z7NtAN&4i3q8~l{QF+zYxYAO*tg$) zwj&#%f1}VAKK$(1GycAh?;lLkCV>6?v2XYi;A+=wG&#aJMLN>G{-N}|wF_Avr%UAL zApbVuo>x~{2uO-ZiN^8;i!{>JY&i0f@Pa7cM)vs+wlfLNF+g(ecqHd_hd_wWM~_K5 znESSj#!~-__NO4~F3`}z!l)=@PN|qiPx&@;9eAgO5iS6)qFgPEEHhmR2#|=&h}2tXi(hzarCje zibF_&z-H3!oa0RL)%3R`b1%2&Equ}|N(8D`Sj!m>)wmvZ@<7s546TpF@ar+4?5#6K z^M;wEsi^66nQw<~-Rdu}{ZJSdIJ-9EcHLlui2~-C!WlMOy$hyL9rDAr8$K#P!!rdA zt~+tK!tA+-eTE7XA*IDH+`4#yMl*lxKHOmMv9oQ&iMV%Tt7sMoE~hNBf!)~Tv#kiZ z!jy9oXf2FcvH&&y+69#D9bQqX19|l3Fa4h{Ojl%6^XrhoWe_!Dim~g^Qf9;5Fkp|D zl^#=sNjPxEc?EF%{u9)fA>w{83fj}%ky*kHLs#2abN|k_bDR}R419yTk7~eUc~RRZ ze^7YCYFRzobAU7e8u#@MOHZvt!fFAci=87n+A`q#W znXOMM8ita)>!C?gyY+R}L42y8{ia|UT*3ewj8ZvtRAvE8SMalp(Xyl*ZM^KR4P$VX67y%~yAs6qT+#HZ2O4lJPRePaH3&d6{ zJ#~3v(>Iu|1bPS!7zhD{uyWlh1E)nbg!-&KO1*9~%J0Y<%RB`~_E4&>gariMTYWX!oo@sN7G7cEc z3!Mle;0G`UD1k;l8yGU8(FL{!VzH*P1ESb}rU14L^5vSh##aOYjfb1PFwW;cb7O@9 z`g?xhEkNF{Xw&ietudS&DkN$vFbfGjb+3YpoUpL+UDu}f*D8AgZK`Vq-V2cr$nqb_ zfn|+`vzy*1uSDPC`-^x^@#}FTKYM3b8tT=@x3b?JYJ0>088M%Ifri_aSDn34`Gfa& z?)O)x5{rn;+ENhd`&HUNoRhL+^R=%Kf)onWA#^BGxAazYiH<+EkR+6~Qq&)hzPcCF zq)QYQoZXMd1xR?_kkol^xZgjIZMj?V^Sdv;=OKYDXi)FZET(=BM~f%qvLLPoV3@?; z=N1dxj@D89OB;Ex;nYlFgf5^CiTL^!RpgeFUi|*HwmT${_dRca_Wc#_8&J?!5hBV< zY7}^n%M3w|K`0(T!;IH6R=dosN{~V+GK4hRi)q@013PSV3Wr>?z_R_MNUj94rIi*D z&vma4z7!!jX4PkFzm=l{1hSNnxJ(030oR;65$cvpxxN(ip{s~M_+AP$qq{TzO& zMDfN~lKx7f2%Rp;OEw0u6(vLWpHYVkB}x}sr3Hv$zi@ip7QxNHlGV`BSVI6Nr?;4c zai*T|E-aHR-Gv;Wso+898bXkut6$CjERu2&V{szlMyl~10>81DV0$j1XRNP-4knFqPc z4YRajS}^xJ^`7p@yHKxC0Ipa{S#v@qQtKKn^_f#9x3PkZuDIyssif4q`;|pYbdO2X zk2V;C4rd8z+v{pVZoXC)XPo}OMm4HgL03}8f?RZ0sQ}M{aC`_Blz>->7udTU9ojNV z$T1rU*;ybb^BTYX#ZU) zf;Z5FAl|ffX0etk9$c7e3X5FB4;@b10#FO< z6dg*7q>#fu@$Luu*G~UidcXmHz||zs^#_HBuqNma=UiQz!3y?aQS7~y%9}tL8*5jk zvwZ<54>=eL=jyHxq>4>S0n;f)R=$N^PmDc**%YG`>Rw-VJTTR1?YaJetv_HpRP~JB zOpDGP$vDCqr8LE8B(7c>W=d=MAaA3UrexdsGCzK?JCq70w-5dYaG>Q#@;%;^7|=Su z>VMhxe@MBeKxWLtz0XgN)69`<3#S@%+2H)n0{ug8NwKQWDOq3xes*OHNXm(3hRMN7 z&sJ)7Q>{9mdif6pdwk_0YLW!1)nG%?EjV9BSx5cn{AviLeI!E}+ya&A7M34jw-Pp~ zE?^jh>KQAc#u#)z*J3|2#&}TrKhsqy`_*UuKh1FUYI>Cm2K>_^ftWjW`lf6;HylN8 z=l&%woJHahxem}hAwxl?6@i2i`&Q`2dw=w)n28!tRa3YmVLxAXCUW;B+xxgb8}ZwP z2zhx>LmU;ato4j-+#{O(Zm($_?nh?ofD32TdI=uy zq%{;Rla9A<^O5?ad^oWIeX%m$fEoH<{TnBEEvF`Q0}&}3)L$LPT+toY08(E@5jb$W zzOOZUlDKqNC4F)cdVhD9jTqzuMy_2-?p6w)U>QN?_pyx{m>wnfd@8>7It2wJ5fzrz z%L&h@C(Dn@oVo8vnVcYX50#!qAz|DrPn`(k9u3e+JiA9+V51z}eShYMSo^L#j%H<( zR3)3ei}RgpC(r%qkt~L;VcjY+Tg9_Vw$aD^K)Kw{m@k&_$Pyr6nhu{7ds)O@|EY#A z*7C1xHB`hf(^%Y>`wyDmZYsjxgDfYf5|4wVeAAJHK2XUzn^qv>(>1`;)dp{-=_vq{ zU6QA{#O9o7;tRC29i z`2Pd>GB%;p*h)KEw48(Mv}E+_5OSFB%btKOu3t)H?jw7pVo78+4P(Zkc)?P+q{yQV zeJQjwo8IgQRa2)9d`$@*GTX|BQqMi7d4sctakBu7_%aNWS%{5Rz?<|N5?AkPBZ%*) z=$tbz`{2V9X zz#(fXk{omEvo|NB0}JLBq%>|@j!sTGob%nbzpmOy*Cg^Qtnc%vZOD8xOWjx-k`x0=NU2R zD4!l3+w>9Mvi)cRkeAsrQgD$+_!|0rWI979ogL_rY>(SLe5K zPxS@(h(CK?M8EdipwB zh;F&T=~aYL%YPed<}UZgSQq+EUEsHD*f5TM>WWqrsN)CCLUY#=M%2bu^@}B}&Q1bR zynp`5Kv2(LQ~dAi35-*^E7%+T>k>}eqcDjLR#2+|UP zlBAz!5)3?4RHVdeu8uRd`JG*p5gwJJeLsjZS@KGayUrfH%4(vw(OgDSJ(^BguDO;C z%`e%#wE8weJT}2)@;-ck-@z+>wmqImRDiM3_F-Fky&&1BOsXPOB~-zqw@7M`b_9uG zr3i-BO)uBX$cDZEI#}}h9XV_33ekUZ)RPQ7VdwcvuLuieV^^6_rQUKcjuN$HP}3dH zn!DZnGz#x91XKC4qEC?i6efc zw@CdX@2^41BAuRKZ&5u#5RXX#hh^%u<+rw;F7gq094}qT^EwG=LjD~ug-!o)Qt8lK zvVVLP_8Altzq&-K#39QLwlXPQV`J(DBn>jdn8eg9{Pg1AqkSdtY&yETW;G&v6WLfl zG`o=h9=}gCJ}rri{doVJ=MlX5Ebr6ddd4y+ph?(kJNF?9L3k#$zTF|{Yqh{ixN*7A z>FXk78MsJ4vNzST=xq3urHtzlU3Vr&v)2>dJ?y7plZDX-;~1`# z#T2f)*C8O`xj=?P=9^~_aEhS~UVS5tHC@$BknBl7rDzDL`0)7+1#nYm6K+;nL&)GQ zK$e4Oi5)Z6_0h14zI@yXBG3fgaU1Ux;vi?J|2dO?=gofp)mxCC zTlYj1Noe-@i%dCw@8*7trdP4}KFXa~b&l#bi!$N1&-frD;N-4N4Os+H>gy)txo?zC zY+2jt&6c;DE41ylw)hI07kDKjdI)6aG`t->Srn|Yf)#`XpY z{EnLu_j>AEkUJ}_us}S4yGnWr{_y!;dBj1}->-?+_;5YDZ4@8G*4H=v;k`Id$si5; z5PFV7P#y5zq+{q|93DSZTCbb+0fo!hi5o(4@PP8#F91Me`12N^us~v1d7|YzyQ+#< z$&-%?T?;upx{vm2i%Bmd*BPpxvY$ti9pGPn%(V1ZzTh~{+0ypxh~4^(OfWG>x|=dh z?i{$3;z_AbR67#A(D#k)pui?S8+C{*M`&NvoA$4*{16-S9b)>6g|#EqL2#~4p5jsX z0OyM4UZ$N2#@i+*Q|A1OxSvsAdsicw%}YcHmDZVZH9OLo5exveRD_pIiL2m&z@f3C zhabLy+xdr{a^&Ex4}BaqEys^%4QgJnSA4VPLmtv8lHJfv8Uk6_l*j?r{h!0@L;Hu$ zOS6A8pT5U;pDN^!l2{jLu0_b8#9TgO`&Mquhs-vonX9Q~tJee6k?}vLBF0!2pZ!qA z#4DkuJ5C0V5E=W?*;}|^bL)}3`QdnHGwgT`JCP%w9DKLk@Zp19_NN(v9NzV=_DhRs zhp)j6_APQ2Jv@N%fS=r8)lOM|TPq1OJuX9`4c`}#JXp{76D|fAbrWgGwumZlh7YDl z0YfxtL{@2%_T)i$K2b@YZw%V_(uYYLleWaEX!sw`?3U0I4{J7J%{y9GN&hO$V~t4^ zoqF%zIDHiqSTg3IFewnQCNe&MFs!9(88|zxgMTR zh}6z=A>m9$I?HPLBYgj*C#nIJw@jdVz>#bmQ#90S-a%X^dLe4w0g5@?i~D%vp&Y=? z;%hD{c{IgFWGms$JyU0jBxrBQ`K32K9}e$8>V7Tk>%xEhwBge#|BUbNB!@N!qFUtH zG5$MS-4+Lwz)XDen)t(9$2j#KTQOEaJkiqVSX&G;zoe@xhA-p5BVc;V=+A|k^(u-Q z8-V)pu=2G%`p$0d1k7f~V#Tjz6V(a<``_hf-gCG&fPo99d_^89H&iS?#(}4llB~az zYt7gRm#3MoQkf&R&`P)dT&lBP4X57osyjZ%`NuTVM_?X{cx~7{uObnELj$)epZ*V{ z{}%!j6W~eMTuZ$680G;rynd_4PP(kiXxQIkkqhWm#Uhp5{%p{F3Wq3czSC)xe#Ft7 z6)wP5L)ND+KQfYqxj+YKGlMOj8iwduk!->DC1x=4zU6d2YHnwkwRa2;Uc@jcwhyZ8 ztf($T>Z@E$EF=BRh4P^EKPPQr*zByX-5B7C^#3Yh-=xw2 zq;kvef*VBb(mX%eWRri;K4VI-EWw0eeS9BvKiPF(P>aVfM)q=VyQiEbu_Wd@S@Glk z+Rx!{9$pg(*!Q0gznk^Rr&&%Wx(8R>wuQG9Xo}0XN*;=|j^MI>$d~8tNT>E8q4^~B%^%e<~5rnud$c&YaJr_1I&9@OIb&i z4L9HE!UEGN0K_-$DO}lt3pYLVg&#Q~999>sMY)~8r5#wN2p+tCxS3?Y{UkmyCx-*M%X|kHW)~6#E4O&Vbti5 z?lDrjYcLwl|Cj&gdq2GO{67Ak=M4pEDqp|Gca4RGbGo=LZ)F ze3zeWUTeH&VJXJ2otgdoJzsGHD=V-R_TE|j?hiofI!YQE8s_HaP$(1(2CJ&7LLd+| zH8pj0bxlo8EiEk*6O;Gv-#a@yCnO|TSXekYIayg*X=`gE5Qu?+0Y^tiS6A1dpdb(k zq@$zb;^MNtzK%wt-Q3)ajg9s6^h`}n0|Ej90|Udu!*z9a?d|RL_4RFSZ7~>(nVA`Z zK=|_I3z%y( z!NI{kK0Z-VQ8qRJv|;C9$8sg$;ru;m6a(eDI+5zR4VoJ=g+mZwYj;uEiEnY z-n}a-DncTW4Gj%mUS2R5EFvNzGcyy9$NTyDg@uKsrlzK+r|0MAXJ=7kVGPtl$0=;OkZE$-rnAhj*h0Lrlh2#ii(PF-@XBXz}eYZB9S;WG=#(9 z#>dAg6iQ!T-}Ll!XJ==7d;8Yb*2>CCRaI3+M#kji-JTHu9WostQ+mGQy^ixKa-g(zpt8Es=vx^B`Z2B~GkGJg&Z z5v&dgWmG8L#IIZ7bDeHM!rUAMq!Yu><232eC0Ut}8LN@`{K>;mk4oe~Xg+U!CT`d< zS&|(S$sRS;_K%?9QB~*{@kinh>sq1^<2kk@RTS&$AM9n&d&%9=h51~pp^6V)#B&af zx_YJDF35NzD`yOOtE?{6c5WQCVh{p$5!6` zP3j!QsCsT{2?=$#LdJ;6Q6jw;fDZ5Gl8#VJoV+BhI7rUp2t>Q;M z==-U#ts=}6E?~?*5o7I-6B@73s8Xq(u$ogjxuh;<6D%OK8jhz>Z|EI}im9T1v~bs!Tnz>nFEtac+PL=?9=C$mRk{z&a4Yn%%)!-R z8aJoD0+-J3_t)2c`8$gy1wvqf2v7&N9uAepb_sMiO`*^$MJ(5h0ZFe%t+`4zHV-$m zTh*ueJpD=K5{xB;@Dn~JztXc)U!x&IK>L=eY=o00`b3$T=rA7APXJ#n_x-4V+a0YvKCY@)`d1 zZ&PBK4zT6$?3E7AX;Hez!SIbCm!t%Aqdns>8!6@5OLP`gHEQDi+sfa+ZH(%=J|pTr z@VYFXp2gy8PF+dH&x47Fe z6~WW}vK+in+AQ0!I824)RW)Fpq9N@H`1OUi>kwleyKCpa)%lOr67Zd6$F6_G@ylr% z71j}b%z>F#Z}b)+Zq)E{n|U+OY%nzkcW)t%(7h^YX%OCZ;&y^O@(HNhqeomB_k-P- z5F2pP0kCY26xh~=84sKLU$XC90v25f`_00z5apc<<#cf*ZvDcN0kG`x%o3PH9wnml zlbq;fN{=Q8rP%3)3<|IZH8U24bdrbW7IEGgdKUdjwpd+ANt$NS+A4l;A8wJ;uRqmq zl;k@)+#1}@RqM$q2{{KQjLDhJo3N5r6BowI1*8dxKoxR*q|L2Q8{?OTFvY*3rm@%y z%JE_Yt$Eq;G(+lDGU?C4zFKp@E9K_hubTe8sbBH@AL!MC9MBIOM8NrV<&?a#pd5RO zCvJp9^EUK zOp9$IjfWrPa>u~u25BRe_?Y9PfR4u3+UDWrjH0_1J-}#)C^4I+X#tCBgp78j zF5(x0B!X4~5D;KpuklPOzgWy* z_hWn%MvGjzmr(6H*DVX6dDL?Z3OT%W+93x49|w+z;S_~k9t@@$&~%ID^V0#!l_Q;M z>uc>Ia%PEb=KEUBqu8!OmTNd133Mn9cfHQ!HW+;XA`#PwXW1xt1xQS#?dbEdca%dR zaN~wTwq}YX0Z0Zafl}b}Nb!)tK!%7w{b{~74ngL#MNXnH=*VGr1=s`YIN02V;TkhZ z1nvfF8Tnb-r2>A|^IL#w;66GZqgRYA)gXK~nqZqkGYB4i6i~yW9_9q)1owZ0obO7j zu<;xqMP{J>+#(?=-Gx8!Bj7&-#t61i{cQ1qcCkJ31bYk#$~_A*G%t7muoO8eT=If}Ox@-H(d57f&_ z?ncR4FRv)-V2;)u+$1^^>8vmR&^K`QNVzOa5prQ`?7jg--OlPoc}-K7-6)GqJ}}9C zlMi!zO>XKbCx?>AK6WGf^>)r%%Ti}EeL+^z%bnT@Nz%8O9qa05SEnCdYH7)_P(5n*dHr|tYBj^C9bFVC7_<C z-MhWf-QMI)jLL-w0jC;$Ae%A4P<+i5yY)>NLB8`>X#zNzT&Rg0-**Be$FzwXOp zn%P(1KSeKIdMRe6Qa2$!VPDk40l)7Phaz9r7shkLQ`GDQS0fqAmW->P6jVIUeO73A zYF}60o&%4M?|GH~!I{CTs-X() zlib`!tLSov=>6}%Z7LOoz2KBIC#fWlD}_~=28H)jmE~!j1}5r$kDz`=muZn#%LLh~ zz=E=jbM-&2iF_I= zhocg^ha3#1zcMo{JG>*Q`QiKa-7}(V8=EVwYec2T7Z^=+k@qA#WmOflmChK}{DA*K aO3K$UH$1X@Ww%pqcxYro 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 XA<=b-UZG}+00000NkvXXu0mjfO1G=` literal 0 HcmV?d00001 diff --git a/tutorials/gui/img/tornado.png b/tutorials/gui/img/tornado.png new file mode 100644 index 0000000000000000000000000000000000000000..b05e9d1f5f26afec57966b481b5474a93b2609c8 GIT binary patch literal 1539 zcmah}=~L1P0Hted%eJk?YC7Cz$F422Y}QKbT)R8~0gps2#S1)B6a@tFOwBvZgP(a| zcmaxvVk%jRS8581T4qWfh=L-aVz%r40XzFXykq8leDh*qkbAp#9^MH8fp$N*ZvqE_ zHl5n=^c`C^ctU)raznPd-?F#`0#zpM`tG!CBX0_T-@6TB^&FLgK$|zg%#n92EG#~J z_>hs20RR93fryETadB}mH#cu=Y{X)*5C~*)a?;Gq3=W4|T3S-6R6d_yUS1v%5z*h@ z&tx*$Y<5FK!^@X1-@JKKUthntxTsJls;jFzIy&Ow;-FCIz`%g7udk=4XINO+`}gk) z3JP#IoV~q$XlQ6^YHDU#0w#j|J6+}+*DWHJ(ojE#+DFc|sy`R(oP7z~C&q14sYiA18_-d>?l z2!p{&OH1?e@-j0shlYk8KYslB_3N^-vbMIickkZK%*+r71REQh$jHdRz(7}5S8s3c z;NakvmX=449xW{`ak*SP9-o_=tI=p$TU)EDs+3A43WcK4Xm)mX91h3d-=9b%IypJ@ z^z^)a`?jQ{Bt1R7xVShZBt#$(jE#+DXJ-cm1w}fzz>>eZ`<4)@$n~5p3Kh9s@3YW zw6yj0_2J=RnM~H*-Rc9+@8+z#o1H z3R|Rpp>EyLd?G6O*Attc;4#LS@|3$H^1)G8nM^KM+Q>iU$gk44IibTbxzc4~82Hk{ zg|RHK{awqAmHh|wx2?%rd1Qm{c!sheIb92<;e+)uGuZaA(4dsBR||iMaB`}gHtWOW z8(biL!_rr1)bqVp1`PvbG7V0WJyQ)gR)u&oJx_-uT_{EN_tzR7^4=>czC2;7{(O4X z6lWyCU1ybI6SWLI74#z!&47Yp%;E0WYErX*GeQoftk9WnJp$XA#$sEv?xo{`@icLH z3|P=~^>?EpK>K194@**W)kf)o_bB(rj$!IXM?>d^(Ew|5Sqv=26`ZZ-0SR z*6ex3cqi@@LGn|h4a%@}t`HM29FzmEpFL`Nq zZKmjFwDt3hAihx6Z8%`w3Go#7_Oz9WAO~m73o8?K9J+<Oi!OjO#&+F>z##oAv2i=IR=ln(aZhcCCCtgQ@ zuSs{$cY|wb_>>4cg^Oyt#+$nz!!|~&$24JisLMo1sGc7`0O|FomXGV;I^{t8BD2bD zf>3`3tc}8oAP!B;!%RFj2Lls7_K&AWYjKAYNX?n=40*c ztCEsGy75@1HUPI+3(W2s{60%o0dvoH-rz*a?5mUnxQ@zKcVGOmfw)2NFT3IG5A literal 0 HcmV?d00001 diff --git a/tutorials/gui/img/wave.png b/tutorials/gui/img/wave.png new file mode 100644 index 0000000000000000000000000000000000000000..b08b3004c5d006483012751786402728f2bff30e GIT binary patch literal 1982 zcmV;v2SNCWP)Px%5Kv51MNLgjP*709!ou9#+)GPKR8&+?PftutOioTt zNl8h>#Keh-iDYDCN=iz@!^60^xL8QjU&}=jZ3t)YSd`{n63U zt*xzvg@u`!na9V+baZsHv$I-STCuUQq@<+3zrTithR)8;-{0Tq>FH~0Yn+^%r>Cd6 zxw)gGqpq&5Zf;5NgoK2hot@_9=E};-zP`SYkdStEcGJ_-Vq#*csi}K=dvS4bkB^U8Sy^LaW0aJX zudlC2NJ!Ao(0Y1$Wo2cXo159$+2!Ts;^N|$mzUn&-lnFe>+9>w%gd^&s)B-onwpy1 z+uM10d4q$4-QC@Fb#=A1wV0Tgb8~a(=;&!_X?%QqprD}P;o;-sgtk`lJfHM*4Eb2($e?$_wVoT z+S=Ncm6g4{z5Dz7&(F_CM@RYj`QYH-*x115wjT}KH|GgC!;%=jsjojNrojl7b3yln0LCkLSyzhP)kVQXvWZteMrzU-1j zL%2(MHRVE8F8{tkD-qPL#UtCoS!_O<<{O(Ai$+aE-xV%zib*VesS%34Nd0q3^-xBv z3j#}D<|S;Fl}5cp-h4H0$DEVX$P@92hEY^^vff>=P{`Ecbat8OXTI_`bKMmd33aiH zsHt??WuosS)Z3XbhsBzz+LaLvNvM!GDFbcR09Aa*)zuJ{Ty~Q2T zg{qzCx-BB(kb_p`;vCef(bfp*^G&+u)2p>@#uf(SYGijcDb#&=>tPm&d|azTttU0r z{Zevx-scH%N1*^=%KoK+DGa$BfnEXK8deq+YTj*QW+Qikf)FN^D<%*ok;Iq?2|sQ6 zPOs*^{424tvhn_x-lR~=l3G8LM2<706_^o1nr~v)kWaU9z%D5mJ=ai$il`8;Z?*L|In1bDtOyf#LabUXRdF9i85fD>1-Li3 zVkyF~_9uTQ@(6v7Gc%=nG(sUUlS17UxyvT~!pTmun64WFO~#6;Lyi&=fD$X^O zRUFFTILjmA(eed+glbgcj1kX6aeLx@E{08x+E-niGUITJILoz_7CW*@BWG%gI_)}{ zj{k(J$t=A)9dqRBi^wEbD{Qx}y_I~YwT{0|Gqc7jg41=z2b`AtUMW7g)0D<5DgBU( zA=G@NDPoOPx~0TOQORZR*CP4Cpo`Xje(y*Mh1bjk)@~oz8aluKW@HY&%FehMtsQDq zOy~I4d_u$?p359R%-tns3g;IGto~l^Ai07mboZEFi{y(N@?}F<&CVK9pN7&%YL2&R zhN(<8E>lW>#16Z^Q5EJEm@@cHl}ho)AqL{#k_<7_(+5N-B%H{rkoAkQ$huh74b->< z0>A6btCGN~lk*~Oad{b$hCO(laY4>L-azJ{Egd0dxhh?vr6Z)wtKcK)`fV~4lJ+Zl zJL-SjnDT)0?AQVLH~%^l)kv+1f#o`I+h{vSt$UVR%; zQ=|fsNcWs|TsAE;_Q3F*$WnIk-xwGMRh!0%W2`axuv|}slIrZdJL`&TpZ8dOD6g9T z`B=l`&&Mu%w#S7RKNPc&8n+NfJWf{h8qZ2RXTsLfM4#CAF8%nAhwd(!l#)6xbtgr& za3xwxM;Kn@shp@!xqsvU000000000000000000000000000000001fCA5zW>^=vxn QnE(I)07*qoM6N<$f