From 2851203e67a935fd90feadb4bb45e2fc609d731e Mon Sep 17 00:00:00 2001 From: Luigi Rosso <luigi.rosso@gmail.com> Date: Mon, 12 Apr 2021 16:57:40 -0700 Subject: [PATCH] Improving state machine api and including more examples. --- example/assets/little_machine.riv | Bin 0 -> 17522 bytes example/assets/skills.riv | Bin 0 -> 79162 bytes example/lib/example_state_machine.dart | 7 +- example/lib/little_machine.dart | 80 ++++++++++ example/lib/main.dart | 32 +++- example/lib/state_machine_skills.dart | 92 ++++++++++++ .../animation/state_machine_number_base.dart | 41 +++++ .../transition_number_condition_base.dart | 41 +++++ lib/src/generated/rive_core_context.dart | 78 +++++----- .../animation/state_machine_double.dart | 11 -- .../animation/state_machine_number.dart | 11 ++ ....dart => transition_number_condition.dart} | 14 +- .../shapes/paint/shape_paint_mutator.dart | 2 +- .../rive_core/state_machine_controller.dart | 20 ++- lib/src/state_machine_controller.dart | 140 ++++++++++++++++-- 15 files changed, 484 insertions(+), 85 deletions(-) create mode 100644 example/assets/little_machine.riv create mode 100644 example/assets/skills.riv create mode 100644 example/lib/little_machine.dart create mode 100644 example/lib/state_machine_skills.dart create mode 100644 lib/src/generated/animation/state_machine_number_base.dart create mode 100644 lib/src/generated/animation/transition_number_condition_base.dart delete mode 100644 lib/src/rive_core/animation/state_machine_double.dart create mode 100644 lib/src/rive_core/animation/state_machine_number.dart rename lib/src/rive_core/animation/{transition_double_condition.dart => transition_number_condition.dart} (69%) diff --git a/example/assets/little_machine.riv b/example/assets/little_machine.riv new file mode 100644 index 0000000000000000000000000000000000000000..bbfd0243f58455b3dffc98bd7d27570185422ed8 GIT binary patch literal 17522 zcmb_j33L=yv+kMcW}gj$WDpXPI0HlxB(erFTUcc?QIG_cEddn6>VvpoKz0$7gb1P# zg&$E76apj&WHJ*VY=W|@EC%HFg;fy*1oEnG*X`*}GXC$K^E}7)*8Of(eYdLa(mgS$ z*T8Nyg*DbZoq+!|5_B~M;d){%L70<RTkwUK)DfD^Nfhh#OPkWnJ#q5zal<B#6!el{ z$!c~i!HN%K_IDE!O$S~P6NQ$dIDFj5Oi5>XZtI^;D?SG2B^~#qth;%~oqBob1FxVL z>-HHlYV_n6M@>vi%aHWuFISK2YPn>o?X)f~7o7DE9_ZsV-ps$}G5Jo`DiI8l!R#%b zw!>oW{f5)p$~@a?tQh-If$4BkSYacxAWCA`?j2uw8<xOB2$Mv?D%FVIy`z;^Xdu;e zw5Sj&ntPYMoxr3e6@t)Q5VD+1imec4Ht%X_Doe}HR8%l$9&|SSk3CMSZQ4<%F+O#C zC)t?^oYm7fs|U_Z(c5R(y)mn9n%rR3?C6LdYemJPN3&y^%A?tVKAKx+WOs!i)Ru!V zF>Pd(5NKxKK%Ra4znZzM3kzdis@XRLLSY(0VL<31KKn)vAszhD>_HMLl-V;$nSCS1 z3})ZJ%x2$n>Pe@yr}3gX)HwSl8fQ(wSp;_$DLbQygQRlCB*j^zDhv%IhIMOho!`a@ z{`HpW(|=E}Hh=YYf^ll(CBNzL-4_CaMY0>SdKVU(&b7Duo9P5ea)jqtUJclq3|Sv& zym3ZtFYofIx@yRyytXkBO#{#TWZql!?93d4XW)<KUampw;x~B&95Hv!lz{EiF*%-R z_RW94=-E2YHS-R{v4ezfuX>=K?7~CRqp?p~*ZHF^u09cnKKx))QH-beH4misF-Jv3 z#T?$C*y=^GTV~oMNpEa(P!}*It(qBtY}diQ7e@~pKR#1xZMkw$a$50W^vx6!Os1Cy zxMA{bERM%_I<5FHUeBK9H;p`;TL6=P!ZLb&uG1LtXmlqw`L^Lcv8>oOG^4k_v1@Xn z8z#@X+?Be%7t7qX+&^R7@~9XX75?Nq9c_nlZx<*11W`!N=$|EPzk>#YL&Kyeg!)oP z`<^{}a80O*EzF+gF=ah{bu$p_T!~nGRbs45ODsOT3bFVQ#NxxN5bF%Y+%hp(LoBM} z#=|zE4yup^L4~cX6L9ycf~w}8$U@nzDr45AWgP7C@PG#usVhuM1ZKT?$kcALF_#pw zKFn?3s%}}A)@`s$aT`=r-1Y&tNjxC+SU{$XoA~mWj8P$D@{GB0-sl8XU>;ukhTrt> zHlqt6sn42McQrXJmws|Nt=oK!oW|X+Uvil??3+={s1FS9bEJXawsYO6;>NCr#$)*m z4EJ@ldaCQH`^HizK0b;m2D`u&vzS`dVro^3)D={hBvK4^g-OpsFoyCRJY&usIC`gQ zn(F)yH@CZMDzXRyOmklnOw)1kmd}))PSYGwmDGr;q^K*%K$1u?*kzH1vuTd5YH@T` zi_{fVmn2dQc7;j9VVbY-oY!SJA2D{^BsfY!ErW5YFtBWocYKF?%Xr3ZLRD@Ps&b>Q zAQ4F-#b8&MG#<G97f*rOtvdQsncK{&ZZoU8rLLe4Ng~BySC}*v+)m?e^_HAY_Y<u6 zkdKk@oFRCOWa%oMBhz(N4-&ageUeC$s?W<09F;Ehg@FS&E@tau$HHk9wR`_UfAol( zf#MkV=4E&tnWKYa5&mJVn3$Lf`7VOTUhqU<#~$&WUzzVa)$o=3w0u>43SX73!gsz7 z!uFod4x}oCaB04-wQzKU3;Gu8?7dp_tAKl+-cq{0wbP0ZW1FToJ*F;!33#H_l<zMc zr5v5HbnIM@Y08g%y|Cdf(OFh5GPteyFxHseuh8^y%>IH#czwv#g*Ce(c^bBW2OO=r zI=DbA)y293z1l}LJ9T4obi|ce?ik?G9zwKC=NKly^`-In^LUj4afs?l!O?8{<Ae&U zVDPve3%bf2cHExlvf`r>hZR~5E09B8C=Q=!Ie@6<z)|7=VvvIppAHzGs8{CtO$+7t ztO*^T&$Qe=LvEjk;`W7>8;ELd93^fb2Dup|;1DW48?+oYAct>4aoDKk0HT@$M~MT7 zK@LiM+AH<5KYgwTa<?^fd<wMO3Xt2jP~5)NasyG#jiba3#2`1uAyj;PS`I$s;19(i zpydFfngd6P1BgKmN_^TW^>bH_Pig4*?A3DHi`@2y;&wpG4Ma6JjuJNzgWL=fa0nHj z@3kDhM-E3qaX6~w0HT@$M~MT7K@LiMo>b~*YsD--)X%BV@%d59?MLMHb0}`7wcJ2d zbK@v+12M>raR?QkGA)NP<ZvMrhhMcEKvZ+!C~*KW$U%uuoKin|a(v1|$LErk+a=_7 zB^0--T5ce!xp9=Zff(dwkbpy|_}tKPxPcsQhT?Eb%K=0+2aXa45Q7|)__S5(=h&J) z0jQt9L&xWymfJn#_8=6u3N1Gf)!aBr+&~O+V;n-oXQp0rhR)OjhuQiNXXqTg<_rZ< z&4HuD0mL8&B|c9m^|Mco&jNkO^Zi{dw|9}-qEOu4({ck*&5fhP4a6Wfg9IEx#b=3@ z!xH51K`0JOwH!cHbKod(05Qlx4`H$VYlPlq#fQ=IN-eKR7{v~-kM)*kP8gh4d>AvY zNPbhym02FR{;beaTcL-0R-WD-8xe;u*&4N7=Svl}Pqk{FqT1@})kdMWtp0Cq0dH%x zYHLt!ZS`u~(Hp6Kp;h|=)z($7HW0nFx&phdD6QA3tw*)5t5@5E-bihuR&67y<yWuP z7rnvFF#z7SXw|l$T0!+{>(N_tS#6tEZ5yg>SE(7{cIr1hCTDA>cJNLd?9<yV);e;w zj9;T=8tm5&_T%6Z^<ZWhZnhnP{ci2x-8i^ZJ(yXh!TYp>_u=3J>cPzNBXSnL(+>U) z2Om}sW|nF258A;$;NYX`!OXHl4&8C>;Nv*>q-wCL<XKr{o}P_m@uODlM^yV+Z;uXd zS*7GzS&-Tpt=bt>J6FA$x-81HYGtT)L8T_AjAnFEJNP0F{!KljcHLJyt@tpq_0d=^ zi*mhjW&Qw<NqG9fX4OtCO66L6<$8D%yrPc{7x%lPcG~y4qemRv?T&%i7sK1kRlP%B z@^^*YYHxg<-UP$J3efmnZ=YUX(OBLTf;3o!Xqny!MdOB+#to!#OCNjN05opzSnG~X zMjGoZn~=s|3JqwfX@FXN>8{>B@ACb)YH7@n^LsB8jeA-e_mD<~KK3Ni@bAfWM`J5y z<L7sgMwY=L?Y)7~fL1&68%i`lt-kcO!T$D@ioTU;uu`U6&N75Z$}EE_M`6+|1JIaj z2ti|>!J$9Kk^-%ErXUSat1m5JG}3{F-jbhtKEZm$dn>`{nmw=B^vH7~@$14u1ANtp zkro-kS7z2Lv6Tf51n@I!QS!B}>pe0cwCU}#9k_Zeko5h5dYzL89be^DG!hjJXYzs* zUy{b~+=xWmrX_L3Nq=RRI+L3=&8no~O}eoEAy@Jv6TVXW$T@Y%n`EpB-*~T{Umet7 zteA!`dCrLqq|vTzWQpwKPIhTgvbks~{*tl~gSFHUySJdXC+d-F*8<UJ|7)-(X6;Xx z@LR?*gQI&P{9?jd(LJ^)Ia_FGEfimLf$m3!*u{I+x@BE#aovv%_~E=0=*lhna*mPx z^Y?2B)}i0)oN{Cz%N~P~&66YhNvOyIP<>=&jcOtbK=qMTX=o$MeN>68tWiy50jNH* zc^KI*46%3aNS>%@j4ZZd*2t0l(%=yGvB*NJeZAL|$mT(0A1=hmt~bO!K;7o3i>;W| zvhD_hW9Buc3$4S2{P!OCiX;EZb|CrJ1Z(s+ClZY3zWLi@^1ojfe_-2aFdu$v<xWdR z-?L6@#>sN0arm@4ev{|PVa2eAZ!&}pn77N*FfVI4ezn<z<To2)dp4+192HpJ%pYx8 zDY;|LeQ3m=M7FThu2Nb`YBw5;S;uC$O}_L_UdU)66Xj3J+YI4d;`;||=fqTh<MAEZ zdf=O~+~*C|7aYRWkXIot(jtSsg*^s8WfelOCf~wf6&qq}{MDj3>Pp^7fAk7zP;tz( zuac3g-{5#DZ8(-NwD1cU{~QNgpK59Hnc7W0;As>NY<FS(Nz!gZ_{_VGfbHw6{R54= zA8mm@JIQ_CP<_E6Obyr7E+o3&U|+cGLp%i4&cM|{+0}Q|xRU#{u2g;KN~MOb4jSP0 zd&Cg?=_l!3qK?n)7KmQ63AWweTGYq+AB7S*bOh%QttnHc(EOSB$;!_vnt!<X1b$ot zboT7I70qiTJnn?Z9)!s5JcAzzPZ{hb0r-W8IeJL?$q*YBJ=7C*^wcO%bpE+Xo|yc* zEB#>LXM<xv@2Albv@$X>_%CHpl^Z9#vBR>;b1A`!599UN1_9Hr@0a0=*jcI=p>~oV z0&`APF~3w(F>;@_VpM%tF)B5zm~)tjiw5}knTi#24(28Juws5Q#I{?us5q))W{N-h zgz>H7nA78r`+)v`8yu05B{&gip&GB4vj+2|MoYi8Y`x)eTJd3AcC@|QH0^k8+`cZW zs9&juy4<IwuIfYTDmA2j8L9uFP`|8D|1%Wzn+kPkRif@5{qhr*t9$Db_0yN`xJ>z_ zPNaTYMg2}S)a5=cbyXiySE(WO+erO^LjATvJxdG`_30vyI<$h+TSED?KGf1RcwxaH zZ_3Gn(Sg)$E+2fFmS&3PKgydrEz3KdOt7ABe{!dB?o-KLQ|CszeNb1kMB{Zwjbc;Q zkh@!9dz&qWjm{t7Z8#ntPzAHa)<VQStb(~>?5qagx}(l6J?M`fYJbovCL{kauA6zH zBWE?+WT92JZZD+@z_O6}i{IpX{%H@yZh;81e^-P9{#`NL_hXUA)~sZrKdD>JvV`Qz zwN~Td3xJS0%qs(ByV8r2$E=9*0F4DeqgMwvgzA0KZm|rl5MrTkNRB8^K(N=qtvN@{ zJq$!x?zv*DFyNIfQD-6w{L#C+{^5zKJFySa{y=mL83NzP=ahdJFN=}FBxTJ5+QRfh zMe}vfg*k;57{X6J{iSHI|Mju>QGdB;{;Ee$mt}BAi0GN~{vF1KpZDluI?`#0PpBz< zBpO}krv$>fod3()Q0TE3)BKSL+*gS9<ufPYE~hcjyd$LK+qkn`O;_eT>jDFL)fmV_ z1D}fa-W^(_0U$Iddu10(5i)ozve!;yub)%ArWy7Ag$7nvV_-EJSfen|81Quf2A|&n z11(=jC;|g(t1++^4SYciu-eXT3UdzrcD=`&;yd<~H}%1?0<5-mA_7I03+;g!K8(5f z9<S-{t0gYr{gt-b)~hoXF0EIp?dwq0_Ki|)&{9_$SXNhCK33aithUXestthZt1Vxt zwnC-a^2H(BvD(m$Ty5Lc+`}Y5t<ug=)mEgfHW1a-2BNy!AcVdn7o3Bm{_c;}77)#6 z7WeSU5#3hi?`kwYIj+bwWz4FskgAeuQdNSf+O6bTV}PaP>Q-lw>EmJdv0O{5F;I#I z_9@i{gbJt4=^`^28qq7kIBQ*RuPLwKV>ED}8UqK=z;_A*jRD4BRyG)T+??qI1Ba_I za2O5zpj4aA{OjvFpJg!q6%{@P|9ts<Ps+J|TfC{;uZJf>-5nLp<;@orS@s<GcY+lj zJB=gaw|Pt(CVhju+%ZU7lT&_^aK?`Jt>YrQ!JNP%IU$DU?R(i{11KPiGxtP$Wibp! z0*{|WyRB9STz6onr&J7|hx`^V>^P^zu#?L^@iaUK4_M`=aqw9h+)~n+*En*DRDb$4 zEk4JS@=|<3AocVkHYELvh(nx~QY4KJ<ME6FkLk0U$8oWgX-S`#Nnb$H7qp~7RFgiB zJbqJ1gB>;LaxLj{9DG?tdP}asry@P0%^^?9d#_ycre4f`1W8{N%{~8^U!?p<TV!mr z=#<B_cWqG-kiMoReO)H~JCgogOBzHq>FXk#GB?H8z{30Ps6QV(?T_{^-sFi%$*CED z{rQ&YXlKpDy9TtP>-3|YT9mGfW})6|tBuAjF1IQ2=e5PEj9>}|7QClUfpt{ClhW(G zKLe@pFS6O(6>*5uat;3o2_MF%qF^?^t}DkB{H>miDBTl{2lK&CYpov(0IZ-M;4~j- zrwO8Zn)h&;Go;uJm&)BySw|fH=(h$Hcw*A!X}&G-X+kTqb`Rw+)mf5eU3OZZeDl21 zSaaPbm#OaOk%>^rvnA$ujubxn!*>HVSKQg+#%p)m@umTNIZwUqwfWj=`btl3hrX;* zw`$zUiGI+X&ilf^EEL58$=>?m$>~to0&rd^#Ww3XD=``$F@kSbBIII`<k)@ZK4t}4 z_rE$zbejlG+<)DPOz^NjE^OjVca2JLeLdq^g3!d->z8g$faBs?$9uYseG}Tw(;eC* zxNoJu)`iBq;q60^+mRjW^cp!ft=U-o6G_1q*Fb38uD%eFsDt(zok}QI3tQE~DYdXb zuhJ=1BY&%fC2GN-s6=)Ukxi%H^zphbt-2o4C8&9LTQOR2qifvGBt&>0Nz`{+EOj4r zu1x@>zOuwFk`dllHP{NBEUw=Jx6BCdZW4R`!Zfd`QCl3J54pQ5f;%&4wUTXMy@T|u zEIoT*9!k?R*cviO;2{#3rY(*Kg6xlzXV0VvZ$B{BzdK87gm(yUJP+Au4dX0~hK_gl z1FzW<m-;8_y6^SQcEXq;!RGTYCP(W2^w2jD$N+#DZ`{uMpKL8WHHzD!CfUk(?%hhZ zjARS{1QD8pz)K5k%6Wpcb!UH<Xp3v3nJfeb^UF(%0)iEU6Ky2NG^OkodUMGV{)I0{ zqczz36kq}iNhHlOH7d`WOvfMjJ)~*ELYOABlIav+Ms=|r{{9%|kqSLjH|&p*6?|l0 zLn2^QH$8{JA1X(9dEHEqL0&fuwZ;8XsSxq(3py-bvk)aRNEkOrAUDWRTO7RA$q8yI zM|19Wmc8z>#9k(`V%Q=h>;sBrofGh;8R0D=al#I!`I{QG#lZ`2umIR=wJmNrp9G~K zspc`HP1(hF0FWrVgz*#*$g@i*PXR-1aeV)wT3T1h-J6}GoI!VZ!4A43jJqR{yCaml zW2h~T?{MUfZ)+r8<=&|T@Zbl3R3arMHBh3A5ymq{AkP>>ZE-WXL5f~XQd3uOIuT2v zP@?D&#-~FdpAMmXIt;bN@qL~6dm(>t7@)*AnSQ*{ANq&Dzt77Zwzy}4gQ1(2_EAol zB7m1nKq&%E@@lFgKp2kzfjj~XwZ#RvL5jd#_|tJPNcDradXOjrgz*Rv$Rj`~j{rmA z{22s)%-Shm*G1^ML_U2!LyvaBo~V27t(S*XsLn<3)P;wmI|xhU?TnpIxFgo2P3p=W zObZcCktMqZYon1mYb1|G>aCHIG*XI28mEz_$kNEGz=bVJS*FvHn64;0>j$Q04Mw~P zi_l;+3&I}NU^FMf+G#MFAz=v`jOI%iZAQeCW=|L%e{lX2MzJ7lpa!GJ5cUFKOB6kd z6JZpm4yglhe|t-|Lf3``w7t=VV>5}&zb)=auukkvY*;6Uf<06@{AvNFBY5Ss0D&rp zT{Yn7gXKm?nFs`OB`&=v)44XBt@@W_iAGLUN$imO4@O!oWyk728G%cWY?Q7%MCR%6 zH;aHXk@<YlhbWPq*T0^P(nKQjeKtx&jjX_2S=vb4K_a^=1usXSR)<F@3<Qc0U6$b5 z5aE4|JsA+;-GV(^m2Ij-Y3;%r23<Rt!bs*GMyK%x*=FbKe~x~O^#6zGQ_}ud(WkSV zqM!6=rYibdU;juI{l|~8%P2+vRohZk^vMd3K8ZZ~?1G@&{(0b)i|7Cd*Hriy&bQ!o z4dgIBGJ=8ZHb>VtssQ=ARs*CDr0!$%6;2pPl{5e1Rg}icBg=>1MrpDvz4Y-PD7~h! zLaULkb!(|`SSaO+XLUuPC6~9`UsAaY^cQd|CYNu#eO=|Uje`-W)+Jr{D!Ih#9%f~! z)O{9S_aeMJoWa|lJOR4<(clvuYT@0F!cedGuXy*PQfS{)M2u4SaQ+>{h!a`iDI}5m zWH(A%Toc&d<s$A{s|D`$aL<RWpmTOx6yR6_VPJ{15EA*W1U>S}R=Y;Sbm(C>Le<eV z1%6ck|8xY9M4LWIw9S*$S)MORw3U<8TZ7SdO<0Nsqb->*+LCjTi|Xj2`zak=honN) z(M1^XCX6;S!e|zR(a}X1&51BNx(K5g5=KWCVKiUDwD)M5Jz;coksif@Fgm&jqsS0O zM;BofC&DOB_Yav=M;BexXVGGzYy5f=nH|+d9e2X+m2T>CX6W)w(cYT6uL$abE()9W z8u1!O(SA?HDB54h7)6^fiZ)>sZNezpgi*8!qi7RG(I$+dO&CR+Fp4%|6m7yN+JsTG z3Bzc^1%t43h)tuchB#GvDSH2M8HR!OED90rQuKPlw+wnc*;D08z+YJSPFe>H(t*TZ zE}*9chua3>l~ru*5BAU%gunmD6QNg{da@*a-U+wAFj;#2gn&{LS!yC<F|rgZW3d{H z(nc7ijr1sOggG^OUX9Hj8tf?z)?b4qYp_8YELDTi#!6h$Wi081wh1sl%3N-*Cvmov zIf@Hqj^6Zm=IBi?4E7#*Up+ShzKigEb?$GkI$`7FFMeRNJ5LoJnv_ZY-X>F_S20>k z_ZNrbnM7;JG@>O+w3ec>8AfZVwv5qQB8=7&VU!fYC@F+dQV659L>R3l!e}iKMr(;M zT1$k{S|W_r5@EEK2&1(`7$s#v%Z@l(O3I?-2$U!(6eUUuy|415(EBQT!IrZ^$3ESX zNTNy@*vf*2Uy{R5*#GsyeC*r~ESY~YqFk8iWuC}fn8)@<BJ<8m_ltsdrnRZ%18Jg6 zEpD71C89=F_<2tvKkwNWg5WDVsI}#l*98QsJbH!ah#ruU@NXLK^Y}le%L93Pi_!~U z0wTO6_}E2#!FO+&E4@zBW|Ft17KWHMli5*aXqq;YY#F1?#3f_2nGi;GOBmHHVN|z- zIc4vJ(PlyzZ6<`#W<nTkCWO&uLKtl(gwbX~7-fwxJOf6&Tpy>3pHegPj^RA1VkshT z$qecH0<TyG+T!q&nEZVmzVm|W03P}b-WUhHlsx*R0v&pej^vHB;4t=)MP3E?(;Wa* zcqGvjBCJ;AO$AICl^T=yp7u{he1nS6!9N*MRsns`Au=DQ)xp{(GOaf~C<@w%a<C6U zv<g0TR3Jvw$O>NtB=S|jz7pBuR#iFqzO2*}*`aQ)j7ez|C%-sy*yLgGg(qJ9F2mjo zyRhd}_RN>R<<QR|Jm~nEqkQtg>;F`a!2etr;muc;it48m(5Pyce`pKkmwzY-h4ZUH zD4gFaLgD;3h)_5`&qCqqGOjYcb{)*glZQ=CYu0zzh|yy*(waRXbe^xP{mjHMqei7o z1gX<}UClnjGFdwTKeXxK?&1Cb{^L?%ZRJi82j~$Nm+Hh7x>8-9?hmVw0Am3V5P<)q UvY?TWxEv(tGB8tY>_`Uu4_DmNRsaA1 literal 0 HcmV?d00001 diff --git a/example/assets/skills.riv b/example/assets/skills.riv new file mode 100644 index 0000000000000000000000000000000000000000..ee24fb8a45e52cb6e41026eadcf70bb87a576da9 GIT binary patch literal 79162 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 ImUKq;8}v1Zp8x;= literal 0 HcmV?d00001 diff --git a/example/lib/example_state_machine.dart b/example/lib/example_state_machine.dart index ec8db10..9eb220c 100644 --- a/example/lib/example_state_machine.dart +++ b/example/lib/example_state_machine.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:rive/rive.dart'; +/// An example showing how to drive two boolean state machine inputs. class ExampleStateMachine extends StatefulWidget { const ExampleStateMachine({Key? key}) : super(key: key); @@ -16,8 +17,8 @@ class _ExampleStateMachineState extends State<ExampleStateMachine> { Artboard? _riveArtboard; StateMachineController? _controller; - StateMachineInput<bool>? _hoverInput; - StateMachineInput<bool>? _pressInput; + SMIInput<bool>? _hoverInput; + SMIInput<bool>? _pressInput; @override void initState() { @@ -50,7 +51,7 @@ class _ExampleStateMachineState extends State<ExampleStateMachine> { return Scaffold( backgroundColor: Colors.grey, appBar: AppBar( - title: const Text('State Machine Example'), + title: const Text('Button State Machine'), ), body: Center( child: _riveArtboard == null diff --git a/example/lib/little_machine.dart b/example/lib/little_machine.dart new file mode 100644 index 0000000..d2237b4 --- /dev/null +++ b/example/lib/little_machine.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:rive/rive.dart'; + +/// An example showing how to drive a StateMachine via a trigger input. +class LittleMachine extends StatefulWidget { + const LittleMachine({Key? key}) : super(key: key); + + @override + _LittleMachineState createState() => _LittleMachineState(); +} + +class _LittleMachineState extends State<LittleMachine> { + /// Tracks if the animation is playing by whether controller is running. + bool get isPlaying => _controller?.isActive ?? false; + + Artboard? _riveArtboard; + StateMachineController? _controller; + SMIInput<bool>? _trigger; + + @override + void initState() { + super.initState(); + + // Load the animation file from the bundle, note that you could also + // download this. The RiveFile just expects a list of bytes. + rootBundle.load('assets/little_machine.riv').then( + (data) async { + // Load the RiveFile from the binary data. + final file = RiveFile.import(data); + + // The artboard is the root of the animation and gets drawn in the + // Rive widget. + final artboard = file.mainArtboard; + var controller = + StateMachineController.fromArtboard(artboard, 'State Machine 1'); + if (controller != null) { + artboard.addController(controller); + _trigger = controller.findInput('Trigger 1'); + } + setState(() => _riveArtboard = artboard); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.grey, + appBar: AppBar( + title: const Text('Little Machine'), + ), + body: Center( + child: _riveArtboard == null + ? const SizedBox() + : GestureDetector( + onTapDown: (_) => _trigger?.value = true, + child: Column( + children: [ + const SizedBox(height: 10), + const Text( + 'Press to activate!', + style: TextStyle( + fontSize: 18, + ), + ), + const SizedBox(height: 10), + Expanded( + child: Rive( + artboard: _riveArtboard!, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/example/lib/main.dart b/example/lib/main.dart index a89e7a1..2434d5e 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:rive_example/example_animation.dart'; import 'package:rive_example/example_state_machine.dart'; +import 'package:rive_example/little_machine.dart'; +import 'package:rive_example/state_machine_skills.dart'; void main() => runApp(MaterialApp( title: 'Navigation Basics', @@ -33,7 +35,7 @@ class Home extends StatelessWidget { height: 10, ), ElevatedButton( - child: const Text('State Machine'), + child: const Text('Button State Machine'), onPressed: () { Navigator.push( context, @@ -43,6 +45,34 @@ class Home extends StatelessWidget { ); }, ), + const SizedBox( + height: 10, + ), + ElevatedButton( + child: const Text('Skills Machine'), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute<void>( + builder: (context) => const StateMachineSkills(), + ), + ); + }, + ), + const SizedBox( + height: 10, + ), + ElevatedButton( + child: const Text('Little Machine'), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute<void>( + builder: (context) => const LittleMachine(), + ), + ); + }, + ), ], ), ), diff --git a/example/lib/state_machine_skills.dart b/example/lib/state_machine_skills.dart new file mode 100644 index 0000000..4b16f3f --- /dev/null +++ b/example/lib/state_machine_skills.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:rive/rive.dart'; + +/// An example showing how to drive a StateMachine via one numeric input. +class StateMachineSkills extends StatefulWidget { + const StateMachineSkills({Key? key}) : super(key: key); + + @override + _StateMachineSkillsState createState() => _StateMachineSkillsState(); +} + +class _StateMachineSkillsState extends State<StateMachineSkills> { + /// Tracks if the animation is playing by whether controller is running. + bool get isPlaying => _controller?.isActive ?? false; + + Artboard? _riveArtboard; + StateMachineController? _controller; + SMIInput<double>? _levelInput; + + @override + void initState() { + super.initState(); + + // Load the animation file from the bundle, note that you could also + // download this. The RiveFile just expects a list of bytes. + rootBundle.load('assets/skills.riv').then( + (data) async { + // Load the RiveFile from the binary data. + final file = RiveFile.import(data); + + // The artboard is the root of the animation and gets drawn in the + // Rive widget. + final artboard = file.mainArtboard; + var controller = + StateMachineController.fromArtboard(artboard, 'Designer\'s Test'); + if (controller != null) { + artboard.addController(controller); + _levelInput = controller.findInput('Level'); + } + setState(() => _riveArtboard = artboard); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.grey, + appBar: AppBar( + title: const Text('Skills Machine'), + ), + body: Center( + child: _riveArtboard == null + ? const SizedBox() + : Stack( + children: [ + Positioned.fill( + child: Rive( + artboard: _riveArtboard!, + ), + ), + Positioned.fill( + bottom: 100, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + ElevatedButton( + child: const Text('Beginner'), + onPressed: () => _levelInput?.value = 0, + ), + const SizedBox(width: 10), + ElevatedButton( + child: const Text('Intermediate'), + onPressed: () => _levelInput?.value = 1, + ), + const SizedBox(width: 10), + ElevatedButton( + child: const Text('Expert'), + onPressed: () => _levelInput?.value = 2, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/src/generated/animation/state_machine_number_base.dart b/lib/src/generated/animation/state_machine_number_base.dart new file mode 100644 index 0000000..e3d4592 --- /dev/null +++ b/lib/src/generated/animation/state_machine_number_base.dart @@ -0,0 +1,41 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_number_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +import 'package:rive/src/generated/animation/state_machine_input_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart'; + +abstract class StateMachineNumberBase extends StateMachineInput { + static const int typeKey = 56; + @override + int get coreType => StateMachineNumberBase.typeKey; + @override + Set<int> get coreTypes => { + StateMachineNumberBase.typeKey, + StateMachineInputBase.typeKey, + StateMachineComponentBase.typeKey + }; + + /// -------------------------------------------------------------------------- + /// Value field with key 140. + static const double valueInitialValue = 0; + double _value = valueInitialValue; + static const int valuePropertyKey = 140; + double get value => _value; + + /// Change the [_value] field value. + /// [valueChanged] will be invoked only if the field's value has changed. + set value(double value) { + if (_value == value) { + return; + } + double from = _value; + _value = value; + if (hasValidated) { + valueChanged(from, value); + } + } + + void valueChanged(double from, double to); +} diff --git a/lib/src/generated/animation/transition_number_condition_base.dart b/lib/src/generated/animation/transition_number_condition_base.dart new file mode 100644 index 0000000..9cc38d1 --- /dev/null +++ b/lib/src/generated/animation/transition_number_condition_base.dart @@ -0,0 +1,41 @@ +/// Core automatically generated +/// lib/src/generated/animation/transition_number_condition_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/transition_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; +import 'package:rive/src/rive_core/animation/transition_value_condition.dart'; + +abstract class TransitionNumberConditionBase extends TransitionValueCondition { + static const int typeKey = 70; + @override + int get coreType => TransitionNumberConditionBase.typeKey; + @override + Set<int> get coreTypes => { + TransitionNumberConditionBase.typeKey, + TransitionValueConditionBase.typeKey, + TransitionConditionBase.typeKey + }; + + /// -------------------------------------------------------------------------- + /// Value field with key 157. + static const double valueInitialValue = 0; + double _value = valueInitialValue; + static const int valuePropertyKey = 157; + double get value => _value; + + /// Change the [_value] field value. + /// [valueChanged] will be invoked only if the field's value has changed. + set value(double value) { + if (_value == value) { + return; + } + double from = _value; + _value = value; + if (hasValidated) { + valueChanged(from, value); + } + } + + void valueChanged(double from, double to); +} diff --git a/lib/src/generated/rive_core_context.dart b/lib/src/generated/rive_core_context.dart index 13c43bb..6d12f31 100644 --- a/lib/src/generated/rive_core_context.dart +++ b/lib/src/generated/rive_core_context.dart @@ -21,13 +21,13 @@ import 'package:rive/src/generated/animation/linear_animation_base.dart'; import 'package:rive/src/generated/animation/state_machine_base.dart'; import 'package:rive/src/generated/animation/state_machine_bool_base.dart'; import 'package:rive/src/generated/animation/state_machine_component_base.dart'; -import 'package:rive/src/generated/animation/state_machine_double_base.dart'; import 'package:rive/src/generated/animation/state_machine_layer_base.dart'; +import 'package:rive/src/generated/animation/state_machine_number_base.dart'; import 'package:rive/src/generated/animation/state_machine_trigger_base.dart'; import 'package:rive/src/generated/animation/state_transition_base.dart'; import 'package:rive/src/generated/animation/transition_bool_condition_base.dart'; import 'package:rive/src/generated/animation/transition_condition_base.dart'; -import 'package:rive/src/generated/animation/transition_double_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_number_condition_base.dart'; import 'package:rive/src/generated/animation/transition_trigger_condition_base.dart'; import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; import 'package:rive/src/generated/artboard_base.dart'; @@ -81,12 +81,12 @@ import 'package:rive/src/rive_core/animation/keyframe_id.dart'; import 'package:rive/src/rive_core/animation/linear_animation.dart'; import 'package:rive/src/rive_core/animation/state_machine.dart'; import 'package:rive/src/rive_core/animation/state_machine_bool.dart'; -import 'package:rive/src/rive_core/animation/state_machine_double.dart'; import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; +import 'package:rive/src/rive_core/animation/state_machine_number.dart'; import 'package:rive/src/rive_core/animation/state_machine_trigger.dart'; import 'package:rive/src/rive_core/animation/state_transition.dart'; import 'package:rive/src/rive_core/animation/transition_bool_condition.dart'; -import 'package:rive/src/rive_core/animation/transition_double_condition.dart'; +import 'package:rive/src/rive_core/animation/transition_number_condition.dart'; import 'package:rive/src/rive_core/animation/transition_trigger_condition.dart'; import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/rive_core/backboard.dart'; @@ -129,14 +129,16 @@ class RiveCoreContext { return AnimationState(); case KeyedObjectBase.typeKey: return KeyedObject(); + case StateMachineNumberBase.typeKey: + return StateMachineNumber(); case TransitionTriggerConditionBase.typeKey: return TransitionTriggerCondition(); case KeyedPropertyBase.typeKey: return KeyedProperty(); - case StateMachineDoubleBase.typeKey: - return StateMachineDouble(); case KeyFrameIdBase.typeKey: return KeyFrameId(); + case TransitionNumberConditionBase.typeKey: + return TransitionNumberCondition(); case AnyStateBase.typeKey: return AnyState(); case StateMachineLayerBase.typeKey: @@ -145,8 +147,6 @@ class RiveCoreContext { return Animation(); case CubicInterpolatorBase.typeKey: return CubicInterpolator(); - case TransitionDoubleConditionBase.typeKey: - return TransitionDoubleCondition(); case StateTransitionBase.typeKey: return StateTransition(); case KeyFrameDoubleBase.typeKey: @@ -262,26 +262,26 @@ class RiveCoreContext { object.objectId = value; } break; - case TransitionConditionBase.inputIdPropertyKey: - if (object is TransitionConditionBase && value is int) { - object.inputId = value; - } - break; case StateMachineComponentBase.namePropertyKey: if (object is StateMachineComponentBase && value is String) { object.name = value; } break; + case StateMachineNumberBase.valuePropertyKey: + if (object is StateMachineNumberBase && value is double) { + object.value = value; + } + break; + case TransitionConditionBase.inputIdPropertyKey: + if (object is TransitionConditionBase && value is int) { + object.inputId = value; + } + break; case KeyedPropertyBase.propertyKeyPropertyKey: if (object is KeyedPropertyBase && value is int) { object.propertyKey = value; } break; - case StateMachineDoubleBase.valuePropertyKey: - if (object is StateMachineDoubleBase && value is double) { - object.value = value; - } - break; case KeyFrameBase.framePropertyKey: if (object is KeyFrameBase && value is int) { object.frame = value; @@ -302,6 +302,16 @@ class RiveCoreContext { object.value = value; } break; + case TransitionValueConditionBase.opValuePropertyKey: + if (object is TransitionValueConditionBase && value is int) { + object.opValue = value; + } + break; + case TransitionNumberConditionBase.valuePropertyKey: + if (object is TransitionNumberConditionBase && value is double) { + object.value = value; + } + break; case AnimationBase.namePropertyKey: if (object is AnimationBase && value is String) { object.name = value; @@ -327,16 +337,6 @@ class RiveCoreContext { object.y2 = value; } break; - case TransitionValueConditionBase.opValuePropertyKey: - if (object is TransitionValueConditionBase && value is int) { - object.opValue = value; - } - break; - case TransitionDoubleConditionBase.valuePropertyKey: - if (object is TransitionDoubleConditionBase && value is double) { - object.value = value; - } - break; case StateTransitionBase.stateToIdPropertyKey: if (object is StateTransitionBase && value is int) { object.stateToId = value; @@ -861,12 +861,12 @@ class RiveCoreContext { case DrawRulesBase.drawTargetIdPropertyKey: case TendonBase.boneIdPropertyKey: return uintType; - case StateMachineDoubleBase.valuePropertyKey: + case StateMachineNumberBase.valuePropertyKey: + case TransitionNumberConditionBase.valuePropertyKey: case CubicInterpolatorBase.x1PropertyKey: case CubicInterpolatorBase.y1PropertyKey: case CubicInterpolatorBase.x2PropertyKey: case CubicInterpolatorBase.y2PropertyKey: - case TransitionDoubleConditionBase.valuePropertyKey: case KeyFrameDoubleBase.valuePropertyKey: case LinearAnimationBase.speedPropertyKey: case LinearGradientBase.startXPropertyKey: @@ -1040,8 +1040,10 @@ class RiveCoreContext { static double getDouble(Core object, int propertyKey) { switch (propertyKey) { - case StateMachineDoubleBase.valuePropertyKey: - return (object as StateMachineDoubleBase).value; + case StateMachineNumberBase.valuePropertyKey: + return (object as StateMachineNumberBase).value; + case TransitionNumberConditionBase.valuePropertyKey: + return (object as TransitionNumberConditionBase).value; case CubicInterpolatorBase.x1PropertyKey: return (object as CubicInterpolatorBase).x1; case CubicInterpolatorBase.y1PropertyKey: @@ -1050,8 +1052,6 @@ class RiveCoreContext { return (object as CubicInterpolatorBase).x2; case CubicInterpolatorBase.y2PropertyKey: return (object as CubicInterpolatorBase).y2; - case TransitionDoubleConditionBase.valuePropertyKey: - return (object as TransitionDoubleConditionBase).value; case KeyFrameDoubleBase.valuePropertyKey: return (object as KeyFrameDoubleBase).value; case LinearAnimationBase.speedPropertyKey: @@ -1340,8 +1340,11 @@ class RiveCoreContext { static void setDouble(Core object, int propertyKey, double value) { switch (propertyKey) { - case StateMachineDoubleBase.valuePropertyKey: - (object as StateMachineDoubleBase).value = value; + case StateMachineNumberBase.valuePropertyKey: + (object as StateMachineNumberBase).value = value; + break; + case TransitionNumberConditionBase.valuePropertyKey: + (object as TransitionNumberConditionBase).value = value; break; case CubicInterpolatorBase.x1PropertyKey: (object as CubicInterpolatorBase).x1 = value; @@ -1355,9 +1358,6 @@ class RiveCoreContext { case CubicInterpolatorBase.y2PropertyKey: (object as CubicInterpolatorBase).y2 = value; break; - case TransitionDoubleConditionBase.valuePropertyKey: - (object as TransitionDoubleConditionBase).value = value; - break; case KeyFrameDoubleBase.valuePropertyKey: (object as KeyFrameDoubleBase).value = value; break; diff --git a/lib/src/rive_core/animation/state_machine_double.dart b/lib/src/rive_core/animation/state_machine_double.dart deleted file mode 100644 index 1fe1463..0000000 --- a/lib/src/rive_core/animation/state_machine_double.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:rive/src/generated/animation/state_machine_double_base.dart'; -export 'package:rive/src/generated/animation/state_machine_double_base.dart'; - -class StateMachineDouble extends StateMachineDoubleBase { - @override - void valueChanged(double from, double to) {} - @override - bool isValidType<T>() => T == double; - @override - dynamic get controllerValue => value; -} diff --git a/lib/src/rive_core/animation/state_machine_number.dart b/lib/src/rive_core/animation/state_machine_number.dart new file mode 100644 index 0000000..26dfe13 --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_number.dart @@ -0,0 +1,11 @@ +import 'package:rive/src/generated/animation/state_machine_number_base.dart'; +export 'package:rive/src/generated/animation/state_machine_number_base.dart'; + +class StateMachineNumber extends StateMachineNumberBase { + @override + void valueChanged(double from, double to) {} + @override + bool isValidType<T>() => T == double; + @override + dynamic get controllerValue => value; +} diff --git a/lib/src/rive_core/animation/transition_double_condition.dart b/lib/src/rive_core/animation/transition_number_condition.dart similarity index 69% rename from lib/src/rive_core/animation/transition_double_condition.dart rename to lib/src/rive_core/animation/transition_number_condition.dart index 8748f32..a7fb680 100644 --- a/lib/src/rive_core/animation/transition_double_condition.dart +++ b/lib/src/rive_core/animation/transition_number_condition.dart @@ -1,20 +1,20 @@ import 'dart:collection'; -import 'package:rive/src/rive_core/animation/state_machine_double.dart'; +import 'package:rive/src/rive_core/animation/state_machine_number.dart'; import 'package:rive/src/rive_core/animation/transition_condition.dart'; -import 'package:rive/src/generated/animation/transition_double_condition_base.dart'; -export 'package:rive/src/generated/animation/transition_double_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_number_condition_base.dart'; +export 'package:rive/src/generated/animation/transition_number_condition_base.dart'; -class TransitionDoubleCondition extends TransitionDoubleConditionBase { +class TransitionNumberCondition extends TransitionNumberConditionBase { @override void valueChanged(double from, double to) {} @override - bool validate() => super.validate() && (input is StateMachineDouble); + bool validate() => super.validate() && (input is StateMachineNumber); @override bool evaluate(HashMap<int, dynamic> values) { - if (input is! StateMachineDouble) { + if (input is! StateMachineNumber) { return true; } - var doubleInput = input as StateMachineDouble; + var doubleInput = input as StateMachineNumber; dynamic providedValue = values[input.id]; double inputValue = providedValue is double ? providedValue : doubleInput.value; diff --git a/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart b/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart index dfea358..53544ca 100644 --- a/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart +++ b/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart @@ -4,7 +4,7 @@ import 'package:rive/src/rive_core/shapes/shape_paint_container.dart'; abstract class ShapePaintMutator { ShapePaintContainer? _shapePaintContainer; - late Paint _paint; + Paint _paint = Paint(); ShapePaintContainer? get shapePaintContainer => _shapePaintContainer; Paint get paint => _paint; double _renderOpacity = 1; diff --git a/lib/src/rive_core/state_machine_controller.dart b/lib/src/rive_core/state_machine_controller.dart index c5af8e3..7a38896 100644 --- a/lib/src/rive_core/state_machine_controller.dart +++ b/lib/src/rive_core/state_machine_controller.dart @@ -37,12 +37,6 @@ class LayerController { if (_animationInstance != null) { _animationInstance!.advance(elapsedSeconds); } - for (int i = 0; updateState(inputValues); i++) { - if (i == 100) { - print('StateMachineController.apply exceeded max iterations.'); - return false; - } - } if (_transition != null && _stateFrom != null && _transition!.duration != 0) { @@ -52,22 +46,26 @@ class LayerController { } else { _mix = 1; } - var keepGoing = _mix != 1; if (_animationInstanceFrom != null && _mix < 1) { if (!_holdAnimationFrom) { _animationInstanceFrom!.advance(elapsedSeconds); } + } + for (int i = 0; updateState(inputValues); i++) { + if (i == 100) { + print('StateMachineController.apply exceeded max iterations.'); + return false; + } + } + if (_animationInstanceFrom != null && _mix < 1) { _animationInstanceFrom!.animation.apply(_animationInstanceFrom!.time, mix: 1 - _mix, coreContext: core); } if (_animationInstance != null) { _animationInstance!.animation .apply(_animationInstance!.time, mix: _mix, coreContext: core); - if (_animationInstance!.keepGoing) { - keepGoing = true; - } } - return keepGoing; + return _mix != 1 || (_animationInstance?.keepGoing ?? false); } bool updateState(HashMap<int, dynamic> inputValues) { diff --git a/lib/src/state_machine_controller.dart b/lib/src/state_machine_controller.dart index f70065a..17a701c 100644 --- a/lib/src/state_machine_controller.dart +++ b/lib/src/state_machine_controller.dart @@ -1,17 +1,51 @@ +import 'package:flutter/foundation.dart'; +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/generated/animation/state_machine_bool_base.dart'; +import 'package:rive/src/generated/animation/state_machine_number_base.dart'; +import 'package:rive/src/generated/animation/state_machine_trigger_base.dart'; import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/animation/state_machine_bool.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart' as core; +import 'package:rive/src/rive_core/animation/state_machine_number.dart'; +import 'package:rive/src/rive_core/animation/state_machine_trigger.dart'; import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/rive_core/state_machine_controller.dart' as core; -class StateMachineInput<T> { - final int id; +/// [StateMachine]s supports three input types. The StateMachine mostly +/// abstracts types by allowing the programmer to query for an input of a +/// specific Dart backing type, mapping it to the correct StateMachine type. +/// This is the most flexible API to use to check if a type with a given name +/// exists. However, if you need to iterate inputs and query their types, this +/// enum is exposed for convenience. +enum SMIType { number, boolean, trigger } + +/// StateMachine Instance Input. This is the abstraction of an instanced input +/// from the [StateMachine]. Whenever a [StateMachineController] is created, the +/// list of inputs in the corresponding [StateMachine] is wrapped into a set of +/// [SMIInput] objects that ensure inputs are initialized to design-time values. +/// The implementation can now change these values freely as they are decoupled +/// from the backing [StateMachine] and can safely be re-instanced by another +/// controller later. +class SMIInput<T> { + final core.StateMachineInput _input; final StateMachineController controller; - StateMachineInput._(this.id, this.controller); + final SMIType type; - T get value => controller.inputValues[id] as T; - set value(T newValue) => change(newValue); + SMIInput._(this._input, this.type, this.controller); - /// Change the value of the input, returns true if the value was changed the - /// and [StateMachineController] was activated. + @protected + void advance() {} + + /// The id of the input within the context of the [StateMachine] it belongs + /// to. + int get id => _input.id; + + /// The name given to this input at design time in Rive. + String get name => _input.name; + + /// Convenience method for changing the backing value of the input. Usually + /// it's easier to use the various value getter/setters on the derived + /// version of [SMIInput] like [SMIBool], [SMINumber], and [SMITrigger]. bool change(T value) { if (controller.inputValues[id] == value) { return false; @@ -20,15 +54,89 @@ class StateMachineInput<T> { controller.isActive = true; return true; } + + T get value => controller.inputValues[id] as T; + set value(T newValue) => change(newValue); + + bool _is<K>() { + return K == T; + } +} + +/// A boolean StateMachine input instance. Use the [value] property to change +/// the input which will automatically re-activate the [StateMachineController] +/// if necessary. +class SMIBool extends SMIInput<bool> { + SMIBool._(StateMachineBool input, StateMachineController controller) + : super._( + input, + SMIType.boolean, + controller, + ) { + controller.inputValues[id] = input.value; + } +} + +/// A numeric StateMachine input instance. Use the [value] property to change +/// the input which will automatically re-activate the [StateMachineController] +/// if necessary. +class SMINumber extends SMIInput<double> { + SMINumber._(StateMachineNumber input, StateMachineController controller) + : super._( + input, + SMIType.number, + controller, + ) { + controller.inputValues[id] = input.value; + } +} + +/// A trigger StateMachine input instance. Use the [fire] method to change the +/// input which will automatically re-activate the [StateMachineController] if +/// necessary. +class SMITrigger extends SMIInput<bool> { + SMITrigger._(StateMachineTrigger input, StateMachineController controller) + : super._( + input, + SMIType.trigger, + controller, + ) { + controller.inputValues[id] = false; + } + + void fire() => change(true); + @override + void advance() => change(false); } /// An AnimationController which controls a StateMachine and provides access to /// the inputs of the StateMachine. class StateMachineController extends core.StateMachineController { + final List<SMIInput> _inputs = <SMIInput>[]; + + /// A list of inputs available in the StateMachine. + Iterable<SMIInput> get inputs => _inputs; + StateMachineController(StateMachine stateMachine) : super(stateMachine) { isActive = true; + for (final input in stateMachine.inputs) { + switch (input.coreType) { + case StateMachineNumberBase.typeKey: + _inputs.add(SMINumber._(input as StateMachineNumber, this)); + break; + case StateMachineBoolBase.typeKey: + _inputs.add(SMIBool._(input as StateMachineBool, this)); + break; + case StateMachineTriggerBase.typeKey: + _inputs.add(SMITrigger._(input as StateMachineTrigger, this)); + break; + } + } } + /// Instance a [StateMachineController] from an [artboard] with the given + /// [stateMachineName]. Returns the [StateMachineController] or null if no + /// [StateMachine] with [stateMachineName] is found. static StateMachineController? fromArtboard( Artboard artboard, String stateMachineName) { for (final animation in artboard.animations) { @@ -39,13 +147,21 @@ class StateMachineController extends core.StateMachineController { return null; } - StateMachineInput<T>? findInput<T>(String name) { - for (final input in stateMachine.inputs) { - if (input.name == name && input.isValidType<T>()) { - inputValues[input.id] = input.controllerValue; - return StateMachineInput<T>._(input.id, this); + /// Find an input with a specific backing type and a given name. + SMIInput<T>? findInput<T>(String name) { + for (final input in _inputs) { + if (input._is<T>() && input.name == name) { + return input as SMIInput<T>; } } return null; } + + @override + void apply(CoreContext core, double elapsedSeconds) { + super.apply(core, elapsedSeconds); + for (final input in _inputs) { + input.advance(); + } + } }