From 4e803de6a9bfeaf90078f9d8aa9adb5a495c6ba3 Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Fri, 20 Oct 2017 00:59:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9C=BA=E6=99=AF=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E5=8A=A8=E7=94=BB=EF=BC=9B=E6=96=B0=E5=A2=9E=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E6=A0=B7=E5=BC=8F=EF=BC=88=E7=A6=81=E7=94=A8=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E6=8C=89=E9=92=AE=E3=80=81=E7=A6=81=E7=94=A8=E6=9C=80?= =?UTF-8?q?=E5=B0=8F=E5=8C=96=E3=80=81=E7=BD=AE=E9=A1=B6=EF=BC=89=EF=BC=9B?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86=E5=8A=A8=E7=94=BB=E3=80=81=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E5=99=A8=E3=80=81=E6=B6=88=E6=81=AF=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E5=99=A8=E7=9A=84=E6=89=A7=E8=A1=8C=E8=BF=87=E7=A8=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Demo/atlas.png | Bin 0 -> 76303 bytes Demo/main.cpp | 31 +- Easy2D/Action/EAction.cpp | 24 +- Easy2D/Action/EActionDelay.cpp | 6 +- Easy2D/Action/EActionFrames.cpp | 82 -- Easy2D/Action/EActionGradual.cpp | 41 + .../{EActionNeverStop.cpp => EActionLoop.cpp} | 5 +- Easy2D/Action/EActionMoveBy.cpp | 18 +- Easy2D/Action/EActionOpacityBy.cpp | 18 +- Easy2D/Action/EActionRotateBy.cpp | 18 +- Easy2D/Action/EActionScaleBy.cpp | 20 +- Easy2D/Action/EActionSequence.cpp | 10 +- Easy2D/Action/EActionTwo.cpp | 10 +- Easy2D/Action/EActionTwoAtSameTime.cpp | 10 +- Easy2D/Action/EAnimation.cpp | 80 +- Easy2D/Base/EApp.cpp | 209 ++- Easy2D/Base/EScene.cpp | 30 +- Easy2D/ETimer.cpp | 19 +- Easy2D/Easy2D.vcxproj | 34 +- Easy2D/Easy2D.vcxproj.filters | 115 +- .../{Msg => }/Listener/EKeyboardListener.cpp | 2 +- .../Listener/EKeyboardPressListener.cpp | 2 +- Easy2D/{Msg => }/Listener/EListener.cpp | 114 +- .../Listener/EMouseClickListener.cpp | 92 +- .../Listener/EMouseDoubleClickListener.cpp | 2 +- .../{Msg => }/Listener/EMouseDragListener.cpp | 2 +- Easy2D/{Msg => }/Listener/EMouseListener.cpp | 106 +- .../Listener/EMousePressListener.cpp | 2 +- Easy2D/{Tool => Manager}/EActionManager.cpp | 71 +- Easy2D/{Msg => Manager}/EMsgManager.cpp | 1215 ++++++++--------- Easy2D/{Tool => Manager}/EObjectManager.cpp | 4 +- Easy2D/{Tool => Manager}/ETimerManager.cpp | 62 +- Easy2D/Node/ENode.cpp | 29 +- Easy2D/Node/ESprite.cpp | 27 +- Easy2D/Node/ESpriteFrame.cpp | 86 +- Easy2D/Node/ETexture.cpp | 5 - Easy2D/Tool/EMusicUtils.cpp | 6 + Easy2D/Transition/ETransitionFade.cpp | 36 + Easy2D/Win/winbase.cpp | 9 +- Easy2D/eactions.h | 43 +- Easy2D/easy2d.h | 1 + Easy2D/ebase.h | 186 +-- Easy2D/emsg.h | 52 +- Easy2D/enodes.h | 100 +- Easy2D/etools.h | 69 +- Easy2D/etransitions.h | 49 + 46 files changed, 1662 insertions(+), 1490 deletions(-) create mode 100644 Demo/atlas.png delete mode 100644 Easy2D/Action/EActionFrames.cpp create mode 100644 Easy2D/Action/EActionGradual.cpp rename Easy2D/Action/{EActionNeverStop.cpp => EActionLoop.cpp} (86%) rename Easy2D/{Msg => }/Listener/EKeyboardListener.cpp (97%) rename Easy2D/{Msg => }/Listener/EKeyboardPressListener.cpp (96%) rename Easy2D/{Msg => }/Listener/EListener.cpp (66%) rename Easy2D/{Msg => }/Listener/EMouseClickListener.cpp (93%) rename Easy2D/{Msg => }/Listener/EMouseDoubleClickListener.cpp (97%) rename Easy2D/{Msg => }/Listener/EMouseDragListener.cpp (97%) rename Easy2D/{Msg => }/Listener/EMouseListener.cpp (93%) rename Easy2D/{Msg => }/Listener/EMousePressListener.cpp (97%) rename Easy2D/{Tool => Manager}/EActionManager.cpp (66%) rename Easy2D/{Msg => Manager}/EMsgManager.cpp (78%) rename Easy2D/{Tool => Manager}/EObjectManager.cpp (96%) rename Easy2D/{Tool => Manager}/ETimerManager.cpp (78%) create mode 100644 Easy2D/Tool/EMusicUtils.cpp create mode 100644 Easy2D/Transition/ETransitionFade.cpp create mode 100644 Easy2D/etransitions.h diff --git a/Demo/atlas.png b/Demo/atlas.png new file mode 100644 index 0000000000000000000000000000000000000000..05e5ce1607c8fa35a6d3112258b00484dfe133a8 GIT binary patch literal 76303 zcmeEv2{e@L|MxwbidNCSFv-?}>`RtWN@zlx%9fC1%|6yCTBt19vV^BdJ=qJ{W?Gc3 z5M{_RWg8ldeK3aix@VC5p2z?HzW?`}_q^xi^kuI5+P>eBNAd?2LAZ$*y{`aaM&L`=LkV7xnV*;(XpE$NKx1F)LEyqm}3g2b~d6W zW_B0NMcr)dL1~bu;%0ARYGv+(x@c};X{*FXEgs(14A(lL^Yr#@g0V!A*&e*{%Zk3_lj*LotguSt;?U!X2W{ zVsuc4>>SKd(xTELru)UEP_pu(;?m+$a^m|?68ps^#r8{ziA#!zODOD@R}hy*&HV5w zuK=GE9n3B%oKQP5(;Y}D@m+RuvR4ojb9HqUb(IvgbFdH-mzS3p+b?q^0W8~eGAY#nE?11O5Q znb?boi|!Zur%Gm~b9L;U9juwGnVE{2TbtXM+d4UddgA|B&;GKVlbz#byMO6&F8g0Q z20FoD=KB6eer;_2v1>=C!!7`V8A$)JrsFBBy}8&4b4NR82UGLIE|7mpD~c^F{Y%xq8ZuWiaWYp1rYI}2UtDCr%qa;81#u|_Ny)wYI_@7s;#NHBhZ86JpBMIF@5%+ ziN)_vXEUrVm4Q-3%`D9nq%KKcl#(=&6_JvaG8MTfD`h4kZz_99L|k4@QsUAj6FG4c zGet4jQ$eL)oWLzHpZ?y*d;u2Y5LP?}qo85y=wt!}&`@LYV+r_?zj#SpPF{Myh^)D^ ztcaP6l#Gapq?v?>xtW}tjJTP!@;}pnnS`mdgq)E*u0E-&2xmC@73~O_P&i~C1zhwHq+3JF}{&cbckj0aK z;94A?1-XCVS^&u6$vg%uEp_LkoyO&1%ND``~%nG_$34J_~aH zz_kF7#gl*FS{$DRxqskV0LbFWKX5IM&w|`Pa4i62@#G)47RP5n?jN`o0J3=U4_u4m zvmo~mTnhkMJoyK%#qn8?`v*8)HmPyT^xaeNl!{()-&Ad4se zz_mC&3v&O!wE&RClYih^9G?Zbf8bgG$l}RAa4n9{g4{oFEdXTke$7ezAAGj6( zvUqY)xK{jnPuScRyd3Nb-U2=t;Z6c?5Ti_wp1?qmy8r~?z#GWp)8KD61Uc`Apr02Y zNZ|nlZL+&>{Qd|8^~!0esh)EC)>Gu=cDf^~tEgZ9id8E4*qgd7$&TMXM>%d+B(F~$ zigT}ApX~OjQ1a}BmPh=zb2Mw7RdXS&Hz(Z)a8p=%qgAMDy~6e52YPWDnS8t)>)3<) z!!HE;t*Cz+cv)ZhMhlgfo)=#<)RU5utx`8tPQ|B@r1g$wDaU2kG|;NZcsnY!&UPb& zJNP|spp=^p(&3EV>|DEPDFoG&R46W!i?xs=s8v&(sk<73S9L2LJqSSv2x4cxY|RFL z#DRa_LeQExk7Gc5FNvdL&1%yJtA<4PnIIhgdZWF{j2~)ZpKt|lXQKc>oPcI)gT&TQ zV}eo5kA`=qHP_o5Jp-!-Dn`b(@J|&9PFhsP?$(&#WQz)bJ7d+|9uF4^g3!z~=skE7 z0^Rz0Kwi0oJf;*BZ`m53j${mX*E&oLcNea_woeUWo9z>{4T`CQnt%r!VB_{FC|J%O z?o-~IT0-3w(i<}75hq(cRCp~3-=VS^vA_Cz0PZdlXAE}^I>SNV$Cw--L8~Cm4jyH& z;fk-ZIHxOn^XgAK?`si=BO9LR^Y`K9`_AQ?rmnMl5hhBXLEn9q0QaEbTL-*(+0eOo z<4$agIpZv3aH)EPT>zRygYJPC5MoA97{3{@OqN2tJxuAhs}!}-K2K6FzUu(p$327O z^r<77_3_#?x9&JGKj>9c0%cv!mJ8?G5bId-qal{?%CmZekho=Yt-WZY-FFzhJVnN~ zYyb_0q(bZyv<#KVZi2;5C~g0%PtZR!g9BUwWuf`mE)2hm=YpW4@yf{8NjLW@RTX4? zL88}aL1|K5?q&ke#0-FNaUcv6T~HTC#>NpxTS?%x{zPqFwhIY6h1gKFo!*Ca*b>;# z#9b#5!RLbgm~e2y__L6Jt22&6J$A;zz$BE%xgc{LHXJi|200usnVF9eR2{Sw{p|h? zD0r3XuZOG>DDVJ*1HaJF`iBtvHqZqcq)>q1{s6PAj}R2H5~sCV3Hdrsx~ddVm`!Us zjd%yD9zlb$Kszjv(9H4(2*QCU!XgNJ{~s&feFbQ&m&&y-rqR|=8-nO;l(N?&_rN}Xetdsc7&@Uh|qglk<7<$rC~Ms{t)+C(IC41c|; zB4KcnziXsxqLrlv+14dwG0!~6mf5;{<*>q4;*1+Ud)?D{x zQUhzhA~V*`!^Y*#En9&LcU`Oqb;mTx^XRk^#hRxi1OEaE9rE;1_eE{Z?KJ$?B) zKa!;@R(CU8!wGcSQd~S|KlhUNfiYd1)ZYeyX8>vl$Tn+XAc0#u07i+85b~GEpwzYb zWzi_O28=Gu7Uw*RO%v+b_mveS?VrYA?dRk48qVe!Bvf@mtfZ zCRsc=?1j9gy`f>mZ=B4=xf#|GC@BPTz8Gl06jLGy(&1x6@9Lp3_`2MprnZ9tkj2hC zg`mJQrXWYvA*8@WAAvCCYP9z46wgcxKs1O2{G3YEc0*DjG`d1F7eu3JoraJy%lSDF zFbA`$n!yxCUMCC#F>;2J_1V7j1OcaD6@xp)fnR7q%#L&dO(BLR(%`S(p5kT-00v<` zkm$|Vxom0lzB(TQ^_Ef)>FNprsOILst6P^H=ODEDU&9mJW~o1fvqymsOb}SI&PfVE z>ysheM>NQ0atQ&2v%r`sExZP?-{H1Uu>3p=Sm^FMq1${b?{oeVg(cNYpFpsAX#JM; zdNaCoWHY*q{ogB}Fgi zknl1D=P=dQAN?1X4=4o#GTR(LoAnV^x+oa!{h=8Jz&c~8U`|WxPe89YibxxMX!$Ed z*ybL?E&djDI3X{8h|uZXJ>~I?9WwsMX%kcautZ2$+5rVktoe83<<~)+YyOpMI79|- z`3>OT2CCnKI_Pvxy6Y(R>%z6DS$|>&X*Qq$91t4`sd6G!QQ#9(Moq+dB`pDdq-8k2+Ry{ zxX61K`@PSEZ&02h3K;qh($gQFhUCXTqskutZuRY>iGs)OZ7Vcge z#H*P<4&F)$UPNa;L;Y5{@6 zryuplFY`L_2x9gKV*{e%FGc`I5V~)CAl;=j$S3=8ED}do&8t$QRP-8GveTA0Ez`Ff zSwa)Ixz;0&W1SZ$s zXWy`4ORAO_ksWTH+qTM=Q`U&0> zp<%H`UIy`aZTD$!0nGS$v0Oj?^tRp1aTx&gJ7hDqyh0cnUeb!L8d}z=@MA=)`0a|D z%F5r@j4ImMui<*TcQvm|>Cye`?UkC4?eK!)^OAx90wwDAKw`Am5$P-J+dV_b&aMQI39qWB6^dLKdfTes+sCcOX{-clK*CYHswR_)1a8iz5I<_Ej{>yJ@H}$ReMo+ekevX2m6sNhj_agLJJlAJHWU&Y#p> zKh?w=)%NS@x4bB-Vvp&|`}EUcuyDnQW1dmEbx=&VTX_Z>syY4;v-{s%Xl@m;6N!^K zRB= zDx4C993Ji`>qBY}Q9?>3dspReFpQ}Q&xT5A^ssKyS`Y?jLiTU%F^45|+Ssf=lh~nV zK36F@V9KFr87KvWRf!i+gn6ilt^*6blMz~cpN!?`% zx@CrOG+>G~Wtf@QA<;gU)0V-pEHP?q7v$hb(6uo+0!mFhhWZt$ge_^3p5^x8KOQgJ zL3j{8w;lqFEtCun_er8qP4hRy9t>VK)l^k)^doLC2$Jl3h&+f1oC zgA6O*{MtaM?#A&ikCkmV@(F=;qH$FP=F8*r>8p^hdABUv^0GT#aB9;w(fzCTqd4Q;}whiYY zzoPid9fhpi=`;f0MyxXu$FXM7+I&(P!OcjXnn^drzAY!kN0RvWb zk@tnlk%-=m5{jwf>9s&Q&y~3CX(gOhLpRq~43#@sn?6Zega0b$-VSVzKPy3YU6uXOkde#qwIK)$vzfRSp$WB#K&`KyPgwCQ4IQ5;we! zy3-tk*^lO`?Y!r#r3WRB(AG)CiCnhUPYa5C9$zv1%7iMkysb-AN^P((%S+iyN^){# z)zB1QGlkM2M+C!fk#X6fjcpqkQ_2UIG8yCF3BulQ@Gz&{IK>rEbImi;hsqbL1$BH{ zu`Tg_%~=n->+w<_ybVpq5`CxW7K&B$V^4@NPH{XXRU-_ty^_H?hg33_xN!n|L&+%Z zgKXyo&sgK@C%Jrh-}9U+By|Tqt|f2o9xDGz1w%0Tri$cb9vSNs_uk!nn6A4LcYW!< z4x>@@Eo#$?^>dCC$}*g+2tz7y9RA zH})tG<3}i-D(NV9>#L*NNDpjVN$Mxnl!EAvLlYjgh8Jn0l#7#7xsP2zAt33=+Xp4!|FSR-SP#_ao>L0r*c_oSV2s- z%ZoxB_cl@;&U-Iko9VCNPY{%{J-B|D$MX794%26oUSZqv+>gH>EgW{UeVa}r(`e60 zv;t*AF$QU;p)7+W#5hl&Mz9~w?pqLcSdI!f2J5gpP(S^93NPfmGR-!d@Ydd3t*g!$ z^P2I&yL)-zRkT)lhL=-%0`%Lu*Mr>2z4?`8NNY01P5qf|Yj*0doJ<6{H>q*Rfu znimeGGnxnRLHqF;XTcg}NRoki%DYN>;0qFaA@FnCPweCe?{Vqr6&^+2tf#MiM;UO_x3G@K>IhK9}G}b@@A{^LbISjqxjcs0AO(t(4_^A+y z+gu9k$CnCrDctFGZ%!rVkDM(jvaH1?Ts8lurV|rmX?e}ot4{664a^g&?lT6gH1Ff@ z2Me$F?bVy6pSGrmD#Ohppnnb$o-3j2rH3zH{EH8r+eN7tw`m~|1w{m9n!M zW~gxQ2-!oUN2O*Pn3;1}Wj+ z&0W}**Va{J!Qm|_+E1!jT+Bs5G?N>cF~C`v)7$nBaY`QUocznm4Uz48GS#5E8qZ2k?M3` z%_ZdmA)lNN`a{C^$ftX%b}grd7K{*xsht{SPa98FQfcpQ(&Uv>@I*F(*xoUu@ri>q&^hg(2u2Hp?sf7jd&)8>J5@gRko&oDeH_a}sEE^Ke z5x>4J0ve8f;PK3qTm$xAYcR7D?B=5ozNCg@$Q*5Yewlk?&)?~^M!miwiE zLMJcF4SQ`@WGMdG>ct^VASUSbpT=njiN3^!N@4Fx2TKC~XQceY;ljx=rAM3#4OWI7 zWEh;Hgi~nGf>I~{`tZ{{LjYg0aU@{~8NSS{S}mQJ&dB*rzK~*+Zc5MEY+7%+k2yj8 z_nzE2G|sNmvDSZFk%~kaw=MVeJCZ{T?H$m>KxPHU^Sq}ltv?Z}f9zVbWXD^<2$QPX z$6HKls+N0^sIQiIu}{bohLSu8eOD&~$+<0k&ObT+)9S$}6F?{Ib{k1DMH-`Ks522Vg(NLaNLt>cH8+>N*`6Y|lOO~0pP?*@cU z3Po#~777&k=SnK@!C0g z8=yReH7a^7Y$y_y!>8;QM_fyoJfUYdvWH6qacY+AI0K>L8_Gub5|NGPh0W-3i5`qe z0qz+CX9Y$OO=l~Go#aMyA&}_Z>^SQn_&9Jj0|gyLve;6E#RY)tOkp7Z8ZPL4j)3yt z6bGV+vFUn8FG8NTwu2Y%B3*zmeQ+i2pq+ovPxl&(-;eDI6!)Tv7U=}6VfEf)AH^IH(4vQ~K!~tj$LhC;|iaYb%lyQX||&tRZiy zycPS1@-t1gDw6!m(SS|z-&Qn^6Ps%rS1P*mi(d!ZyCksp7~S_u@u)}P_oQWpuCiA@ zjtmu5_nUw%iI0-P;|p7Xm+!w?>DO4*jO+wM9p}y>{=3l$7BRwuo)z?Qu3zTLrN*Te zCkC6x4D@Iu|4n|I_aXZ)h5SchB*ej21rD-d0fEps2*ve7#&;VS0MT5ShugM4{5>&|APx`mhBYZH=#Db<*O`9NNrUl4SM5$xgb2r zK!%X-%=20lbb?#0*})UulMF#^^t$dAr5djv41FJuAP))5tQ*k~tX~+@IW*AA*w6v| z4iCRu&>0!J#gt^s2T>V=K5R<||Lw!^C?nfyawlknqT zpftL@iT_cgTHM$sYW~ROH8ZEr*C62uP7qw^&4$(@s-#Jfw@l}SmoUJ#CHo0 zoAX0&m5o_D%m3(M4(Hf{dkM*Oy8K4O#I=G8`cp&M-fzG$^`sPbPdnf(arHI5n(p*3K0IHcK#}u?6y#x9d?1gqOX?%o@XOUJJ@c#G6{A0g6%APWuw;oixjy5 zFU%DQ`foiNwt9!F#)m4)dIc(yrbawD046X5EZbQSn$ZydMcj{r@62zi>^Eq`wn#@O zj0xNg)^8fABL@!~49j;r){;wydW{zqaOrvwpu9;`+V#N5zVRAH9$3=m<{A5elh2Jb zU0+*`sjwdk;H1WpdvmEsex(K_tx7fiPUCjbqfozR#n3z*z)b!&)FeP`=(Z8Ukh_2( z;=601!L&gp2QEV;{wBDL@xD8vjd>YE^>b=D^D@Sotb;^d;%VYJqG7zR@+Pn2CNb{@ zejm&JqX$$F+iOf=ZF4}p04E=XldI>oj)OBY}ge0;|S393PYZYx=~Y7oN}lI`_f)u4LNo%H}l_)CtE4 z5BKeUut!bY0@n=uHbCPFVyuZ3983_f2cse8)T&-$bw@^ai`b8J>wuHl*ypEgTJ{w9 z5CviC6>4>gwWeO1Dwv9$isM$|$=X>NDPtWXW>adgs*CDn33vr`*CybxzenSMjOBqALHhBW3Vdj`VJm5S&zZ7YXGZAH$M% zZGiQFgg1gvGXaA27qE6+_|t_7r|HdNk(O`eFE(E~^paXOb@FP9;%7m-o9m8Nj$CQ= zp>EUfXpzm)qyrpOS_BP~za>#ljrpmttL&`C?gkPIG;fDthDiGxt$2jMuyd^+5=xwd|v=~iz4llYut6s*(p96|f{qHLN; zr}*?PUUWJX`;-*=?xwHBw~hFxKq%ddg$Ck6_3z`xlIeM#$*E-z4bBF(+l7=3t+xb{?{^=*S%~#S@ zjQt6B;@L>kKw!WU!=SKf)jgwr{v!QJ&8yZoE6<~@DtmT^w@Ud5!$IsK`6B#My_*W-01RH1~`cB+!8hk&%5W8 zjh?gjU=$xfS}mx$n2+Qi8dHDyQKJ9d9gi>N>>+ztN5#Ng$LjC7O6p8?0F<-a_{*p9 z$x_$ry+-jK5Bmty`DnEw@Aoro{~VD1p?5U_!+XaFT3^5}JnFoYZBMQ`gTp$l z=Tpd9G;%=4R2Jr6mpn7p2qIfOf(5K9ziRt9A9UNOjkxq!#KhLePxM2x{p)W#$CwxA zca=nR1M_@o`>d{b52>xA>4blg&^I%xzf5D8nDM9a1i9T2v|_uIwjYwqhO#|)kmxAu zB%y&@4sP0<5Ca1ZM{U0Ua)bKY2ZtY(4vA3VmD(Ik=!?r|0GpWx92Nl^v{&+PoQ?6f zWJ}i{2!Hw^Vs~3iYmah^U_ofkzY6-o+4(blTU6dDP+KTtT zF2jD=(u`5D#$aI%#P?#IQeL+{*x~3h{ACGiss3*voS-eS3w6p z+T}-}u%B4qzSYx6oUOPr$=)BVy@EGy^m^pxuNogiIx{fjhBs#pmH<}PRE;Gomm0tv zC%hZ(>s8yQ(Rir`eu{r*n!EE51TFcaAaHdULKC zhvQ=N8xe=zzte9XpJ2Rl`Kp)H_dVi-CMP%vavZYS=&HI~h2*`DwQ2*cpg}`0MjaxM zx8tDeU^s?Ur7+++UjBqyVRw9L4MOLlf!C*4WmSk%Kmc+O;Pf6*Etvf2>w*=!5%;OO zNsZ9NdS%WLD z;EnY=;;Nq1c02Q~pY$c6wC6r&c1kzKMTFZCc0Q!?<`4)kJP0YC^wm*Wy<74oEH+## z*^)oujRiICNUIjsBvgqUh1N5`l-X<;o|gIVpuEXP0j7aZ;Rd-OSHeJ*mtar)WcOLD zH|dHzcH-3c%;Ry&0##J~9l~sV-fi*lLKWC!f|Pv;J$2kUGzBJap~|Y&Vm(%ra9;dZ zQ5DbUhTbn#0%NK(c#?{EQnaq7sS`FqlGAo_XM?8lzyojM5`@kf^2(jivaJCUswoFv zB~__0?CL6m>j!8x%Cqh@E<*4>~X5wFL~ z)uC7guly=qpXpcTe}Rt*&)cTkB5vSIrfW|db7Vh<5IUP%e5R4WlSB{+m=ABcTviVK zknD9BJ65n=u32#T@!SUFla6Lg&0wEkL(2|}GQ3ij8HtBZ6=}YDKFB7b&NRm6;A8!m z$H#j>uSqKD>cHo;6-l8}arK!z4Fazi=7xjWJpAqKI6e(dpRqbI&(I;=)i2tIqiWB^ zw}Iahf15;5vECqu6FOX47Mg56sU)@&UcCG7V8a11&~Gc;gZs01*r7_jHEiEI^$0)o zhe%$njM#_C^kO<*3875;$q#OQNc6r@$mT;AwKVW^`VeDgzT;&Ll0=Ih1eM`QZR9T#fT2oBR3iR-bTvrFx#^bqLTqTbn+GucBZo<4Eec zH*&%7Y)~sVWXtzcz1Y8^!Ckwu&f|tQ3!yai2+Uy3d#b0&?$e0ibo$=Yi2lyZTsTmS zM28Xj>wd<@Q*Y#+p}D6a#99PBf*4!~9W})%HQ!Z?Sixz>#3^#GfEZZ0gEh|qBm}$* zmANbP5Y!(BJ3ZqJw6C6ilBDaS`=ujZ(Mxlx-y*yyZpeQ$o(~G}i!`zg-!?^V8@%N+ z`4mKf?c=$;RN*_`%h+*j@2}PNI-o35^wPMtxN2qDwGOtpbi3OX^!TJ79wiX@=z+Ua zv#4jEPY#~)hz(n3=Ft(EOe;tD3i3qX?%LSV+iX`l+9zw>TI0U2GR<_GIWhBIR&BL= z&uUAh(VG}ti$a5_-9zihw38lSx;JV{f~|DqsA14`ur%}6isO#DZqs{7$>9a?1k3d0 z`h&X>!q<^kkF~`bg$|T8#s&7op3G6IrO1~^RjNYk5tKS==(LPk+~nuv*0O2GJF=0V zq~L9JT=5#jYme(7;sn?4gx~=)Hl4Hrw{zrckzm_ilJ~AG$23p+J)axa^*(-+^ntHq4H5CyS>A+=MCc;ENL21swp%_+Ui?F+fLH$0D{O?=AXmR z`rCbdr1A`c_n9<;2_D90izAs3VaUX1a`-|hOj0E>T8`E)_B9YiwMMhG$YpZ*hwDYw zRd-$_OrVa}BR|+0)*(Mw8`@F>hdk9|6iJ^28w+H&wVIYXSq;j(D?fzE8q^8J$SE8z z{;YP1oGEJt)5w9lYb9iWtHs^m}rObeT$uF}jG1a(EBTwGl@ ztye(=S2&J+oxEjIo?|hX&y%+iy5WsC8T*t2KXUW_)19 zCBAp=D5imdQGyfVrRVB`_hE#-`9x^OG+_xT<8zau*cKBF9Y6VdX6q?;f2 zHn#I3bY8n%q1s{r(GlKP)noSc9sMR@eRkqZ!9FiAOqjXRonl=pi#4|BZ47(;Ahp7y zKp*_Sg?C=QZ|xe-{UB3TS1)+Z`Kj)i9ammr%A!rLdb?z3z!cYaIW+mexAsrmy@Q?p zF6Xk+F%kR%65mpeaYq_brAyOjT>kgGRYFR8B9ci>BHDe;yO>0^2~DQu+%SstO>V1q z?k3Noc>aFI7tZsLS!2&$b^p7@kJibAls&M{J@ta;bJ}vs2_A}SXrb~_1RF}lfNJ_5pKY7(Bpcng^NWn&_>S`s|i(8l>2qsUGM40u$$6 zs}iE&x_3x&M?ptaVDsP$-+M6aZmVV^b`+gypcy@PDk2=pZy~*L?~m(`<4?VnRS_(S z;C%U2miVcB#n+Gf8l6p)B=o_UCq>+4m}PxGQuKzhaXwqZ-M;jvOJAD;oni1Q<5bu3 zkh6W$R`w4bLN~_5rrB}w=JAX8UdG6U7%)}LG2$K&a%JozlUKgrPT-vG;AO7e)HXZc zB5F1N7^!i$e*BV0%ewdLfboGK>9R^wjEmv}+m2qh+`|ejHX#h^`_IJ!!Xe#VfkOw? zV+yN3M|?@?S$#1$G4+|i&8@+GNYBH()tY? z9efa<-KB`<0H76nfP(~hDmlbL7SS0SW1!OE{D85kO0iMoz=sLC2c}qM06=ujSp9`a zVJ?7Zk_pkEUaqo8kQY_DA>T#?K0ulc<*YG}$^j;gI)QB8yPKzf(2d*djOiK0`KH(g z4xQ3z5SWhIe~MS!+PPQ$|Q#jU2i}edu>7wdo(6?T)y*iyG@7%@WzHjwIkeXig-6M@Nveu z$I=zPpq{UhuBWgUiCPM}m=kykg$jit<4WcIG~n2HrLvlKl3 z7xBgjcyXq*Azv*!9Dj-wdN6(YXX8g*OJ9f7>y8imH1+O9^fixp$#1=LgzZ?v=v_d^ zbor+lhS1&Z46#9>__)S4(o}yCZ@AS|yY9Hp^c42opy$c>du&>N6{EVw18y(RTaG|q zyajz%QiWKvE!bU!A0Y=yc2Fi#DyCblYLh6$<yB97Nb=iFJwi6!Bk6r z_rdRk)#LbMlOG6LZ69R8%Noa_FT6%VBSq{`ZUeE>HO7owfEj#?R~kIHhUN%b9C= za3MkSx?6wgfkBm@Q{ov~(?ZjX<56QD4r0eYWoJ?P!CL@ZRzi`@9&1WpcJGCQ{ndg4 zubTyM5DtyVs7T8)ZO+t4C+XS6Tmum`O) z^ky>Y?qkBH{HQ3)^PQ2Uenye|xC^rM*S2uCgeH#YfOpsK+ps+_VLOrYsaexY>CyR3 z@ol4xw8UzPDhdkNui8XEo;(>jy_r`S0p2}f9D?{Ahc6#98jF-Qt2b8J$i zEzmRUO;2&= znEg2)T5i`iuNT^=o-3nL3+Bn)^$+itb}`19;}2Bs13ME+B`uju>+UdS3#R(z8bm`8 zAKlyYx(x|l+AE59kZcLJxr^Va`v|mc1+2l7+FuHo+xJ10pM!*_M?1eMt0P&3*w;gF zBs8oU%lHZc)YmfJ;kB}*Ki{p+X^6yJ$j{YMr@1t^TF3Mp$ia;AHtwMZ*@Wi?O4HEO zhCY=$EY7$-RsFd};6tJSSJW6WT4#2S-&ha>k1;6$=$`dbWOaZ+&)xAFZgj=#hVOOP@_vt_K+U>v!Kd;8I?Gh+@|9*O#Fj zd?PBADpR`mR_o=rNgNNSj2x|f!33**q#Ax%l$=6K*Dq-np~!1Fz3|k2D_EGm-8NWn zjcjRaU~`sSu?Gm{XFw=_&Tus(HB;XY7)Q#zr^gkOXvL&^SnXqP-|D<~#u^-E>+;Q`BHemZjFo zr8vfGTdv7E)2l99z`nQd)DRep#{-*dHd@J82i7+8+caac_SV%eVYo8#nlmpo?6Au5 zkG93s4T0O`;L>e;cfCNBQ_ua*vjCl~?H0G{N~_kShF~(~_O=*_z%+iQNglo+I*E;dsB{0;>05PWe*^Tjtc$GuQzM1G<(6~z>h}&r zUrg6H*&}Tkm>SYqztyta$m%w4dUk=v`GT1C8(sw+fI_(nb~Fm^X#Q05 zxp`lKX^gq6^$W#3*BF>U|GPl{rBCXuvUZO~OSz`|bL(5&7P8guwFyZc%_;4ycW>CP zFQy_t_BSxK=QU2l(v}Jn(M3~Bd-cs#>1O}~k)RB=qyIcsV7IE*$V2DBp9d&4E#G>H zJ;&o40dVc(freWMLLL`CWeL?;=Vs8Qi)z!QfB58>CIj29U6Jse*6s`%&1dA*nQluQ zslORke42;>$6ncEEumv0HvTrjBAKht-0q+#ox@%(N>O~-65!w4Y-R32JKylF=tz!B zdWc9SaaDSGMEvWSl-9diu?P$9Cerb;U&;=+z`zn;nm?usiCiJ= zzVpqs{QBs|bJZ<;tJRGoZ$3`1xcT_G`Mb|wB}^!Xn1sjPylWS?GyG<{R8<&E)Lhvz zT4PM&?wljh7p>a618oMKN@Rd0!aM8FpL>;iZeyQKP6>Qs;`P2iJ9TXtF-Mtyo9T0N zQ|oL@qSQ`eYC~^xV`7mt#4xkAnXf|(87iy4VMpF%`H+sr)ixYI`-^J zoMn|OwNB36s0hD_1opkgz{pDPjbYNruIC*vwRGNUhbgXei$hS}=)fmQkc@J$8#-nw zmw$e1U|K}{_Q^b8Kvgyu&-lm%u2?6+(NI^UnymfJhYC+q^of zs6aKYrIAmYYEw3*)Zmh+k+Z`x>roqUq%z=0FZ4&GRf$M?@^Yr{o>9o;&fn@c?VCS#!M3g{?%vaRk` zJ8!NsKg}jJoSsuxUZl?(=8>zs`5`nGMU>SQC{!ii>vEGPeS6r8m7HW0$`(}gE0s;; zFR6?f9k?^8R5n6?m<{zGi07WRtQHbjF`0FuGO}^#1}7A`)t&#gN1fs>K!+U8To{%g zzK{CpxRMJ}BuTj8`6+XQ54>~9+FU0e0;gc`_!ImLI$MuFxiN7~bFLnL+J&c?|3HxK{pL(LkBb-(Rrn8> zuFjIILp27bgxaXrl@Vhs%3)Iaw3bO;4{O`;%$|2&&2K&Bj0yic?b(S2MUlWf>H*o3 zJkud5n8wSeo(+aGPM%DoKL<5nO6%-)&>M2fOUK@9A}YQUycFGU+iSE}zkpaCadx}N zU)8BURODYB@piDkXH98AHRj9m`}>Y<91jN}zdSK@lw?QZCsnm7>8^WBZPc=7$s z{JlXoI)O5N>h4DytNVF27zyv8Loi*Vmgxbo^bT-S4wz6@MP)eOw3eID1ShY~;E4WC zhf-d;Rdf?k8uLM>B+qdux4rTc>HdLL#x05%e5^0cOrJ){N~Jr~x4-l|c;j7-F`iG$ zXFR|&X?*9nCg=f=jRt65B6d6n+JGr8O-`O0>RUd}yDZq|BF|T>qgUZE?mXsANNw4j zA3r-^dYCX2x1LOTru{bhIlHETys>T7rh|~d#aD0bv%x*B7pDuma&8*iRFf0o{a$eO z;rsag6nOV$#zbdlbN0$JS5cs-6*y|PbOr5ObZ?zI1D)=F`rT)}q#s?+9gK&L0hpiM zwV8^52@_W0iU}DoJefH7S~dx$*4K$3yjs1L_MVp7Lhy<9#Mb7vSH$22!ecIJc07q1 zoJgm%)u)yZ6c1E_2m}+ajCQ0?y`td}n>fD5GTI^K4Cxbjgd=@TD!Y$cXz$6#@7`cY z3M)`ZE;W33(wfc9VrYp{wclk=i+gveDH`&XJ05a(1XlWwD!TSg1IwO{aj2Sl29wM> zz085CUd$k%tnSkD4NhjMO$6sBFkw*AJM&E)?=@xS9r-{FYIEfcH@sPCxAjV5){7%Y zY~##c86UC5tBlYJT2DEBfWKs;$f`mr52p0-oiLqqO*E?8@hlSfXc$cNXu>Xlh zE#4wVz+_jiUgGZ2zop(AVXky;ROde2e1*CqyqfAip68*ET&4uzkd zYP+pTJRL=L^QO5PE#!~*jI9a>1=#1PoJ7#1|kDzfDooZ^Ej zB@L`!HQ9#)tIE@V-yji368TYNy_!&-P^A$cqpU6~3a&a<4GElMeL)axUtkX&eB}<< zPW|o)-?4$`dJ-ETSKFwafJ|bpTOJ&n2ninqG0_FtxV4=;2xrF_J3)HKukLH%y3(m)F@f zsEv#~-rE5vH0NmvDYQVrsy*#k3wLPnx8gef{^+AYHs0tDf&!h<8OeB|(Dpz^sGGKg zm$nS!G2mFGyi`_@NnMyw^Wi6D4&=_|tz(l9f96}hrMfob*-%fT&ZcoCJk8x>;jtqx zzw%;HPzH^A6hAl;7gjzo7-#0v%-;@PpIx=z;PR`F{mXA!f#bO&-0KN`>m2SBv`lQj zA9qJt$jf$Oy9c)-7}c=9k7~2a+}O1U^!3|d*@b?>hE{oHCAq(OkB|D0S>9u8*4>uD z)mw@>w)v+PKICq58n13R;E&uDC+7taUp1h1D9A_8Vmqc-N_$b*f)0BI*K4A}+v%Q#140rcZBKVX{ z`8$+M`8{}c4BuI4r)eJf#$eje@aoHMgLbOFYPv^zM0!Q3h;c44nfT7*ej81V>PP}T z;J*-R1Ard{Fv^Gze@txK89X?hGnBnlfux@ziMhQZ{6WWrvgU~VU>sP^aE&;J2Ge8_ z-({9eK2^=-_bIo32ws`Y<5<JA@|iOQ9DoP~ z$?-C$xL|32R}1=B*YicB`fAS^BiSF~{(+?B9-Cx8+jDcuUVApy!OtY8YM*qu{knVH zwd$p=4mUVhr^}i@chTk|%4F(I*6qwpY6|Z3dgX7g`RFJAslJi1A1y)CXU5`)4__V6 zwKVo7ag!(=N@brsT34(gQw$gn^Vx)7LPuqPuos+`Bk8|?EUGFz?A89$doVm>C@$=S z$Nh9l<$e=q?#~%!9(YfI_9S<_R5aq}e|hE2`_nWKdhDNtW}Y>{SGi%|_vURnnR}2H zSO3cYmK|S*l!lf@Ppse5tjNSiSwU*=Y}`BJO5#Xl_mj~{N&HVL88JRoZ%*9yHE zQX;%q+JxDEl8X?GX@6^^Le<$~*6qtcEg0=7`HQ>YqOlLW>A?=J zEasMy59}0s#|7oCe=Vl_CAI8ZBG}D-zS_s^)v}s{%tZ`*cduDYe7JFt2N$h-Uhrgr5f5!}?u+6h> zr3PCeg735Y9lI;hydt)HU>Ctia#WO9@@WeHQ4Y_RszT+UYN%>~GxPG7NYp-dT{|!0j zwP7^M1BWL zPoN;M@dXMny?Ev$xIu@$YIiOfTz!Uf=3RaUjesN@Am+Y1_=sb6J5zt|U4R)W<_g0X zy_x$V|BJFWfro1U|Ht1m4KhF{^jOh=75 z06Ls;?tSL3h`Nr2dcZ;qWh$B$_NO1JV>WnT4CS}4!Xo3NQ&JP*;AQcYAi&QfF_VaczN-^`Muor)E z!{PI#PLJ{J(ej;RuD`uZ{tF8q2D>4W(LVv^WqzPoAIa0NPJAjr`wcg`py-aQT0n`M>UzaS4V9Fs{v< zAaIDOKi~N0BEm$SgOR~>F)l`jNyR?>^929gLkP#X*|{%L;lqp>rea@%x9IR6=7Uh- zf5scwr+;1qdkMR_zwM&GOgD3*{?|o*8yj{RG93Tssm0EGcRgaX&H8!S|NM*50fcc4 zDm3g<7e<0R{`Pr>urVeLd%K#a#sBwprq8cBV+a4o9Rg3E+})ya>Q_Aj%qRBcdGXT4 zGv@iXDS+8!Ou_#;@6VAzLFmsf{X^4e!kYZgy@81Xe44SCj2Xbz_pjqo6GxkW-rYYw ztEivS7xSjy$`Yk>?)i*tl_^w84TO<`Kn8-N*@~>^Ja8ELgB!> zBIr50co$UaZl=k==VFd6wdMCxA_h8zJk7*l6yV=eMScx0i$uS!l5 zAaD4j>^Wp%sJ4N?XgEj3CIA)++cNVL-=PW&+Oa1AuV#Kg15_a|Rq{ar=<4L1sESP$ z6jxHQk23caj1$|jbUcy1HlV1>ZGmFtnq(reVl{PGkVrqrdXQidHs(+32zEJ>q#nXq zP9-p^)#%tM$aANFOP_;3%Xgyg+M|3sPGcn3T%%cyw`k}fSBM~flT>%h@#K973QA~W zM%i{+f#hX$_yRPbBg21;F~R7Wt42KsRN1YCufG?(`Y^Fnclliuv1+*gkq(aYbWf3K zN&m_T&(ZBF0_5}i5Ononjvl*rP+M>tOj)a6gzPq*e)!1|n6SH`*@qw2ZOS{&Q)U5s z!$d!2Mx`A$%{A++&YT3oImTGv`V4``WDL1+A;qX!Xou4_Ua8ROyh~2fr{M$_Fd*;hAhT8++(z2Q)7;x8XEx{cy2Sm!Lbg*|NA`p zAs(yp2WY$ew^xp*8zOdin--lWPI?x#Pfi} zlEmr7AIBgVI^=yT5TI388L4qCYq zEDUd7{Wck5U!ih~h5qF8N50vvm3`r!InLx7F0@1u>m&-=2b*$CJN|S(fl-N&IeNsu zAkxk$H#x^+NA9V!eNOD6+yj$d4~v#UopjMYq>O9bmR%X_tc5mzm|*s6WiB2zroV2Y zumZHGLG@e2z_{HrjtQ?Sw=Ifm)t-zf_nze%HrD#=S+0+)+WPDVm#(f`sZUVL7~#jw zFFiI{%+t+J)&@6tGmnJ4?xG{n=mM?xyukU?S?09N*_6M^FT6ycnu$<#YYLr7ljOgR zlyUA~*Mf`ruD~7fqvq$9Rgwom-hb&|hFdVVU{p*#RRih9L>%;Q2`v5Vco_p`Oe;(- z!qnGpc^_XYr>yoEqfZT)Dc6h%hxe&u_!PVZagbkh)xu?;j|*vZesSK?I*Q=mlGdcgQMf9W4$!pKpGCYj% zO5M!oz-t`83m0>U^YTF*q|97I-8vwu-8EMh`7xU*G9(4N_HXNb1#NI{3x*D_%aIDv zd-UXsBz0d^W>_@8pZ<3Lm?)1?X6h+ZH`s6>edKv30e)xP8uM1G_*tkAgTj^SD< zGq*_NL8q*j2@*DQ;utNm<|dc$w{^wlhs>CiqNhik4WYsDe_SGtKz%5TT|(&pp(mLe z=GSUL8#tlkNuGHJZ%^c9l!-jXRLR0C3x~C)YPfN~Pc4->K>EBrCm>%E>gRL2wa_cz z$)uA?%Ng&tiiMNYsz7)(nr$vsZY=%CP4FrqU-?~C|8oc%aJx$+o{cu<_fvkT7){=3 zn21Y-c%m&1qVk<0|FLM8Y=j|;z4+EksHin{wl&y?S4=v+-R?F;? z`@eU?O|&6=AIhHDA%dw*dIk;c5dML?`v3gW<3(hs-uD1XYI5uglqOPqf$}u6(XFLVqkv{=`!6dcmCrm^dba(h{2V6t_S@*K8NFVxlqWY`0P{LX~^q%2TzRN^G+99 zho+bT;@q@QvDug#16cqkS?qA@)8^;=JZXap{i|u(Q@#i#1W%s1>wQwg+k0X(**k7x z^b&l7`ac(X21>SB$Dm|e{b$McO0=7Q`mE-}WOdQD=}D*P*<*spWL7?Xp~@^gmZALF zLi_)6PM6qiN;JB%aJ7 z=8v>M2jtbTdjG>x`B35Z1Bmp@Nq#|C9>RvrX_ChFRZ`v!y%MRVE!=4Dd6=Mimz|Ey z6&YTD$O&W(%#QA!+2>)8Z?2B7GConIHhc6uWlF9SzKOXR^j{`}jLFcP55Tz*z5L{z zeC?Vj{pfSraE<2JtMM)1Z{X=v_zd<*I$VV@S{O6+J=PhGxy(M;%m3Fuv9EBZBA!9N z!AqCNN?gZhl#T0zm2=zO$Di@ly=ptPB*uu8%%eGPQ2= zkr~c=t{sNhv1)oCX+p5q^ZMlXo-(2W{+EzplmFM{(sjUPSWM{}Z1zenaPIH=eD|#K zNfzq!^LOrkdiGA{NFCuL8(lri@#tQ=`^fc3cKKo=jx$=>;OKW@VM6iq>zVDJG|x`u z2Ry%P-!@Q%Z@uX~bD`jSWlPBD+BngEMJ2sG8>7|N;k&bracv7*B13WOxLJ0Hx141Z(48HlD8{cSy~@E zqSo??)0PH>Z{6xGVRK@}#N@_yW9*no{hHpGQ=XG(;k$=?6nB&VY+a5IVj>W>!B zT@Bu&eD&`Xcbs+>_A>D{4NfZaK6WOnAoGc#iG86FcFY`m&Nn2nrY}VOL6KmfzPCo< zXid@8{^{Y99r6+!q5TEhwG$=AO*ea1%wE&b;kb?+#P2hzl-HAs^KAO!Dh@l%YWGEs ztjaU5J&xH+Hm0J0e-RifrZmh;M?8-fGP$3x4#yvq4tpZCtLem-7$d%XLTg9OmJaOb zo~m$kp0TK(wYuKx{rKhD^ucGap<1oPcuUw2t##|II)d`4nOtCG`tU#QgXpaJc9E^Q z-^Rv6S2@w)t(mtT>@+mrl8{x&MIRg0<2i&g(`2(H(%I-;_TdX-pBPYHuMr@1euh@n zBv)GZ)@M1yqGiZWa{xMIJ8}ah#g;jIrozAs9OD+|wafA>l-s|;?MtDN?S3UO6vIWo z^PTeQom;4#4?jH2h(b@@B6ios^4JR+8p-X7oy?9on-(EHs~jUX^gM59va3+M$h)u6 zap;TpwNRbe(1Ov@18)5Rf;h<>!~9NtBV5&xgWqEX<8`!}U0OB6@Va$w!Dj2+sobx# z<-reTf~UIsqCf9C)3UKLcs4~rdFIhjN8~y<77>bvj%>CWmo(5l^JHVPmN?F8yQINt zOz6DI0_v;Z9Vb!Oqu2cs&4<=$ZPWkIF06@^gqJEz=9NdG?9-JYwSB9qXF!V1rW?(4 z?e6*_n>l)>kQA0Mydz`ftL0&=Y!aT5n_@o^vI~ zX?8QnNk&yohNH;zECMy%yXMoq%r65644%xc$vo|Sf>^v5Hq%O(rmF%7Mz;)+RxY_7 z5O|?sa*gt6rNvZ}a;Ute_s+gZ8WDsGb2iSw&HofM#!N7cqXtg06KqXnDNk{PaFc+9 z&h9W|<&$Rg!;VDdMmldoNIKAWm{yQQj2A#JIeGvWFN8$!bS}CQ3*aa4h$6H7;KDSvYD^ zHvZbjAL~V;Dr3X7B~iD?3{3NDhmLwnzVT*nea%*{R8vHZ=Ud=f`DQ46v}t2t+0yHO zwEMpdJ;QNTcs(b26wx9IM^rVz;d2@>b8{Zitegu?yYVeZE;G{Irn=(&m5_Qd`|EII z2_a0)>iN=;Ckq{xltP!2aj5xZ4J#^bFj*@IM}mna>I;Jf712qXxu$SKnzc#>_t+dM zi-pEcr8I3jd6999bb~4kUQx+Ye0AG&R>F?=cyi#dEEs zPbAzf43CDAg05Y-cgLd)v2Mk^?=J(7;bEC@BgH3msh(!fj_cKuo{y!qb;3}$OONLm z8w#y50^_=eS8;Z6@TG!*qORfPS#`A#D9yF5eU|d9 z8ADfX?rx3{LX=wvaaAr~mwnOXLWjZ9q}2qMe{AtG`Z4pPG4sx3oW-tDWg$(}%TpYS zr)r@UscS_7-7n*&d^{%qkSHJSnvDSc;9ZfRzT?tYKDY$vnP^EGlbniJGW#cD*V$KoQ&Fcka7a+kpt`SWE! z(h0ko;^|=hikV%ZQ7DRQfw=4LlB?(;gyg#eA=E%9S z$M46t3L{5FR)-&;TF;J4M#tNf#KO~Cw&8lWOBu=Sc^%I5q*5hyab{Ww95J7XW%@|l zt&}(Zh(Z` z)-LFd7?^#Nzh7}cYf6jy8(z+Y7(rXi#e|N+Xs78)VH$9DaJDyP_ZS`zdPFR+!}DYk zii2>{LWI<%!J)POW%XRp-HLAiB}WJ;$E+!{#wYtwy=R^ZC%!zZlVFO^IML={uvKa= zejt5x=I&I_({WBT$VK;a$$3?h-+0WR{g6TJ_F9?2MhCM@+wGjjc(Z6EXO1H5Q$p^p z5wkebyvQK(Jwdk&?fjFVn={-dc3p{i{Y9(?mWmkeAJ4 zX)m$8_;}isv({`tl4W^7(i96lsHf%{PJCTeqE7=s5|pB|=^uMOs2SvR^sMk~Bsg?| zle|TWHA6^WO#ETP0i1(JcCS3Ft0?9&(YI#576MQ53V4!yTf~l)z1FN(&N2K^nHs+SyG=*= zR1{3ZHG@<8qRS_st1w5zM8NYMi|LN*Qc#un#H-a}76#^i%_aP&*)av( zrAOXq2a|t=8>YC18_k+6I&1oQW(rzwa5A5TI2Q!{bi95=-jb}6_XuVs;#k0vFmFv` zWcIC2x)N4<<9fB+78mw-z@<;%lZ6&E5OlTJoL`$Ymwws@tlKbm5$cChDLqU-!ot_T zxKzpmoVD&Pthz<^0dGRWKd>8Zj;9ew=ICSu%Sg^HCDx4hTDVNw)cF@8f3W3zoeI#nlV;$1iKWcm{Efm^ynWwQ7_i{hC_;Kloj7l9B;zn|{IwX&S z$eA}zoUek0o}94Qaqvn?lYx-f8U2d+@F`>Fv_YgG;u1pJ%6-STsZmf$t7KP>&vR=> zp8V2hi>-Ualhh72-@DLr1dtta)>rHGU|1D9) z^nvFc8;E=9x54L7uutB&cANBFVmzf#=HclwbmHiAN$++g8nPqOK~5)jTgNDEHpj)^ zzJ28D2J1*UQS}1^Hu}m!v7wSPq&I9=l6B9;-&R$>7~2mam4rm|q?^HJIOnRBH&JAk zN91cmrPo1UYQ!gD7dZRaY7&~H=voluRYRnh;pMwAg@4_ngH58?u~gyABL&VQKDI1n zLq^Ab3?)$fcOu`SqW+hKq?RnaU{=MEshI=u-Q#Ore>e>lKZ*;zKfWVD6jC|dIF+gX zyYlV;P=|qf`iVXL^!u5SH@%etde-)+B4)n$?V^9&Lm6O3PH}9+IlMq8ZrhiksKoR2 z;pnl_0THlu6ixIxe1V+!J1 z1((-H(zJL>E}?DjmI^d;(UV!I7ysL8Pc5cDIT(&`Hrrp*cV9A*wp%_txdKlD_!OV7j7l7{~6P^ zbWq$BbINxKp~n@sDBXr_@uNvZPn#5dL-Q=pCes2n^4>O1iL1J|;(Ly>>?);kI0+Fh zZHNA&4Dg1b(&jbq&sdW>xD6+5)c6ggAmz;m2+g4VDLlE38|~_>E5ACvHDJ)a(^V90 zhUpAPhxXnwM|Py*;VABg9_g|g3f=uCIQFGN2!zzfmdlXVx}Q)ySfAPN>Od@hc~dXb z@wfyr)B4)Vkri&H&yGZ)6QL#GaD3F_Z2}KysW`5x{cia7(lWFnpAfJ78@Bs1fMo6s z>Mc#=Y;#tVLrV4Dw@cCw9I4oNRp_a4(lYLBgIls*Otn1|h4P7+d<(3ybGJGFxqHXK zYiJPPd^mc>Bior*M_Tr=IR}k+PQJ5B zMs{O0h5pCd<4^Qo)~8+n(xlAbGtOrmm@>>TCty^_v-o1^M@|s6b-L$g&AdAS$bn0B z?Zntv!E#23V${=4BQ$rqM;%I1WYtyoTaV=UAB4XxyD#)Z?Mi8E^59B{747ts-z2x73GFn+bGBSdH=pQ*2aH~;(_6nL|3q(OK^URl!;WMTs%zr||K$LV(2)$J z=W%0Ph9jt=COx4w9Pi67EZ91Or?U7jBkMa@k*NDOKV+B}1y;#6DSu{4dpa$^N^tZ{|gjFIg|gnS*BvK6+XG7n2r8|&7k4X5iRz8 z1S*JpzEI1@xb@qcCY@NQnxQ*tmhbh3XY4w8D8`AOlJvQQ`TSh}uQ=ThZOs4fZs6QC zl9}t6yfKYeRN`QZ0CtRoUeKCO_*A{!GeLR}zjfIs>!T?~pLLWB#DwEgMpmLdPKw;< zm%BOvzPu+Z4Y_PI#kPo_Y5JCwWH1%(Hx2Kb5g?Mm1e=lq2vXS(YmzeG*{&RQ6H*6L zy@zU|`xbw`6^(XiX0Jywt>Ca|0t9o@JpwhSR)=4FNzE=JT&uiEB`6!$r=gXvLqaPPD7Eeiie8E4 zh*Y;~B?6x$2vu>>TcaL!BYm*=z$hl65qa5%LT* zz1g?*&A&dsTP!~Xswtc_`|+VCs2dadn$PTd(x|xg2a}}9J6_< z;p<}K*C?m5;#7?}CA@64=&7#DcRmVPSu;){z-_a4#WW?PTAF!vKI zOr!5%lJOJu!m}41J6DDTwLiLh2dq&5g`TgjR$Cpoc1A53PUYUoSo( ziiN8P7jM24yx4YCH5MOk-bHi|p#f%24E_bR`FCahjHQ^F2k-^+enzBypTHEH zx^$I@LdiD!<)5f4C4(0b(kwnCc1Ew_5BrR=U5w#m2For#Es(O-Be9y%*#EAv$7Y0)JT^ zkXR<;K{pKF+PCIdMe{a5;G()uv^_BTGzu}(w9|w0S||oo_{9g*fkwkPYZBGyKKQ;Y z^h<0{-_lR{iI}6CmVTl;Q;=jkX*~&@);0kP190w&@eraT(@L6aEpiSlSZhiGn0Idk z0;LRo)MFihM>ZaMc0_YE03{I5)V&HvR-rrioOs?%?*+QZd}#Ls4U2F;eW%klg==+KsG!+gvy(jngMe}~;p(d5$a8x4L_h0OopSzEllh*YTLJ~TdvstAD zwu1X3!=2(=z>|?>0;or7&YO|fkt&L&6L_+TTbEg;_4e8Yxy*#a4uD#%; z5U4uOAXmb$j>`)O{}Xhh#}xakBCs>RwkfuE5t=qek!rPo6-M{m5TBgnhus;hFMJ)1 z*`}U>mn=P^4n27@^7w`+=#hYnzuVKB85~OjLlL^Iqp%?@m zuVJD|q>sDtt&gl0td#y-Lvgzr0Y2tL|>VY&U9NL$r==mx|*H&&f~<^7@Oz}{N|f&i74($Kd^g-3qPY)Dw8mhgdZ0gSMp zdPQ2$?rNQHqy5#&{XQ`Q$U~D?`qs%WvFpT}pV2rV{;&g-?fK!R3D&|J@y5{aXtq{YB zWFC5D>hDpiFLPB)BF58F_}2=9Bc-L0Qp3N1M}p5G8ufWU*8CxSI4M2Z_0tmp36E`u z4uINoDqN1^)B_ijY~xdy@=!H=tNsV^sU?RoEi)HNOs#Nh6s+Xc(PHn7RHz|He&wS3 zwmJZQI$6^*B5`Ugtyg~VuqiI2x}z$obe$UwO@4-Kua{Fw-_cwK{B$-{|D!9>5p`;z7Slq(c>gK->JW-y zZj}znw9&Xy@WpAHr$Kd#>y34yzkeB&K2>=DB`5C&jP(uMbI?TlSojWFd9?(I#mGU% zit>W{KAMAk-iPl~6GpFjsC=P04>a|^-Phy`U0DU%{Tw&C!kzi}owCZ?gBS#)%d+c( z6n(;zn{{GRbh-01q?5$9cN&XvI}HgVpG9K$5>)Q~xLz5`2jE1y+f7GF5i;U@g@j^EVpS@;*yzcC#i$m>12~kdvxpuh z<)%b*R7Is)1R37st4kK1;35tIcw}pSRNJI58d0KnUqqwC%UBQ_NAU-34CX^NmW@@u zQ?iX~VNvOAV>sG)|2i1dZ{gmi zxOjlZx`BA6cVIidSO#}l6Gi%NeWef z_$_v~@>yCBUZuSA^5aD(3@);j4Q*@``x{Rt0D0%e$(l} z-H}hHswW((U7unchohbN_(7vPcL$ATZkOa7c=mJ;z?@z;$Vnd0H$ zhJdJmzx(`3#Ut7fc&@G*Dz{#s{Lv(QvG}QhC(7LTY(nv(1$NhxN4vnI3E06PMFR=_ zyc*TlXm$&&mBG-3vHucu=FP;r0z$zaA9|>tp=gY6@T4cf1#1^V_E7*lm=l2FF=9C_ zj%se?GP*P(f6_lm8h2nXWIXXNxKCitnOPM7SGjH%=!_Xy0LS4R{>ynLUXqkc6#8?E z+My$-wd0KNAs+Uj+gQ%VyPA^QT70IjigKY z15ktqd@0|@{H4>jS78ZK{&|~Dl{>SWg?;5{r#rM-uPm{wEXMMAnU~Z zMq?e)XC}Hh!HITqf~%~zA=jv?O^RoBz_(^=En2N4ifFg(p z!*>2uiBy<&Om5<>AUPJiMl`TY2+OQOLe=tBAuWZb$}jU!X>-xepx5bud_2-K4UPlA z^bH#T6!n>L`|zy??`K$qmtQluhc9kQ0RS(Yycz=Jd+l4PT%k6!-f>&*bukyULtDF?2`dye&%$b2V`j>92P8h zSD=M#T^H=G9V@nd1?EilaG7&7PugJA83{aRA>LcKJ2(JUY-SSs0V@0E)0CmnfOGK(CK12AN8Ol!sP z!~zz7Mv87Ox5Lfe&{6eNnLy1gHC?}C8C3wQ>Vco%Voms)jbSmGzuL3V_v7OOGAUya z`hqaGk7UBX=Ht>Tb>fqNENgX{{|S+o*7U)rmVOIcaQs__aTL9F2_Ngcu_L?H> zYMW^jLVb}t6#0dKLj8C3$B32T)v!~fV&KPV>?6{H>S{XAG(4^Zli2CL4h+AOVoi)h z7ST-M;aga_wYze9!S78?h8$=^N>!K)?8P;Zl6qmio&<3ap*Y0|i*kHYXj3u_8WkY| zjkwrc3gdWlBOJND%IFKE?=0rg6LppAM6v?{pX=B6-%TlwG$gjuhN$Et!B1 zYB*RyfHFE?Y6?<3uO*n)h>9Z=NA`SPXbyUH>%*+}5$T6A46=p1iG+odVzXiYB6P;a z^Mw$4>oRfa5*4S5g?n6e)|zN|EPs=s=&~$eHR$DZgPozMaPWo#unC#PD6$Pvr{yH;@7Z{NgqE@&JhW0nl8X`EVb zbOPHiU{@xu;I!poYQK{LTs%DD05)rO=RYTenCTsjc3=h$K1(>|w^N!RBWA3iWigoY zUW#scIeslzPHl$k-e?&xE{X#qPunjK2n5L@PKw?asnEPH&gxncz&GYYLxA;aaR37k zw8#GbN^#tP*eM4Hzj;*b9Fv96ql19^h+U`%JAN`;1bYnE--8I4aqLB`JAY(qFF^AT zYfHC57{g_A27svqNDu7Ka%{V27=5v))*aH4VLVn9Dv5Zix{rKXRS?d@@@wc{LCT*p7j$gtohAgyIurcYnrZ>LM|Tb( zELXuZ%aq_AetKDRcIX|E{;uv1jr|A=meKK`(ApdAw)m4!V6+jJVbnt-s(^w^0Iwvw z6rMI4f0s>ek8W`EW>!fv<4+aBHlI5}vqb7{2#8XaL`-Nrw|i9j$Mqe@PJPy8z`xyZ z7ipsKrJ)8GsMaf^B10R(gMpvRKQ=g@JOWv+L&_yGpU<}DMSnimH6+Pe6;sL0+s8vy zes(pt$k6&*T2=|QPIzxyJdMM@B8B@ofS`XCtYd(SuK~{BM1^?jort9$`idA_e7M7Z zY~@c3fvmnxmrOz&Zfviy)JUxRw{;9Iq zcI|-kBC=In=mio$FRxAy5v{L2us9p__@!Q^kZLzg`VS#`hsf1*$s6IfA<+sUdN6>HJ4EKaMPHzf<@b} zuTA%q+%3b)zj38;ulLkqi9w6$dX=Gu8|*>emLbwF&02bjT;qlLC%TcrWc0J4hJ~Mk zat52sRynA&eLQB_RZ8&szv#*_as_k#*LwKG53Gdr8&UxzlsgINU6AA3`;VjxuGDU=&+;jpvf zdz908i{=Uy*%n-gM|0{r0`>jeWX1&JJlvSP3$8aKi44i>T3E5VPp|N^m2N(R>X5M%8%=;-zN1ecOgQiM&XhA zM*zDXtD9i7qD4HR5j+ccz(E1J;IhmNdtW}SWFZa_pY}1^`ZERTT>fK`JH)mFp~TwU z51Pk)S8wjffG4EF%qu0*ydT)eIr!m^_bY%BMcTWWB|1W#6+|8#k8u2(33is&TnBDB{ zs9QTL)J$_&7}Kxu{N6KzSAnK6t3iYncgu`kqjoua?&&zgJV(e)$XDSL7oi#;6xD(q zP0Wj>46F*qNeASyvCvYsKs3NYx26D)p0~&7eg?zv(I6FS`s6M&)gCT%;e#}sE97bv zHn~G<7P3vK!a=m1m}xqn#=WixAY@#%phT4T5cs^C$XqmzcG?s`I9LAEv`LYuzBR$T>f57yqq{)UwmuUmQRPA>_enuhBX{KC)f(2-VRoBT)X0hZ`E#b znfb9j$w>ma8+UzSXVFk&uKq7Sj+#t3^X7(1=1ecSeqd6inv;5m{TfYp;VZw03tA4Q zZ(7HUs+Xhmo2vwSD*p&B`ZRi8+kZN^OB)HAdbf?`Ekk*S_^B|>NDWMQKuRM)a@bX| zrPF<|v>_Z*XQJh~J4hAU31y*55cj3ZxS=!#S;Lo`w-*b!ezr%0Ii}(_3PuV;8}? z`~KAnX$g~yt-ykE1WX3<>#%5^AQiW5#PPV*m}dlbI-q^At;XkIM)X=E#K3(M_;!JUUO1Xd#1WRd=mH;w3+ zw>Zd_H1jA_qMv(u=Ej!e?z+@vA$lYgD3x7?>M2cMQgoEk{-&4d1&iq4C5Af+zPDG{ zZ0@?rKWjn}LJQt%DVm%tD{3wA5=8jgE_m0R;N}l8H$vkp5wJ(J`U>CK+tsPn$>5~h zM{JMs9RTOTZrj6bK&=ORYbV%Q=rgh4!d_x?GC6xQ4LN|9SvagT;wpksDqrWTAH?g% z(uQ6>tvHe&;H{bI9a^`bsI-Wnh5~k9CBl$~EPC$g?5@dsmN}@c6ZLjUxOiFmwZ#iB z=s0+v0s|4dM^XQz^i95vjUD#^x|uMHOI*tOYR@>KUlI#Ve?b}{XK|9P9y+Tl*~7PX zIc{McSh*|+w{bD9s&2xA8cJoX!BuHUSkmqN>QVwOQBrsBniMA=i26@%(_ zda>6fbTJnQGIUBec*wS&be5q#0q4C^N7IEk+`V5x?F1CB7@h-;X6k17JOa5Ag5Rj| zynrGx)WES#tMQX%OQ|w`SxBG1J%LKZo+qArq+-~e)wt@rR~?4xX?c6fcyO*1U6mS` z*Qr15>)Q2w6Xsg{lt&zz-iu;Z3EFsX*}W;xmL7BFoN(9S)(Z6niUwyD{LK-l0o+Pg z$B%x4?WV2)!aX%S3tVUXVx?y+Gg7`kNtEmvdPc5yIGSPXAfkw481`{{05-B42i+|J zMtuG#AWH_v4onF!0E1s#l_0eY&o2k3al6W>oZUSi(?_aB7?Dj>^!0W%c~(i-np=+? zW|EmRXy2q&J~B9(A-h9>#H8k9j8Pkb%PMM+_2^~z@(-9@GeNRheCiJh^1+^ocTp8hwY?`BICZvX_MJI@Y-ugyGh3w5VnP_mNul*5y6 zwoek#-5pBn!1I}EbGGcMF$yLyzMy7^A7Bi_1b~KnSyo$G_HxAb?(mr^ zU{xV^?>(VAxJCB^4?1ypZ`;7q3m%K>_mt^ZS|A<*MUqS-(XvpBI zE)K%d$~QTA4OK%pdDmNj5g3x;-zf6zc@n|4{~w<#c-5GE!8waDY7|kAV=MG%|JlQvcBi>8#Wi?Tg$jH`t6GZOTW|Xt<4xVb~0=Zg?tGXLFzOFCwMAp zA{=hBT5*RQ27@WR08|_OP^16?e7|$)RgC87_%>^wtnejB5SBh$hJ`6DfCPDgVZ^wj zzzsWXdt3YzBwL~={?~(z#jd;YE=Ue2)cR05d!TuCci=`fY84a}QI%Js=uGWHS}LgE zv}MTS?QPf|gCFXzokBK$t32zmO45v)9^*YT{)aH~;Oc{-Xl!pSNm}^oqY|N*{#|j9 z)wk$4BbAPjIyg!sBS=TU^CXC7FKgW)5WWX6BE+cgT|7*)A@I2oZ-PODrRVJjN4dG* zxPr z4X3>*D0cLC8E=&M3|I_z?>?SlwSeF(Y(+p%ee z&Vv5JgY8Q*%T9)<`J_R&qls-Xt2U;OO8o#T2t&ZQL~)VSnNT#D}QJqNDr3*7<9F_>T&xywgq%V}*CH(B+FPu)vcvS7mym<~e1h=eQb1cL5 z`h$`PL8ehU^!AD57q80i9V0DEG;MaNn)+CHO88jpxJGvSrfq!t@hf3Z7HXI|7w$Jl zoxb_g?Z8dfwj6&8TxaQr>?5Y}TX+}n{3!BBmzCcwV_6m2TCg~VkKH<4Frm@8@@cFq zsrUhd#*FBjxlrPbW-Yy(axFcqPAcAJi-KLyN{noU_;6-9werwYg&Rf18|}UIhHXSH z4iYpve@+C8IY)EfPnIl$h$nxO^RlBO34scKgN07@Yu87B5{Di&94@4{JNm z0*EO1!?oH~aX;RS)Wa-veau3KBuW|giAN>UW!w$GAyYL=uUW>ek1nqf)p`Nlzc8Na zAq+k0NLvk_`JmmkBvtaUzyeBnr)xe-i%i89u=tyBy3e3*MQD7zZP~+#C*#U_Pejsi$3&8Bbu}9#^!G;Y$K89mRzpvJpj1o$gAInn753 zG{6pmSb7-z$TRG%7bPx7EHmYim`gu3wm*KG0%Z)uy|=nXK-r~DGHc6fKOSUOnBL@B z&@GL74S=)B8DJ*Rd}68z84q^K07sR{JBG~KL>6CY5;0RF1JekhNk$!U%)+M|k|!@} zN3Oh!co+#OkyDWN8JWSe?3$XSd0Z1VuY(| z%${|2N4d7)4?41zmTc>KM4NcKTRf0y-bl9|!l>5Hbc|n;AH5Y8v?vOL%&v zdD1Mz_KP~Q3id59)v0p#2$|+lr((w9r(|*>p_1Zr3qGGIn!GtRGg=hk)b+OBeb(Y_ ztfCEZJvv>kSMA^qfvRTki>0g;i7o8mix+Zqe;+gI5VckaeKuIhu6gg2@~o;(HgEs5 z>(j%P<15{VUTDO9k6SA!?|$#r$xxl;o$fvmq8r{DX9Q=tG?lMlA zHYxp#CJkWESi|y4Z*3EWTiM|EcI06s@ebfvviM?gJ~bC;Yz~nlRU>ACjak}i&5?GmrCHO~j;Fordh~t0~@wKw?l%E`{!vvIQ#KLF7G!q~;Ka30ES+E@|HO!z5 z+4}TKSA1WyAlZBvic0`lJigB-1&SwW=wt}-`^k$Y7~^ag0#H{;2m!)%1xfm>mtvJH z^n!eSfBJ_gwBl@A+~(L#hX^4T|DJMT0`Jh~bsn+<4j&|#fH|jZC=UFbJ)*c|hU(o` zS5w+>xxJ>;xNOAwXlj555YhVOvfh(3i19TkRVN`AV_FH|d6u)l=3m~j43I#taLYW) zB082!xrt(YkoAZGt3x?mrww~NpOY2A_hjgEGLYE&A;~l1h$Xl#->+CFg!#XW$@~=y zFkyBk$GI5zaqZ{t1!Pf%&%GI$0)M`=!9F!^yD`*3=@b!)^Y(~C8|m{{`3e;5aw}?a zA3*PEyqf?iYjn9}f=Y8z8YynTm`H)jqz@E&A<;4Q@oC}UiW)*aU+6Y%%TylAvJO4q zqw0OXu=|e~o4ZH%5P%89yBc?k#&NJOhAei5vK7Z}fCv9Jkr*#)a`g2l3>rD4>Hv+4 zxp3A~Z2y-0ghwbI!r0E;Z+jTfx3TO2X1GzP{#BTPi(_@JSOL#F%r}cZq|6{ZFHtlB zA{`T6Pe>g}%rk+cNITIDxX!={EPyhXcCeLia#gX?a->+u<{!~FU4XSs08;9DE&!(K zP@9)Paf5_}iampLv?T!$zAxS8>}I!#W|b5-cMrRlT{0C9Vw_SB>=Zz4#5^o3>u1!~ zTGx@WRbMRiVZ(baf0#9Aa|v^fxak;$f!;0wu~Yw^b3*eZ=+iMbArUm_4z=meht-az zVkL*&2l32QG{&F84t<`4pt?YQW$>EpNmSYg$fMuV;=YVB>b^iywCDY)03csN1~2R0 z;g^vLMHG73@mGcIkL&{IZ0D~tl8yJn2nNv{I~6IF>BM+D$8H&%c232uWxU|m?nGFn z(g5%O5-o6T7=B%*ExsEX`Mo?2c+k=5Ls`yB`gSDu<~E7I<9`r=0dJ1JxhmEaNZ8=w z0p9|is=ihB*kpugY1yj#A2RN;C63<;SN*_+Ff!=3h307y{FejLh^<(zF~eT%YotQx zKw>lii%-GD!)heuEg{x~x&Q@8Yk`9-ga8>kIXL>Hh)GI^;M)1AZRidoJZF)zQQH7? za|mGU3OuG}eiBFKw@O$Y4>j}y)IYVEPZ;vw53BX(Y9FbFs8kxZZ~j~%*mo#XX4Q@6 zjsk+z>V0Z{EiM4V37-)Bp+*C`;xaZU$XEt^Oo#)MiFx+#a`44agwq7{I-CN-t+FMa zYZicLS6j7@QjU?1Lu@c^YE;i78prt;yg;zpn)!)J1Nop4>3PcXtRWP7-kyJDjF6Ax z%}Q6k5Zm0gxP8k?1WpabGb-arz(_^X@p3o_!MFoBGcTwr*nc$MeBns`h!UPbwk=zH znpxa8S8Ox}K(DFM-XjG1C61f}D(Zfa*Y{v=y#$>N{>WI4Gb33%Qdg2x>5E;L+FU_H zpeMnPqyx#fTnirNPRCTiLscMDVJy;=i~$nwgv;&Hb(_%RQk7`l69MPK4}h9jMAx0C zM8g973cr|&HJ%6K?L>7$H3?-|Hq@x?<+yn$TFsc`M0>yWRGpdsi47(_pG>qB#95~-_-%(-W4S3pAAl; z&1_0ieV$?OIeuPWr+I8SzBr5*;-+;A) zOU`l8oBk_1d+8y;44Uv{x*CJr(^7ygU|W9>7t&WdF;`~`FbWiYjn%UuyXvH)&n~g? z9UObjE<663{i@KTwlU+ROG~hZFhHRYLP6+|bf>$4G(`><59JR~XnSmp7#GozL1NaB zR{}#<+I+)JKwJbV!gbgcBtwatj{J0%&~GaX&hMuGblve z49r}kHXt0uLh4fl# zGFDn5Mc1i)2`O0;FeL8zi1<}KJU?G|6Da2YvhC$9hJku_b1&etFOZxN`V`#(*{BOOk?$4PbRk)B3>LeZzLWbr|YpY;SiF+{MKU0Tycm z4UV_c;$@Uds{?_oSjxXStGeN^P2GBz*SD-4a{>4>l+sQF%YoIY-1`gYrH*5vM_0w& z^l>YP6Nl$D_4QQN{~IK9Sf*07wVim9aumMX{U`s z0Yld#^C8H83?_QWB~}9UkU(t!Au4^A62Z2dTU6g+IkYA?S@IXS|6ll7<=)Ub`WEU0=6eh!Y~m! zCO`a6w;osFbk1D7VPJkPkkRqj>;RZ-b=GrnJMa@WRc(}d+iP@;=nE8{-b29W(oJu- zcn7m{R-Rnp(euHsoP_O|X5pVb2w-RkEEvyRe~}lxwdk&EY$6cI{>s;p9x0E?x5JfC zc~_xz@1VE>B(WyJi)pelVoV12gU@V?(()Hv(9apkg?Dn`g!xhu74U1#I_aFGoHZm$ z8*piA1DL66&7t8APH%`ypdNg-rZxo?!Qd&ztIme~6#$LcSyuvTbrvyMj>I{udjp#iz|ui> z&%U>O@weZf;_?wX?8{urV%pbX_>3+$JUv?I+L0RdjeaaAb8%t_;oV8fllwnc|1wY;MbEZpgqv{Ur;l{w$y3p)c@Vm~L4HSo=0IRD-26m|F4J0sq2AafTC^p4HI5X7lFC3CUM_#$zEVy^pVMU)8^<5EVMg>%7sJD>{l0iQO7 z*9yRzLdtmS#HRPC1>V>k1vUcGuE`7683VR!1z|R(dG$ds{>}It|OTU5~tL|Di zdl{X)zTFm5?6uaN(UhD+!&jv-C}IRF-IPbhH6ct_WBlN8B^QrJu+{qe!1R(!UwI&0 z=WVDY+_KtSRc{Cm^!^g%z_Q0p!6(3cRV8?=P8T?w@QzQF6Qf2M`4h<_ViEKvIA?6balw|f?a4vT&pI#5 zGfJLl!jz7)HL`D))A6cJ;J2A#DHMd40)hAlt=i^$fo->za0&WgpyE@vkx&P0`V4l`wDxDmfE6A_TGR6G22EA)&Su2#rG%SC6i%f|K$67t3e>W zM3r#;4x>8o`a{MQRKNtE;tSrAZ&@B_J`sNV?W%QIN(yM$hDhVQC*9+1oGe{!pOGR> zUwdd6uQPN?WAmfRfZ!DuuXgYF1@#?tm>J@-fCpGq@(J;K*QIXnu`W5f&1h`#Nv)7W zJffAU&p_GCk=aY2L3MYUpz(MTAf8+~3@!8Pu>8M^{sOBJdXwyu-OiM%e@f8xC_4rN znBG{mft`a!~y2iDEbp~sUtSzThANG%sRfV`RiwH0SuLYdL|`4}B|+AQ^5 z2cRz?MRqfU=s}^9c>5H1=kSm$lk0d~&U3+1_V*V4h`W9|HyvAf?_7e!btwfMez&?o z_8OUw@ZW9gD^7G&j(Qp?fz7yg642BO^rPx*4XeM%ELFb$5>Qq_z^7^828;xk!5ARD z{DQA|M{$~2C0PDm=x`5Efu!X8@(boTe0M}0w?NSHvbr5S@f#8})NL76JPAmaNZln( z$a1+b=;wJi^&s@o#mz8*0f=H_%jrSO|CMe&2s6T}p=BU{;+k|7bSLgbMN#?idzn;? z7vtqn+P%B2;j^QFmLMv>#r1MI{Zx97-!-d))MscPK31YD6<3Lts$}Sqf<9GzhFdIT zaL}o_{DP1PeNPg4iO;dqvmjDWg+bp4o{BcVT^I3Xk`c7~nMflH8Qge>lM16TERV2K zo&)y>b?o4QL#!7h{Xfwf2o1c6uwf@+I!-O{bSm4}zXzXalviwP$_Y)84N!vI!Tv^p zp!9-eFAPsO@Ko@rSaxjl=j}u?4XRE>Tj6^E8Spw?LL%SVp4=hE~RXz~zeKoFFumjAf`+i4;Gd^tNVZNpgfmYFdj*xe~>S~iM7<0f<$`s2?G;B{p zM>cxk0$qAI#?VbfAVq)Fg(}~(1)&dVQcTcfGZH%PnLMu z6%HSjLA##{{$92-%`!D%BW$aoc;3>jMv|V_BwUFL?S?J~3Lys#ah)%R+{}lTW^Z;^ zP&P{=j=Zn7hM`x}pikkF&ihX0TqBQAW#-g{*E6ijs<6wCXP(5Q5vB4u$^R2Ef#~)B zi;7UIqOIUlsZEA`_^&4D6BOfd6Er>dz(>F0M0|Jo7p={kx)0i2eJ^q9E;TQF&sL+I zXIj>GT;Ca8=)LXu1?r2+0Y_PZRB2fbqIy1-ObQFH^*$d9G2#QbU z$T!R@t&VY$NMWDM;im|a{PS$tJ$$&Sw}_Nl7KUnmo(a2eTS*lnw8sl-Nxh z6<#&4Z*8AT{;jY{RVh1AQ2L7VinlsH+`1_0>qTFpCXtN~blCdvs!ZN{$#G4>c{ki_ z@bqjXQqK)dkuZT14O+cZPLH+Q21h3P-6yBLWlh}$mKbHJ6DgeJU)&%Co*=x5s56|{ zwUtK#y7lciX*MhlY@cM=-?(>COXP^><8K{m8FJU~$=T?{n!n#9rt#T1m9^>#Ua%w$&7$S-Wy=jzMRj6jmb=I~FgpGr#)P zon_gb&}SmMd8;80V=9o3{l~=D!5bu{`vkECTLvy;A$P+S6TZH=aKpe9<*;n|rZ+bj z_OuwQETIzH`o+V7i708kc3C#uWAdJuadyo#fxS8P$0S%~mXC~07@`aO=xEYvpW8J8 z=u2d&e9ZZLeY_B{pD zrdsTFB(ftX&2mxEw>WhV-Bv-QZP3||m0pT3ev;uzX^d0X2-R}Cy`Al)atlG#D_whc zgz(K7y3Ok#GJ&AMQcr&;xNU-qo|pBJAx zpIkJyHEzj|+St*a0JYIa=Mo3vct{Ayc@$h&{$t7)?hIq>!Xah(t~ZrU3B6@k6DAVh zw7&AU$v(>V6;xTx;>y&q8qj0t>o2i2)zkTqyH#+d@T#06;nD|byI5sWU3WqeQew$S zKqXGY#F%Qk`kH4=9^Tl#14@2tr7k4yKH@ZNXfWhO_F<*Gmco+Ti@wkFCFyuP*7^;X zqb$OR1kcMPoiq|JfdWS6?*%J-%}kvY1^o)k++>m1IMPyS1$t@2l5WuZf|}{X`mu7$ zUF6{B5Rs>zr!#D#Vl=zf#H<-~Q+fZ&=hgYC#zVsN3#zdfR4s*Tp13pJ~YSXNcw&;C-l6Exm zHRyDDz-HQ3pCIyWYHtzzZO|;$W~bo0T0@?X9F)AVH~E+@idQ`esJ{jkrhRSzQs96PioARKh646YgPhZUv$m`{L;h~S~pR5_7T{BG( z*<9&5Zq7}@R#Y=0%LUO(VTvfGsMrNU!q$2D-iph`N#7egFUP5uRj84hWQa7D60w#h zLaVjMrTCVE8hsm3}ft=*;cK>$0Q0J%W#^8Rsi8rGNBzrmhG?rLCI-&WUNKS4=hWs zX&jNZ-CbZuIjonZ=zQ$gaN~AiN?=>@!F^v&x8#l))f5}u$yLENC7{MyVLClz?xfEL zN<(`En=T6b7mTauh!avFo*#5c2=I9z+Q6tT7yHztt?F2u95feSnYVw1@yReo^2W7& z$1ViaOU7ldCQ^fT4&Jz4rJ2UJBvulYWSKTWQ~Mp%P_HM6wl6~RnJbguNj%zP-4{Dr zb7t-3(o4AptzPsPf8ADV7K_tM)2YiZImCrTNv|Yq^9P@zs!Xg(fYwc3XKq?~MFQJh zWSZJ8tLoXB-AJTw8dqZpK99!R-;8yInY1ktnHJzBT!j6{)%Cwf{sadGe(3q&2;4?= zQ*J38_8eJSZb^{0&Ni3n1_EHHcCg(vKc33-Q^r*Hnq6`T9aLq8FbweZgq&WkXgA;9 z8uqTtHR2$7WcJ8T5KpdUDYJJPmuu~eAvn+0EOsTs*5Ah zc#}xd*aNAE61JR?AS>c{-*;#&mj8{A7ZzMiw{sMS|5`zF7`kzjoj=| zi40N$7y9Al!%gE7D65D@msGIroaY=DVd)a&V}zV4t(;$boplx@>YEAj#C?+=C-sQg9nx2P$ggm}ldzv{P-?F`6++TVuoA=A0D#DbR z54J5O+O{o8`#EVmJ>Ha!ETtL};=ALzq0g1Wzv5HCnZ?~8RRQufM&BX>+-eRSlTS5q z(>;rf?E>|0*BYT~DiOE}W7blrDpH1cee1tk`t|}|Wbc;mgsyR5Vu6KVJRU20a#U$x6bIA(X~^?^=SPH!o*vSlr`(xJ@(d^y!@3t?~r*xY&-^v*tvHQ=!o^%RkYa z&;dmI<-v49pR6(^w;J7n1`IqOS!U9Jy^dVVmQQ0m_H7Z$!b z`SQ_+*`*nUrg96BfleXegpwsYG$zgv|TNc6C zcZY4m)SdRBc%&b_IUVLt0vnvpfdo#Z?pj)J9-@%8*n>6mfA z>@M7dVm(sWmh&K`HZ05YNv7;h8dl=Fi57RzrEkX)?j)}#PzUZ^hcVW_>!Jj^{tI2^ zVR}!DU9Z%Q6igT)Cn>bm2pJi)hs9JwJAIPmuocmvsq>G!q=sotL0({|vrp1gA||_A z4(_u*W9bS4jehuvUUQ7Su}A(0ANCsTWrd@G$aO9>R$ZYs9ub9+VrI>^(EqIujxH~R z4qc00Ul58w2LzEl2D1u1*_=cld*uL;_A`v7($t6>%#t0+gcjPYhJcFGJn~u)g4t^v zyhWsSNDjj`>LX9exgzO$(esQT7ZUla(k(H2s z7<+9x>4bK8N~|TEzv64*F3@Gr=_*(AhJ(_8WyGSHl84eJO~{c%2~IIVB1J~;maJZb zM#f+idEC~vsqhTdx34LR#0G^lF4+vi+p&B1kwqps{YK@lSq1s$+JpJ9%$1$-nX~*9 z(G0Jl{IL8LXK&~OCf)e3mmwpFtX}&ZaE;jC{Qi@kU>&7`8S6H#Sr10h!6wyDamKGK z1?(XQCW-V5T+YX4LUY0fNX|-E*Dvm~>gbN|)U(DT+8QJ9L>F_nu5zI4yt}$y5fxOs zLA=sq$5P~8lPbG808BvV(7tR!X|&?M?lYiS&-?N|ywpb!euUj0beO3TG9qy|+Vh$d zAP(LqOfWrRI)3EJ(x4V;kCSRgTn4%7R}`?hDa%62p-6;4RuXZQW$x~A&Ua$3zrCrp zWyF3VQCWFwn+%Z(o;0KpYW#6Ra>({#Orq@w2~*uYxbl27E_@H9O=7Co0BBxw;Okh5 zLSF6H(6OKmi&k8=tR^Lh+(ko~s>)KK{#p>AXUafZ+OH~z!Fy<15H}Dg1H$rEbH#r{ zL=cUhGSQ4{D%eJ%=~rROp66*2tIW)F&qCKzLw;yMMuRTTaS}}*go>ZimQ?yg^Rmri z#TpM*OrL8cvQ(c32={M=DJE_gNf+V^-Mxum;a2Ydup3((>*iPoF3}8^C2E@ zd@HGH=&pPI`hJEv(N{^{oaeR%fvOvchpuXyo{ztbu7NnD=8cNqOH8DItwBR#Fa}+e zV9OUiABg*A@StZc-P7B$`G~Tc>!w)sM3|IZ3cfr4Q7)#*g5`Rd5gphpXGsrZ z#GYLmbGWqfoyf!z>+EjmjpU?F1PW#oJ}@rT_4(JG4xbPEXQZ%I^?uI3NjCkyexF$# z!{_<_;ItW$k+H8Oj~{~zbiS5NY7jZmlIga4HVrOeIy4Iv6$ z8~k|H%}zJ}Rg!NOtx)VRbx7R9TG8%10Ga#%>3^-c`r^W2%Y4nK{J0^6#eUc>@ zZw7_xysQ#v<#@CS{eH2tSPBCJxFRP|$`3Lc4T%(AnD)s7QoW&}Uhu(s^SVh0$5Zz5 z7KJ|2hlI0R0O3J5F9iGl4E)Kky}0Gg$--mCYOO!yCeo5_<)rQ4>XO2~I6zhGfI%+{ zo6{yDt!mY*FnzZtnB3C!ml9;dj)B|V_TB9=inQF>VyT@Ty-^%~E( zHcKu~Lo)h}yV+k${!{IISRq8%W{fUXhlst>vT;a!6Yl-+sjK}eNnH7@`z{ne>2cz5 zu1PIU2@2ZS0o>6j5aWMBBtPY(@c<_+3Lj5+uCo`*>hdojH7p(pfjw{VX2rx_ROA%u zDD?FYH6r0pylS}3ItqEeWvVO^*_C=whc&ddehpG4QXAJu3lVk z7XkafN-9EoFfAn}yR(6VT@V#+A-403oXA!ola}lLb2AqTLoa~EQ2_8vrZMt#PIzE* zg(ar3z5+)#%q>`!D_J;ABx_i?vN;v*&prtBt*nOkGU2WJ9u~mJ#K4^!+9RU4##Egx zQ=?=cCs&anrQ=j9Tcs*ufYgp5H>!OB)Df1npPk9@DW8bREVaT{1kcFvm$%llJ``! zMawkjRtXzG9oLlou&4tgvUDYZL-_m*bfwp9xD`4YS;~c-im9F=QGy^~FKq7KRhh~% z(|0hXPGPjBt5>x+;6j|vjQU77BgjA4+P#MZJICU){aHvSiIUGYYZy*}^Hmt9$;5x% z^^crL^i&`qDh_3;hT?Ge1jQ|;v6m`pj+%3~O7ef;r#GaBX34^|JC$$L6c3Xtb&$N? zfg>fpxr{cVBt}#XC$hOLy-Y_tv1#+w;JlDpI?!qG*EMl2!?s1T-(#7?P>3V-rwsvozJE&mxAFs(b zEjo>K<(k0VYY`j3Z#)N0x<-S~y)JQ_o0cUj^5XfhL*p6b0E9_YV()f0&GNQ?QWq26 zcTE5Y76P2S-lg}-+1##gXOm8v=0gTZSL{5C1XH4Uz~)K|65L1;nlTV2(3-lNwuMav zJ$RB)x9q_YDQvB(&$=TJYAha^Q75=%dvbrYW{jQjAJKAXUs5vCI}li$>l}(W2uHHiHr8qSKq00~KbRnCP+i2^UdMt?{s`(WtiAK&eHRoPu0Fgt3`lwY@0FpFxKotf41iu2;Cko26jr|~ z1p{y8c1m={hkY)GfoX>Y@8{#)i*y%Gf(3>BH7-%P&(@%ez;J!xsE}_unQxL{XLA70 zcSJK{4&U@${n;)%jSp?Gc%}f>@Kc6t9z<}tRWz^gXSunaa=r0L%(yl_>==Xuks(0} z`%vG9-#)8tl9qn-z zye6*S``5{OJUQMzb%#780VLx~^|kuYib*9I*4c*<3iv)=I%M^2F>!?&>ew%4{yAvE&w4=p)Cy#GW#{ zuaUD~p#Y@dD-|&xPFsY0N)WNC{B#j0ue8>Bc~xUaZff(ZxuUS(d{)Yb|8)a93?L)~ zAS6XBu*u8UJI5Q(!+I}QzQ^0@8x}X-TZYP<*S~phKX~u@R`$tTu^DpFhr@1g5$f+; z->SuK4jA*nVIoZ#hcC}TitTs63B9n=kZ(~740?D~)2=|eK10;lk-}pOT?1IuYQW(E zKfWk0pGPF$B$;Y00sU{}nv_7oC${}Y2B0Tw#rZj%Jk? zSK|9*BFR?HPruoOlKm{)kBSwrWbot_Kpr--ixmTZi@OT}99bDm>^|3~XaguzQ$tx4 zCkoVR6Q*O4VY0YO*B3D(_sr}kv~!;OR&EDl>6&K4`Sy}@pZqUXcz=fkr7_3?_hhAo zLn0O z7#XWW(XaYFp+y&sL_XvKFCnxV0gP~2-rjjT!07=jxm=iVJenlI=^k}c6C_IeR6Hp% zP)m|mxr64!=3H}NE1))Tl6y0|&4FDZhLWU#`c?nB?=ELJFx7Wi2E+aS8lo95UQJd@ zVFT0|cdIXUJFQc5zHwkvSHF})7JEjfh)9n@J?|)j90MNAK>J7WA2{$ng=?v;p`I9Y zty7`_I;IFNo}7x?A|YyBW3Nnm40>7QcAq?OJAg2U;R9z*w~{jb^92{1s1M4S1zbGFzTb z$ua01%iDfH&tqn-UN9NNs0^=`x+y+`S{~hvp5GR+-U#nmcy{#Q7c$XjeN>7i1?>f+t5VoJ6=(0T-^5Ky8qUXK1sg6(_ zjD-}f7&5g*Ox&R&3+&2=;$2UDTp)-smqjjx6x|Q0b_*i-=G{I7uB&S?zJ{?~t z3jvcI+K(4SXQU#aa0+OVy&JXTz=}(eibw{~gDA|AGlUjW@wzfNUjpBdzwZ)4WPB|y z;b?OS`O;J3s-0n-o7V-}}(VVcsX>-LI{EA2! zOkASX=2|gVX5w9QGNmuhXKp&LbgDb8t6%FD^Xi*Y>%y<5H!-!@Y2t~oK0y+agVVY} zj46XI^NL`z(X#L7`%Zpd^)+yY{q@x3lA9;ChgDItBH7# zlBHbd)^-V?8?a&ewXF0jJ8}nKNPiWb3mG{#NAcGezIF7l6u~V`J^A5-)AQxb(a705 zurYg^2Qmr!tE)%0O1p8lcip;@z(-qkzLtp`~tBv(VPrO5h9FxCYFvJyU0PgceeBmT=XIg3H)cu_tTs%Co~st4|?cvVOoKqGhy>BV%Xc~LFvbj za&xm_rrJ`9Ejim24<8s38cx(PskP(r<3k!&bN%0gCPsZLM90HO^w--`9kXY}9TZaM*lp*xtVijDxZyxoj;lvg_(JVGCjY3Mnvpr`5hhGUz^`YaE z$lSm4qpU{U+#ai8SzV;xb}astk5!lX+-Umrw>Gi(8P|<9vzxBm9AgX`4feJrCdW?Q zJld(blF+=)x3F({skNB+_&Ie=Q{a&JueOs!{)g?F#>3+QX{DAAWD(Q@%WZb1xE78< z>WcG4vTaH9xq%9U4%3J*^?&m=Z|jBWDH`O8nHCmJ0xw|Ux+s(cMe`mAXj3Xg+t#$5 z8-$u$N+MifdOazSK=F)(@S!x4X@#8;32KO~&ko-%%pfV{TeccLQ6!udBly~W0i(O5 zqFGTq=zf(j1ft8e+l7!x?L+fq+f~G&qN{Sy)QF#oH4v-+RY8`JN2EP>LhRCF2_aDt zM|>U6;54v3^V#x|;e(0BwsNwBv&#vW$|uhnCqmvlWw}78+DLS}2M1>~)ONkJcx%eh zqm^!6`YYP9z$sBMM1>oxdm7pN0-psAPoA5a=EE?4dP`aV`iF1_ZcGDdO&o8DwHb!X zn+5`0u|n>XKHAxL!FA_jMZ#Oj31I?gqJ6ZT10ekmf;1esX{~m_DOm)w6T1Tmroz5j z(*YF$MF%0&QvtQB+c?3f+n56R9JZ6x-mNoMT^}(J zE6P5YAj&Qf2~pw)C}K%Y;~C<3VxqgdpB~|SeDT2oV{|cS_U(kXs#p0(YZix7k360+ zvnSUk)M$uK@l03D9Z+{%106sJ!~Hh}-1yHRcOKhuN+acb)?CqBWYRj`!ZQ4{UJRh! z5Jj_8#WO}71YUie#f%CD)zXAfpbbW&ND&~vAOLJ6 z(az&>-8gN?dPZbj4glO?0=d&N%50I*(Jy#a48TUK0?q+!T$}H^8I*F^s_jCq4tt%a2Q*q z)@Vt^yLiGrqvZ>$#wBEa5zJ4aFGC7hDsa$ze((W+*LI!w`vVaY`fIu8k(Q9T6tIw* zfvsS)&5ZV%BV@{hk3_jO2j=qUN7IMu!5 z)A#TdfB`V@smu;aa*VADKis~ozHV{L{`os${%of=dAdq7}*u&A^zg4{VEuY zpqLjmr{C62O@2AD&w#_F8nEz6w&GI>MqM{;% zR(ZFTeS52GU}=h4kJe;xd1;70z&2L&NGWU=`;=*i_{+< zY@Ynj{AG-AnR%N(4PE+40`FMlh?O|`5!=Dm?DAH{fw>eXJv`5;-b$7pn2}vR?J9#L zrf>X(T)VKY1;O~Hk23a=-cIoi|DiA1co(IQjollWt1psh-#0h&m0~NuidT6k`{2-D zZVY4tr1U>G=1sz~PA?M9s%yHz^L*ExCW3orsa-zFplohtrvDLP;(Y{5NU-Z9BmEY} z7#$PB!}=#7|DK}e*f$|7zII+OrP=pm1Ce^K!}jHq*av-_S{1jEigZP%=h_5DswqRQs}Guhk>DXn2jb>+RId+DZ-mKZP%b-v9sr literal 0 HcmV?d00001 diff --git a/Demo/main.cpp b/Demo/main.cpp index ba277fda..1e72f796 100644 --- a/Demo/main.cpp +++ b/Demo/main.cpp @@ -10,9 +10,18 @@ int WINAPI WinMain( { EApp app; - if (app.init(L"Easy2D Demo", 640, 480)) + if (app.init(L"Easy2D Demo", 640, 480, app.NO_CLOSE | app.NO_MINI_SIZE | app.TOP_MOST)) { auto scene = new EScene(); + auto scene2 = new EScene(); + + auto listener = new EKeyboardPressListener([=]() { + if (EKeyboardMsg::getVal() == EKeyboardMsg::KEY::SPACE) + { + EApp::enterScene(scene, new ETransitionFade(2, 2)); + } + }); + listener->bindWith(scene2); auto text = new EText(L"中文测试中文测试中文测试中文测试中文测试中文测试中文测试", EColor::WHITE, L"Microsoft Yahei"); text->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2); @@ -26,7 +35,25 @@ int WINAPI WinMain( text->runAction(new EActionLoop(new EActionTwo(new EActionFadeOut(1), new EActionFadeIn(1)))); - app.enterScene(scene); + auto bird = new ESprite(); + auto animation = new EAnimation(); + animation->addFrame(new ESpriteFrame(L"atlas.png", 5, 982, 34, 24)); + animation->addFrame(new ESpriteFrame(L"atlas.png", 61, 982, 34, 24)); + animation->addFrame(new ESpriteFrame(L"atlas.png", 117, 982, 34, 24)); + bird->runAction(new EActionLoop(animation)); + bird->setAnchor(0.5f, 0.5f); + bird->setPos(EApp::getWidth() / 2, EApp::getHeight() / 2); + scene2->add(bird); + + auto listener2 = new EKeyboardPressListener([=]() { + if (EKeyboardMsg::getVal() == EKeyboardMsg::KEY::SPACE) + { + EApp::backScene(new ETransitionFade(0.5f, 0.5f)); + } + }); + listener2->bindWith(scene); + + app.enterScene(scene2, new ETransitionFade(2, 4)); app.run(); } diff --git a/Easy2D/Action/EAction.cpp b/Easy2D/Action/EAction.cpp index 659ba67d..9eee2cb8 100644 --- a/Easy2D/Action/EAction.cpp +++ b/Easy2D/Action/EAction.cpp @@ -1,8 +1,8 @@ #include "..\eactions.h" +#include "..\Win\winbase.h" e2d::EAction::EAction() : m_bRunning(false), - m_bWaiting(false), m_bEnding(false), m_bInit(false), m_pTarget(nullptr), @@ -18,7 +18,7 @@ e2d::EAction::~EAction() bool e2d::EAction::isRunning() { - return m_bRunning && !m_bWaiting; + return m_bRunning; } bool e2d::EAction::_isEnding() @@ -28,12 +28,13 @@ bool e2d::EAction::_isEnding() void e2d::EAction::start() { - m_bRunning = true; + this->resume(); } void e2d::EAction::resume() { m_bRunning = true; + m_tLast = GetNow(); } void e2d::EAction::pause() @@ -45,15 +46,6 @@ void e2d::EAction::stop() { m_bEnding = true; } -void e2d::EAction::_wait() -{ - m_bWaiting = true; -} - -void e2d::EAction::_notify() -{ - m_bWaiting = false; -} void e2d::EAction::setInterval(LONGLONG milliSeconds) { @@ -61,6 +53,14 @@ void e2d::EAction::setInterval(LONGLONG milliSeconds) m_nAnimationInterval = milliSeconds; } +void e2d::EAction::setTarget(ENode * node) +{ + if (node) + { + m_pTarget = node; + } +} + e2d::EAction * e2d::EAction::reverse() const { assert(0); diff --git a/Easy2D/Action/EActionDelay.cpp b/Easy2D/Action/EActionDelay.cpp index 409ba3ba..d51ef460 100644 --- a/Easy2D/Action/EActionDelay.cpp +++ b/Easy2D/Action/EActionDelay.cpp @@ -15,13 +15,13 @@ void e2d::EActionDelay::_init() { EAction::_init(); // 记录当前时间 - m_nLast = GetNow(); + m_tLast = GetNow(); } void e2d::EActionDelay::_callOn() { // 判断时间间隔是否足够 - if (GetInterval(m_nLast) > m_nAnimationInterval) + if (GetInterval(m_tLast) > m_nAnimationInterval) { this->stop(); } @@ -31,5 +31,5 @@ void e2d::EActionDelay::_reset() { EAction::_reset(); // 记录当前时间 - m_nLast = GetNow(); + m_tLast = GetNow(); } diff --git a/Easy2D/Action/EActionFrames.cpp b/Easy2D/Action/EActionFrames.cpp deleted file mode 100644 index 751ffab2..00000000 --- a/Easy2D/Action/EActionFrames.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "..\eactions.h" -#include "..\Win\winbase.h" - -e2d::EActionFrames::EActionFrames() : - m_nFrameIndex(0) -{ - // 帧动画默认 .5s 刷新一次 - setInterval(500); -} - -e2d::EActionFrames::EActionFrames(LONGLONG frameDelay) : - m_nFrameIndex(0) -{ - setInterval(frameDelay); -} - -e2d::EActionFrames::~EActionFrames() -{ - for (auto frame : m_vFrames) - { - SafeRelease(&frame); - } -} - -void e2d::EActionFrames::_init() -{ - EAction::_init(); - // 记录当前时间 - m_nLast = GetNow(); -} - -void e2d::EActionFrames::_callOn() -{ - // 判断时间间隔是否足够 - while (GetInterval(m_nLast) > m_nAnimationInterval) - { - // 重新记录时间 - m_nLast += milliseconds(m_nAnimationInterval); - //m_pTarget->setImage(m_vFrames[m_nFrameIndex]); - m_nFrameIndex++; - // 判断动作是否结束 - if (m_nFrameIndex == m_vFrames.size()) - { - this->stop(); - break; - } - } -} - -void e2d::EActionFrames::_reset() -{ - EAction::_reset(); - m_nFrameIndex = 0; - // 记录当前时间 - m_nLast = steady_clock::now(); -} - -void e2d::EActionFrames::addFrame(ESpriteFrame * frame) -{ - if (frame) - { - m_vFrames.push_back(frame); - frame->retain(); - } -} - -e2d::EActionFrames * e2d::EActionFrames::clone() const -{ - auto a = new EActionFrames(this->m_nAnimationInterval); - for (auto f : m_vFrames) - { - a->addFrame(f); - } - return a; -} - -e2d::EActionFrames * e2d::EActionFrames::reverse() const -{ - auto a = this->clone(); - a->m_vFrames.reserve(m_vFrames.size()); - return a; -} diff --git a/Easy2D/Action/EActionGradual.cpp b/Easy2D/Action/EActionGradual.cpp new file mode 100644 index 00000000..c9a67236 --- /dev/null +++ b/Easy2D/Action/EActionGradual.cpp @@ -0,0 +1,41 @@ +#include "..\eactions.h" +#include "..\Win\winbase.h" + +e2d::EActionGradual::EActionGradual(float duration) +{ + m_nDuration = 0; + m_nTotalDuration = UINT(duration * 1000); +} + +bool e2d::EActionGradual::_isEnd() const +{ + return m_nDuration >= m_nTotalDuration; +} + +void e2d::EActionGradual::_init() +{ + EAction::_init(); + // 记录当前时间 + m_tLast = GetNow(); +} + +bool e2d::EActionGradual::_isDelayEnough() +{ + // 判断时间间隔是否足够 + if (GetInterval(m_tLast) > m_nAnimationInterval) + { + // 重新记录时间 + m_tLast += milliseconds(m_nAnimationInterval); + m_nDuration += m_nAnimationInterval; + return true; + } + return false; +} + +void e2d::EActionGradual::_reset() +{ + EAction::_reset(); + m_nDuration = 0; + // 记录当前时间 + m_tLast = GetNow(); +} diff --git a/Easy2D/Action/EActionNeverStop.cpp b/Easy2D/Action/EActionLoop.cpp similarity index 86% rename from Easy2D/Action/EActionNeverStop.cpp rename to Easy2D/Action/EActionLoop.cpp index 0b94f570..eb2bfd11 100644 --- a/Easy2D/Action/EActionNeverStop.cpp +++ b/Easy2D/Action/EActionLoop.cpp @@ -19,7 +19,10 @@ e2d::EActionLoop * e2d::EActionLoop::clone() const void e2d::EActionLoop::_init() { EAction::_init(); - m_Action->m_pTarget = m_pTarget; + if (!m_Action->getTarget() && m_pTarget) + { + m_Action->setTarget(m_pTarget); + } m_Action->_init(); } diff --git a/Easy2D/Action/EActionMoveBy.cpp b/Easy2D/Action/EActionMoveBy.cpp index 3dbe2867..7a2fdace 100644 --- a/Easy2D/Action/EActionMoveBy.cpp +++ b/Easy2D/Action/EActionMoveBy.cpp @@ -2,20 +2,28 @@ e2d::EActionMoveBy::EActionMoveBy(float duration, EVec vector) : - EAnimation(duration) + EActionGradual(duration) { m_MoveVector = vector; } void e2d::EActionMoveBy::_init() { - EAnimation::_init(); - m_BeginPos = m_pTarget->getPos(); + EActionGradual::_init(); + if (m_pTarget) + { + m_BeginPos = m_pTarget->getPos(); + } } void e2d::EActionMoveBy::_callOn() { - while (EAnimation::_isDelayEnough()) + if (m_pTarget == nullptr) + { + this->stop(); + return; + } + while (EActionGradual::_isDelayEnough()) { // 计算移动位置 float scale = static_cast(m_nDuration) / m_nTotalDuration; @@ -35,7 +43,7 @@ void e2d::EActionMoveBy::_callOn() void e2d::EActionMoveBy::_reset() { - EAnimation::_reset(); + EActionGradual::_reset(); } e2d::EActionMoveBy * e2d::EActionMoveBy::clone() const diff --git a/Easy2D/Action/EActionOpacityBy.cpp b/Easy2D/Action/EActionOpacityBy.cpp index b9d2b6b0..6b66265e 100644 --- a/Easy2D/Action/EActionOpacityBy.cpp +++ b/Easy2D/Action/EActionOpacityBy.cpp @@ -2,20 +2,28 @@ e2d::EActionOpacityBy::EActionOpacityBy(float duration, float opacity) : - EAnimation(duration) + EActionGradual(duration) { m_nVariation = opacity; } void e2d::EActionOpacityBy::_init() { - EAnimation::_init(); - m_nBeginVal = m_pTarget->getOpacity(); + EActionGradual::_init(); + if (m_pTarget) + { + m_nBeginVal = m_pTarget->getOpacity(); + } } void e2d::EActionOpacityBy::_callOn() { - while (EAnimation::_isDelayEnough()) + if (m_pTarget == nullptr) + { + this->stop(); + return; + } + while (EActionGradual::_isDelayEnough()) { // 计算移动位置 float scale = static_cast(m_nDuration) / m_nTotalDuration; @@ -32,7 +40,7 @@ void e2d::EActionOpacityBy::_callOn() void e2d::EActionOpacityBy::_reset() { - EAnimation::_reset(); + EActionGradual::_reset(); } e2d::EActionOpacityBy * e2d::EActionOpacityBy::clone() const diff --git a/Easy2D/Action/EActionRotateBy.cpp b/Easy2D/Action/EActionRotateBy.cpp index c4e6515a..9ac061a5 100644 --- a/Easy2D/Action/EActionRotateBy.cpp +++ b/Easy2D/Action/EActionRotateBy.cpp @@ -2,20 +2,28 @@ e2d::EActionRotateBy::EActionRotateBy(float duration, float rotation) : - EAnimation(duration) + EActionGradual(duration) { m_nVariation = rotation; } void e2d::EActionRotateBy::_init() { - EAnimation::_init(); - m_nBeginVal = m_pTarget->getOpacity(); + EActionGradual::_init(); + if (m_pTarget) + { + m_nBeginVal = m_pTarget->getOpacity(); + } } void e2d::EActionRotateBy::_callOn() { - while (EAnimation::_isDelayEnough()) + if (m_pTarget == nullptr) + { + this->stop(); + return; + } + while (EActionGradual::_isDelayEnough()) { // 计算移动位置 float scale = static_cast(m_nDuration) / m_nTotalDuration; @@ -32,7 +40,7 @@ void e2d::EActionRotateBy::_callOn() void e2d::EActionRotateBy::_reset() { - EAnimation::_reset(); + EActionGradual::_reset(); } e2d::EActionRotateBy * e2d::EActionRotateBy::clone() const diff --git a/Easy2D/Action/EActionScaleBy.cpp b/Easy2D/Action/EActionScaleBy.cpp index 460cfec6..18110d14 100644 --- a/Easy2D/Action/EActionScaleBy.cpp +++ b/Easy2D/Action/EActionScaleBy.cpp @@ -2,7 +2,7 @@ e2d::EActionScaleBy::EActionScaleBy(float duration, float scaleX, float scaleY) : - EAnimation(duration) + EActionGradual(duration) { m_nVariationX = scaleX; m_nVariationY = scaleY; @@ -10,14 +10,22 @@ e2d::EActionScaleBy::EActionScaleBy(float duration, float scaleX, float scaleY) void e2d::EActionScaleBy::_init() { - EAnimation::_init(); - m_nBeginScaleX = m_pTarget->getScaleX(); - m_nBeginScaleY = m_pTarget->getScaleY(); + EActionGradual::_init(); + if (m_pTarget) + { + m_nBeginScaleX = m_pTarget->getScaleX(); + m_nBeginScaleY = m_pTarget->getScaleY(); + } } void e2d::EActionScaleBy::_callOn() { - while (EAnimation::_isDelayEnough()) + if (m_pTarget == nullptr) + { + this->stop(); + return; + } + while (EActionGradual::_isDelayEnough()) { // 计算移动位置 float scale = static_cast(m_nDuration) / m_nTotalDuration; @@ -34,7 +42,7 @@ void e2d::EActionScaleBy::_callOn() void e2d::EActionScaleBy::_reset() { - EAnimation::_reset(); + EActionGradual::_reset(); } e2d::EActionScaleBy * e2d::EActionScaleBy::clone() const diff --git a/Easy2D/Action/EActionSequence.cpp b/Easy2D/Action/EActionSequence.cpp index 0f36f1ac..8fc2c5d6 100644 --- a/Easy2D/Action/EActionSequence.cpp +++ b/Easy2D/Action/EActionSequence.cpp @@ -33,9 +33,15 @@ void e2d::EActionSequence::_init() { EAction::_init(); // 将所有动作与目标绑定 - for (auto action : m_vActions) + if (m_pTarget) { - action->m_pTarget = m_pTarget; + for (auto action : m_vActions) + { + if (!action->getTarget()) + { + action->setTarget(m_pTarget); + } + } } // 初始化第一个动作 m_vActions[0]->_init(); diff --git a/Easy2D/Action/EActionTwo.cpp b/Easy2D/Action/EActionTwo.cpp index 006b4eef..e2f29af4 100644 --- a/Easy2D/Action/EActionTwo.cpp +++ b/Easy2D/Action/EActionTwo.cpp @@ -34,8 +34,14 @@ e2d::EActionTwo * e2d::EActionTwo::reverse(bool actionReverse) const void e2d::EActionTwo::_init() { EAction::_init(); - m_pFirstAction->m_pTarget = m_pTarget; - m_pSecondAction->m_pTarget = m_pTarget; + if (!m_pFirstAction->getTarget() && m_pTarget) + { + m_pFirstAction->setTarget(m_pTarget); + } + if (!m_pSecondAction->getTarget() && m_pTarget) + { + m_pSecondAction->setTarget(m_pTarget); + } m_pFirstAction->_init(); } diff --git a/Easy2D/Action/EActionTwoAtSameTime.cpp b/Easy2D/Action/EActionTwoAtSameTime.cpp index f3bdefdd..c9a5ed08 100644 --- a/Easy2D/Action/EActionTwoAtSameTime.cpp +++ b/Easy2D/Action/EActionTwoAtSameTime.cpp @@ -34,8 +34,14 @@ e2d::EActionTwoAtSameTime * e2d::EActionTwoAtSameTime::reverse(bool actionRevers void e2d::EActionTwoAtSameTime::_init() { EAction::_init(); - m_pFirstAction->m_pTarget = m_pTarget; - m_pSecondAction->m_pTarget = m_pTarget; + if (!m_pFirstAction->getTarget() && m_pTarget) + { + m_pFirstAction->setTarget(m_pTarget); + } + if (!m_pSecondAction->getTarget() && m_pTarget) + { + m_pSecondAction->setTarget(m_pTarget); + } m_pFirstAction->_init(); m_pSecondAction->_init(); diff --git a/Easy2D/Action/EAnimation.cpp b/Easy2D/Action/EAnimation.cpp index 526a228a..f6a3ff77 100644 --- a/Easy2D/Action/EAnimation.cpp +++ b/Easy2D/Action/EAnimation.cpp @@ -1,41 +1,93 @@ #include "..\eactions.h" #include "..\Win\winbase.h" +#include -e2d::EAnimation::EAnimation(float duration) +e2d::EAnimation::EAnimation() : + m_nFrameIndex(0) { - m_nDuration = 0; - m_nTotalDuration = UINT(duration * 1000); + // 帧动画默认 0.1s 刷新一次 + setInterval(100); } -bool e2d::EAnimation::_isEnd() const +e2d::EAnimation::EAnimation(LONGLONG frameDelay) : + m_nFrameIndex(0) { - return m_nDuration >= m_nTotalDuration; + setInterval(frameDelay); +} + +e2d::EAnimation::~EAnimation() +{ + for (auto frame : m_vFrames) + { + SafeRelease(&frame); + } } void e2d::EAnimation::_init() { + // 判断执行帧动画的目标类型是否是 ESprite + ASSERT( + typeid(ESprite) == typeid(*m_pTarget), + "Only ESprite can use EAnimation!" + ); EAction::_init(); // 记录当前时间 - m_nLast = GetNow(); + m_tLast = GetNow(); } -bool e2d::EAnimation::_isDelayEnough() +void e2d::EAnimation::_callOn() { + if (m_pTarget == nullptr) + { + this->stop(); + return; + } // 判断时间间隔是否足够 - if (GetInterval(m_nLast) > m_nAnimationInterval) + while (GetInterval(m_tLast) > m_nAnimationInterval) { // 重新记录时间 - m_nLast += milliseconds(m_nAnimationInterval); - m_nDuration += m_nAnimationInterval; - return true; + m_tLast += milliseconds(m_nAnimationInterval); + reinterpret_cast(m_pTarget)->loadFromSpriteFrame(m_vFrames[m_nFrameIndex]); + m_nFrameIndex++; + // 判断动作是否结束 + if (m_nFrameIndex == m_vFrames.size()) + { + this->stop(); + break; + } } - return false; } void e2d::EAnimation::_reset() { EAction::_reset(); - m_nDuration = 0; + m_nFrameIndex = 0; // 记录当前时间 - m_nLast = GetNow(); + m_tLast = steady_clock::now(); +} + +void e2d::EAnimation::addFrame(ESpriteFrame * frame) +{ + if (frame) + { + m_vFrames.push_back(frame); + frame->retain(); + } +} + +e2d::EAnimation * e2d::EAnimation::clone() const +{ + auto a = new EAnimation(this->m_nAnimationInterval); + for (auto f : m_vFrames) + { + a->addFrame(f); + } + return a; +} + +e2d::EAnimation * e2d::EAnimation::reverse() const +{ + auto a = this->clone(); + a->m_vFrames.reserve(m_vFrames.size()); + return a; } diff --git a/Easy2D/Base/EApp.cpp b/Easy2D/Base/EApp.cpp index d144ad3d..7552e6ab 100644 --- a/Easy2D/Base/EApp.cpp +++ b/Easy2D/Base/EApp.cpp @@ -3,6 +3,7 @@ #include "..\emsg.h" #include "..\etools.h" #include "..\enodes.h" +#include "..\etransitions.h" #include #include #include @@ -20,7 +21,12 @@ static std::stack s_SceneStack; static steady_clock::time_point s_tStart; e2d::EApp::EApp() - : m_bRunning(false) + : m_bEnd(false) + , m_bPaused(false) + , m_bManualPaused(false) + , m_bTransitional(false) + , m_bEnterNextScene(true) + , m_bTopMost(false) , nAnimationInterval(17LL) , m_ClearColor(EColor::BLACK) , m_pCurrentScene(nullptr) @@ -29,17 +35,17 @@ e2d::EApp::EApp() ASSERT(s_pInstance == nullptr, "EApp instance already exists!"); s_pInstance = this; // 保存实例对象 - CoInitialize(NULL); + CoInitializeEx(NULL, COINIT_MULTITHREADED); } e2d::EApp::~EApp() { // 释放资源 + SafeReleaseInterface(&GetSolidColorBrush()); SafeReleaseInterface(&GetRenderTarget()); SafeReleaseInterface(&GetFactory()); SafeReleaseInterface(&GetImagingFactory()); SafeReleaseInterface(&GetDirectWriteFactory()); - SafeReleaseInterface(&GetSolidColorBrush()); CoUninitialize(); } @@ -52,7 +58,7 @@ e2d::EApp * e2d::EApp::get() bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, bool showConsole /* = false */) { - return init(title, width, height, WS_OVERLAPPEDWINDOW, showConsole); + return init(title, width, height, 0, showConsole); } bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, int windowStyle, bool showConsole /* = false */) @@ -69,7 +75,12 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, int wind { // 注册窗口类 WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; - wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; + UINT style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; + if (windowStyle & EApp::NO_CLOSE) + { + style |= CS_NOCLOSE; + } + wcex.style = style; wcex.lpfnWndProc = EApp::WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(LONG_PTR); @@ -106,15 +117,25 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, int wind rtWindow.top = (screenHeight - height) / 2; rtWindow.right = rtWindow.left + width; rtWindow.bottom = rtWindow.top + height; + // 创建窗口样式 + DWORD dwStyle = WS_OVERLAPPED | WS_SYSMENU; + if (windowStyle & EApp::NO_MINI_SIZE) + { + dwStyle &= ~WS_MINIMIZEBOX; + } + if (windowStyle & EApp::TOP_MOST) + { + m_bTopMost = true; + } // 计算客户区大小 - AdjustWindowRectEx(&rtWindow, windowStyle, FALSE, 0L); + AdjustWindowRectEx(&rtWindow, dwStyle, FALSE, 0L); // 保存窗口名称 m_sTitle = title; // 创建窗口 GetHWnd() = CreateWindow( L"Easy2DApp", m_sTitle.c_str(), - windowStyle, + dwStyle, rtWindow.left, rtWindow.top, rtWindow.right - rtWindow.left, @@ -146,6 +167,27 @@ bool e2d::EApp::init(const EString &title, UINT32 width, UINT32 height, int wind return SUCCEEDED(hr); } +void e2d::EApp::pause() +{ + EApp::get()->m_bManualPaused = true; +} + +void e2d::EApp::resume() +{ + if (isPaused()) + { + EApp::get()->m_bPaused = false; + EApp::get()->m_bManualPaused = false; + EActionManager::_resetAllActions(); + ETimerManager::_resetAllTimers(); + } +} + +bool e2d::EApp::isPaused() +{ + return s_pInstance->m_bPaused || s_pInstance->m_bManualPaused; +} + void e2d::EApp::showConsole(bool show) { // 查找已存在的控制台句柄 @@ -198,18 +240,20 @@ void e2d::EApp::run() ASSERT(GetHWnd() != nullptr, "Cannot find Game Window."); // 进入第一个场景 _enterNextScene(); - ASSERT(m_pCurrentScene != nullptr, "Current scene NULL pointer exception."); // 显示窗口 ShowWindow(GetHWnd(), SW_SHOWNORMAL); UpdateWindow(GetHWnd()); - // 运行游戏 - m_bRunning = true; + // 设置窗口置顶 + if (m_bTopMost) + { + SetWindowPos(GetHWnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } // 记录开始时间 s_tStart = steady_clock::now(); MSG msg; - while (m_bRunning) + while (!m_bEnd) { // 处理窗口消息 while (PeekMessage(&msg, GetHWnd(), 0, 0, PM_REMOVE)) @@ -224,17 +268,18 @@ void e2d::EApp::run() // 关闭控制台 EApp::showConsole(false); // 释放所有内存资源 - this->free(); + this->_free(); } void e2d::EApp::setFPS(UINT32 fps) { fps = min(max(fps, 30), 120); - nAnimationInterval = 1000 / fps; + s_pInstance->nAnimationInterval = 1000 / fps; } -void e2d::EApp::onActivate() +bool e2d::EApp::onActivate() { + return true; } bool e2d::EApp::onInactive() @@ -264,18 +309,10 @@ void e2d::EApp::_mainLoop() { // 记录当前时间 tLast = GetNow(); - - if (!m_bPaused) - { - // 游戏控制流程 - _onControl(); - // 刷新游戏画面 - if (!_onRender()) - { - MessageBox(GetHWnd(), L"Game Render Failed!", L"Error", MB_OK); - this->quit(); - } - } + // 游戏控制流程 + _onControl(); + // 刷新游戏画面 + _onRender(); } else { @@ -292,11 +329,20 @@ void e2d::EApp::_mainLoop() void e2d::EApp::_onControl() { // 下一场景指针不为空时,切换场景 - if (m_pNextScene) + if (m_bEnterNextScene) { // 进入下一场景 _enterNextScene(); + m_bEnterNextScene = false; } + + // 正在切换场景时,只执行动画 + if (m_bTransitional) + { + EActionManager::ActionProc(); + return; + } + // 断言当前场景非空 ASSERT(m_pCurrentScene != nullptr, "Current scene NULL pointer exception."); @@ -308,7 +354,7 @@ void e2d::EApp::_onControl() // This method discards device-specific // resources if the Direct3D device dissapears during execution and // recreates the resources the next time it's invoked. -bool e2d::EApp::_onRender() +void e2d::EApp::_onRender() { HRESULT hr = S_OK; @@ -316,12 +362,13 @@ bool e2d::EApp::_onRender() if (SUCCEEDED(hr)) { + // 开始绘图 GetRenderTarget()->BeginDraw(); // 使用背景色清空屏幕 GetRenderTarget()->Clear(D2D1::ColorF(m_ClearColor.value)); // 绘制当前场景 m_pCurrentScene->_onRender(); - + // 终止绘图 hr = GetRenderTarget()->EndDraw(); // 刷新界面 UpdateWindow(GetHWnd()); @@ -333,7 +380,11 @@ bool e2d::EApp::_onRender() _discardDeviceResources(); } - return SUCCEEDED(hr); + if (FAILED(hr)) + { + MessageBox(GetHWnd(), L"Game Render Failed!", L"Error", MB_OK); + this->quit(); + } } void e2d::EApp::setWindowSize(UINT32 width, UINT32 height) @@ -377,18 +428,44 @@ UINT32 e2d::EApp::getHeight() return GetRenderTarget()->GetPixelSize().height; } -void e2d::EApp::enterScene(EScene * scene, bool save /* = true */) +void e2d::EApp::enterScene(EScene * scene, bool saveCurrentScene /* = true */) { + enterScene(scene, nullptr, saveCurrentScene); +} + +void e2d::EApp::enterScene(EScene * scene, ETransition * transition, bool saveCurrentScene /* = true */) +{ + scene->retain(); // 保存下一场景的指针 get()->m_pNextScene = scene; // 切换场景时,是否保存当前场景 if (get()->m_pCurrentScene) { - get()->m_pCurrentScene->m_bWillSave = save; + get()->m_pCurrentScene->m_bWillSave = saveCurrentScene; + } + // 设置切换场景动画 + if (transition) + { + get()->m_bTransitional = true; + transition->_setTarget( + get()->m_pCurrentScene, + get()->m_pNextScene, + get()->m_bEnterNextScene, + get()->m_bTransitional + ); + } + else + { + get()->m_bTransitional = false; } } void e2d::EApp::backScene() +{ + backScene(nullptr); +} + +void e2d::EApp::backScene(ETransition * transition) { ASSERT(s_SceneStack.size(), "Scene stack now is empty!"); // 从栈顶取出场景指针,作为下一场景 @@ -399,6 +476,21 @@ void e2d::EApp::backScene() { get()->m_pCurrentScene->m_bWillSave = false; } + // 设置切换场景动画 + if (transition) + { + get()->m_bTransitional = true; + transition->_setTarget( + get()->m_pCurrentScene, + get()->m_pNextScene, + get()->m_bEnterNextScene, + get()->m_bTransitional + ); + } + else + { + get()->m_bTransitional = false; + } } void e2d::EApp::clearScene() @@ -407,7 +499,7 @@ void e2d::EApp::clearScene() while (s_SceneStack.size()) { auto temp = s_SceneStack.top(); - SafeDelete(&temp); + SafeRelease(&temp); s_SceneStack.pop(); } } @@ -475,41 +567,43 @@ void e2d::EApp::showWindow() ShowWindow(GetHWnd(), SW_SHOWNORMAL); } -void e2d::EApp::free() +void e2d::EApp::_free() { - // 释放场景内存 - SafeDelete(&m_pCurrentScene); - SafeDelete(&m_pNextScene); // 清空场景栈 - while (s_SceneStack.size()) - { - auto temp = s_SceneStack.top(); - SafeDelete(&temp); - s_SceneStack.pop(); - } + clearScene(); + // 释放场景内存 + SafeRelease(&m_pCurrentScene); + SafeRelease(&m_pNextScene); + // 删除图片缓存 ETexture::clearCache(); + // 停止所有定时器、监听器、动画 + ETimerManager::_clearManager(); + EMsgManager::_clearManager(); + EActionManager::_clearManager(); // 删除所有对象 EObjectManager::clearAllObjects(); } void e2d::EApp::quit() { - get()->m_bRunning = false; + get()->m_bEnd = true; } void e2d::EApp::end() { - get()->m_bRunning = false; + get()->m_bEnd = true; } void e2d::EApp::_enterNextScene() { + if (m_pNextScene == nullptr) + return; + // 执行当前场景的 onCloseWindow 函数 if (m_pCurrentScene) { m_pCurrentScene->onExit(); - m_pCurrentScene->_onExit(); if (m_pCurrentScene->m_bWillSave) { @@ -518,12 +612,11 @@ void e2d::EApp::_enterNextScene() } else { - SafeDelete(&m_pCurrentScene); + SafeRelease(&m_pCurrentScene); } } // 执行下一场景的 onEnter 函数 - m_pNextScene->_onEnter(); m_pNextScene->onEnter(); m_pCurrentScene = m_pNextScene; // 切换场景 @@ -627,7 +720,11 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam case WM_MOUSEMOVE: case WM_MOUSEWHEEL: { - EMsgManager::MouseProc(message, wParam, lParam); + // 执行场景切换时屏蔽按键和鼠标消息 + if (!pEApp->m_bTransitional) + { + EMsgManager::MouseProc(message, wParam, lParam); + } } result = 0; wasHandled = true; @@ -637,7 +734,11 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam case WM_KEYDOWN: case WM_KEYUP: { - EMsgManager::KeyboardProc(message, wParam, lParam); + // 执行场景切换时屏蔽按键和鼠标消息 + if (!pEApp->m_bTransitional) + { + EMsgManager::KeyboardProc(message, wParam, lParam); + } } result = 0; wasHandled = true; @@ -687,9 +788,11 @@ LRESULT e2d::EApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam } else { - pEApp->onActivate(); - pEApp->getCurrentScene()->onActivate(); - pEApp->m_bPaused = false; + if (pEApp->getCurrentScene()->onActivate() && + pEApp->onActivate()) + { + pEApp->m_bPaused = false; + } } } result = 1; diff --git a/Easy2D/Base/EScene.cpp b/Easy2D/Base/EScene.cpp index 8c736f1b..d7647f67 100644 --- a/Easy2D/Base/EScene.cpp +++ b/Easy2D/Base/EScene.cpp @@ -15,11 +15,11 @@ e2d::EScene::EScene() e2d::EScene::~EScene() { - SafeRelease(&m_pRoot); ETimerManager::clearAllTimersBindedWith(this); EMsgManager::clearAllMouseListenersBindedWith(this); EMsgManager::clearAllKeyboardListenersBindedWith(this); EActionManager::clearAllActionsBindedWith(this); + SafeRelease(&m_pRoot); } void e2d::EScene::onEnter() @@ -30,8 +30,9 @@ void e2d::EScene::onExit() { } -void e2d::EScene::onActivate() +bool e2d::EScene::onActivate() { + return true; } bool e2d::EScene::onInactive() @@ -49,26 +50,6 @@ void e2d::EScene::_onRender() m_pRoot->_callOn(); } -void e2d::EScene::_onEnter() -{ - // 启用场景上的所有定时器、监听器和动画 - ETimerManager::_notifyAllTimersBindedWith(this); - EMsgManager::_notifyAllMouseListenersBindedWith(this); - EMsgManager::_notifyAllKeyboardListenersBindedWith(this); - EActionManager::_notifyAllActionsBindedWith(this); -} - -void e2d::EScene::_onExit() -{ - if (m_bWillSave) - { - ETimerManager::_waitAllTimersBindedWith(this); - EMsgManager::_waitAllMouseListenersBindedWith(this); - EMsgManager::_waitAllKeyboardListenersBindedWith(this); - EActionManager::_waitAllActionsBindedWith(this); - } -} - void e2d::EScene::add(ENode * child, int order /* = 0 */) { m_pRoot->addChild(child, order); @@ -99,6 +80,11 @@ e2d::ENode * e2d::EScene::getChild(const EString &childName) return m_pRoot->getChild(childName); } +e2d::ENode * e2d::EScene::getRoot() const +{ + return m_pRoot; +} + void e2d::EScene::clearAllChildren() { m_pRoot->clearAllChildren(); diff --git a/Easy2D/ETimer.cpp b/Easy2D/ETimer.cpp index 3b42e30e..3272236a 100644 --- a/Easy2D/ETimer.cpp +++ b/Easy2D/ETimer.cpp @@ -3,7 +3,6 @@ e2d::ETimer::ETimer() : m_bRunning(false) - , m_bWaiting(false) , m_nRunTimes(0) , m_pParentScene(nullptr) , m_pParentNode(nullptr) @@ -33,12 +32,7 @@ e2d::ETimer::ETimer(const EString & name, const TIMER_CALLBACK & callback, LONGL bool e2d::ETimer::isRunning() const { - return m_bRunning && !m_bWaiting; -} - -bool e2d::ETimer::isWaiting() const -{ - return m_bWaiting; + return m_bRunning; } void e2d::ETimer::start() @@ -52,17 +46,6 @@ void e2d::ETimer::stop() m_bRunning = false; } -void e2d::ETimer::_wait() -{ - m_bWaiting = true; -} - -void e2d::ETimer::_notify() -{ - m_bWaiting = false; - m_tLast = GetNow(); -} - e2d::EString e2d::ETimer::getName() const { return m_sName; diff --git a/Easy2D/Easy2D.vcxproj b/Easy2D/Easy2D.vcxproj index 3a108153..c40ae968 100644 --- a/Easy2D/Easy2D.vcxproj +++ b/Easy2D/Easy2D.vcxproj @@ -195,10 +195,10 @@ - + - + @@ -208,30 +208,33 @@ - + - - - - - - - - - + + + + + + + + + + + + + - - + - + @@ -243,6 +246,7 @@ + diff --git a/Easy2D/Easy2D.vcxproj.filters b/Easy2D/Easy2D.vcxproj.filters index 6ca3be05..2c30e2ae 100644 --- a/Easy2D/Easy2D.vcxproj.filters +++ b/Easy2D/Easy2D.vcxproj.filters @@ -13,15 +13,18 @@ {261633d3-3814-40c7-bd6d-201ede6c6ade} - - {cc102a62-b34d-493c-be3c-f3e5dfbe4cf4} - - - {b9bb1728-5106-4574-998e-8564b49cb4a1} - {50293f38-87fe-4dde-b938-cf1b7a2921f8} + + {563b19f2-4c5e-4362-983a-94d2ae724550} + + + {9031e36b-fa85-4b4e-8e80-657c7e68f283} + + + {b9bb1728-5106-4574-998e-8564b49cb4a1} + @@ -36,48 +39,15 @@ Node - - Tool - Base - - Msg - - - Msg\Listener - - - Msg\Listener - - - Msg\Listener - - - Tool - Node - - Msg\Listener - - - Msg\Listener - - - Msg\Listener - Tool - - Msg\Listener - - - Msg\Listener - Node @@ -87,9 +57,6 @@ Node - - Tool - Action @@ -99,18 +66,12 @@ Action - - Action - Action Action - - Action - Action @@ -129,9 +90,6 @@ Action - - Action - Action @@ -147,6 +105,60 @@ Action + + Tool + + + Node + + + Action + + + Action + + + Transition + + + Action + + + Manager + + + Manager + + + Manager + + + Manager + + + Listener + + + Listener + + + Listener + + + Listener + + + Listener + + + Listener + + + Listener + + + Listener + @@ -160,5 +172,6 @@ + \ No newline at end of file diff --git a/Easy2D/Msg/Listener/EKeyboardListener.cpp b/Easy2D/Listener/EKeyboardListener.cpp similarity index 97% rename from Easy2D/Msg/Listener/EKeyboardListener.cpp rename to Easy2D/Listener/EKeyboardListener.cpp index 61b2a160..a95610a4 100644 --- a/Easy2D/Msg/Listener/EKeyboardListener.cpp +++ b/Easy2D/Listener/EKeyboardListener.cpp @@ -1,4 +1,4 @@ -#include "..\..\emsg.h" +#include "..\emsg.h" e2d::EKeyboardListener::EKeyboardListener() : EListener() diff --git a/Easy2D/Msg/Listener/EKeyboardPressListener.cpp b/Easy2D/Listener/EKeyboardPressListener.cpp similarity index 96% rename from Easy2D/Msg/Listener/EKeyboardPressListener.cpp rename to Easy2D/Listener/EKeyboardPressListener.cpp index 69162bec..7935ecc7 100644 --- a/Easy2D/Msg/Listener/EKeyboardPressListener.cpp +++ b/Easy2D/Listener/EKeyboardPressListener.cpp @@ -1,4 +1,4 @@ -#include "..\..\emsg.h" +#include "..\emsg.h" e2d::EKeyboardPressListener::EKeyboardPressListener() : EKeyboardListener() diff --git a/Easy2D/Msg/Listener/EListener.cpp b/Easy2D/Listener/EListener.cpp similarity index 66% rename from Easy2D/Msg/Listener/EListener.cpp rename to Easy2D/Listener/EListener.cpp index ff8b384d..336056a7 100644 --- a/Easy2D/Msg/Listener/EListener.cpp +++ b/Easy2D/Listener/EListener.cpp @@ -1,65 +1,49 @@ -#include "..\..\emsg.h" - -e2d::EListener::EListener() - : m_bRunning(false) - , m_bWaiting(false) - , m_pParentScene(nullptr) - , m_pParentNode(nullptr) -{ -} - -e2d::EListener::EListener(const EString & name) - : EListener() -{ - m_sName = name; -} - -bool e2d::EListener::isRunning() const -{ - return m_bRunning && !m_bWaiting; -} - -bool e2d::EListener::isWaiting() const -{ - return m_bWaiting; -} - -void e2d::EListener::start() -{ - m_bRunning = true; -} - -void e2d::EListener::stop() -{ - m_bRunning = false; -} - -void e2d::EListener::_wait() -{ - m_bWaiting = true; -} - -void e2d::EListener::_notify() -{ - m_bWaiting = false; -} - -e2d::EString e2d::EListener::getName() const -{ - return m_sName; -} - -e2d::EScene * e2d::EListener::getParentScene() const -{ - return m_pParentScene; -} - -e2d::ENode * e2d::EListener::getParentNode() const -{ - return m_pParentNode; -} - -void e2d::EListener::setName(const EString & name) -{ - m_sName = name; -} +#include "..\emsg.h" + +e2d::EListener::EListener() + : m_bRunning(false) + , m_pParentScene(nullptr) + , m_pParentNode(nullptr) +{ +} + +e2d::EListener::EListener(const EString & name) + : EListener() +{ + m_sName = name; +} + +bool e2d::EListener::isRunning() const +{ + return m_bRunning; +} + +void e2d::EListener::start() +{ + m_bRunning = true; +} + +void e2d::EListener::stop() +{ + m_bRunning = false; +} + +e2d::EString e2d::EListener::getName() const +{ + return m_sName; +} + +e2d::EScene * e2d::EListener::getParentScene() const +{ + return m_pParentScene; +} + +e2d::ENode * e2d::EListener::getParentNode() const +{ + return m_pParentNode; +} + +void e2d::EListener::setName(const EString & name) +{ + m_sName = name; +} diff --git a/Easy2D/Msg/Listener/EMouseClickListener.cpp b/Easy2D/Listener/EMouseClickListener.cpp similarity index 93% rename from Easy2D/Msg/Listener/EMouseClickListener.cpp rename to Easy2D/Listener/EMouseClickListener.cpp index f1b3c861..c76890a4 100644 --- a/Easy2D/Msg/Listener/EMouseClickListener.cpp +++ b/Easy2D/Listener/EMouseClickListener.cpp @@ -1,46 +1,46 @@ -#include "..\..\emsg.h" - -e2d::EMouseClickListener::EMouseClickListener() - : EMouseListener() - , m_bPressed(false) -{ -} - -e2d::EMouseClickListener::EMouseClickListener(const EString & name) - : EMouseListener(name) - , m_bPressed(false) -{ -} - -e2d::EMouseClickListener::EMouseClickListener(const MOUSE_CLICK_LISTENER_CALLBACK & callback) - : EMouseListener() - , m_Callback(callback) - , m_bPressed(false) -{ -} - -e2d::EMouseClickListener::EMouseClickListener(const EString & name, const MOUSE_CLICK_LISTENER_CALLBACK & callback) - : EMouseListener(name) - , m_Callback(callback) - , m_bPressed(false) -{ -} - -void e2d::EMouseClickListener::_callOn() -{ - if (EMouseMsg::getMsg() == EMouseMsg::LBUTTON_DOWN || - EMouseMsg::getMsg() == EMouseMsg::LBUTTON_DBLCLK) - { - m_bPressed = true; - } - else if (m_bPressed && EMouseMsg::getMsg() == EMouseMsg::LBUTTON_UP) - { - m_Callback(EMouseMsg::getPos()); - m_bPressed = false; - } -} - -void e2d::EMouseClickListener::setCallback(const MOUSE_CLICK_LISTENER_CALLBACK & callback) -{ - m_Callback = callback; -} +#include "..\emsg.h" + +e2d::EMouseClickListener::EMouseClickListener() + : EMouseListener() + , m_bPressed(false) +{ +} + +e2d::EMouseClickListener::EMouseClickListener(const EString & name) + : EMouseListener(name) + , m_bPressed(false) +{ +} + +e2d::EMouseClickListener::EMouseClickListener(const MOUSE_CLICK_LISTENER_CALLBACK & callback) + : EMouseListener() + , m_Callback(callback) + , m_bPressed(false) +{ +} + +e2d::EMouseClickListener::EMouseClickListener(const EString & name, const MOUSE_CLICK_LISTENER_CALLBACK & callback) + : EMouseListener(name) + , m_Callback(callback) + , m_bPressed(false) +{ +} + +void e2d::EMouseClickListener::_callOn() +{ + if (EMouseMsg::getMsg() == EMouseMsg::LBUTTON_DOWN || + EMouseMsg::getMsg() == EMouseMsg::LBUTTON_DBLCLK) + { + m_bPressed = true; + } + else if (m_bPressed && EMouseMsg::getMsg() == EMouseMsg::LBUTTON_UP) + { + m_Callback(EMouseMsg::getPos()); + m_bPressed = false; + } +} + +void e2d::EMouseClickListener::setCallback(const MOUSE_CLICK_LISTENER_CALLBACK & callback) +{ + m_Callback = callback; +} diff --git a/Easy2D/Msg/Listener/EMouseDoubleClickListener.cpp b/Easy2D/Listener/EMouseDoubleClickListener.cpp similarity index 97% rename from Easy2D/Msg/Listener/EMouseDoubleClickListener.cpp rename to Easy2D/Listener/EMouseDoubleClickListener.cpp index 8071f432..26679aff 100644 --- a/Easy2D/Msg/Listener/EMouseDoubleClickListener.cpp +++ b/Easy2D/Listener/EMouseDoubleClickListener.cpp @@ -1,4 +1,4 @@ -#include "..\..\emsg.h" +#include "..\emsg.h" e2d::EMouseDoubleClickListener::EMouseDoubleClickListener() : EMouseListener() diff --git a/Easy2D/Msg/Listener/EMouseDragListener.cpp b/Easy2D/Listener/EMouseDragListener.cpp similarity index 97% rename from Easy2D/Msg/Listener/EMouseDragListener.cpp rename to Easy2D/Listener/EMouseDragListener.cpp index 8eac4183..c2d1ac20 100644 --- a/Easy2D/Msg/Listener/EMouseDragListener.cpp +++ b/Easy2D/Listener/EMouseDragListener.cpp @@ -1,4 +1,4 @@ -#include "..\..\emsg.h" +#include "..\emsg.h" e2d::EMouseDragListener::EMouseDragListener() : EMouseListener() diff --git a/Easy2D/Msg/Listener/EMouseListener.cpp b/Easy2D/Listener/EMouseListener.cpp similarity index 93% rename from Easy2D/Msg/Listener/EMouseListener.cpp rename to Easy2D/Listener/EMouseListener.cpp index 90bcc713..e10f8bf8 100644 --- a/Easy2D/Msg/Listener/EMouseListener.cpp +++ b/Easy2D/Listener/EMouseListener.cpp @@ -1,53 +1,53 @@ -#include "..\..\emsg.h" - -e2d::EMouseListener::EMouseListener() - : EListener() -{ -} - -e2d::EMouseListener::EMouseListener(const EString & name) - : EListener(name) -{ -} - -e2d::EMouseListener::EMouseListener(const MOUSE_LISTENER_CALLBACK & callback) - : EListener() -{ - m_Callback = callback; -} - -e2d::EMouseListener::EMouseListener(const EString & name, const MOUSE_LISTENER_CALLBACK & callback) - : EListener(name) -{ - m_Callback = callback; -} - -void e2d::EMouseListener::_callOn() -{ - m_Callback(); -} - -void e2d::EMouseListener::setCallback(const MOUSE_LISTENER_CALLBACK & callback) -{ - m_Callback = callback; -} - -void e2d::EMouseListener::bindWith(EScene * pParentScene) -{ - WARN_IF(m_pParentScene != nullptr || m_pParentNode != nullptr, "EListener cannot bind with two object."); - - if (pParentScene) - { - EMsgManager::bindListener(this, pParentScene); - } -} - -void e2d::EMouseListener::bindWith(ENode * pParentNode) -{ - WARN_IF(m_pParentScene != nullptr || m_pParentNode != nullptr, "EListener cannot bind with two object."); - - if (pParentNode != nullptr && m_pParentScene == nullptr) - { - EMsgManager::bindListener(this, pParentNode); - } -} +#include "..\emsg.h" + +e2d::EMouseListener::EMouseListener() + : EListener() +{ +} + +e2d::EMouseListener::EMouseListener(const EString & name) + : EListener(name) +{ +} + +e2d::EMouseListener::EMouseListener(const MOUSE_LISTENER_CALLBACK & callback) + : EListener() +{ + m_Callback = callback; +} + +e2d::EMouseListener::EMouseListener(const EString & name, const MOUSE_LISTENER_CALLBACK & callback) + : EListener(name) +{ + m_Callback = callback; +} + +void e2d::EMouseListener::_callOn() +{ + m_Callback(); +} + +void e2d::EMouseListener::setCallback(const MOUSE_LISTENER_CALLBACK & callback) +{ + m_Callback = callback; +} + +void e2d::EMouseListener::bindWith(EScene * pParentScene) +{ + WARN_IF(m_pParentScene != nullptr || m_pParentNode != nullptr, "EListener cannot bind with two object."); + + if (pParentScene) + { + EMsgManager::bindListener(this, pParentScene); + } +} + +void e2d::EMouseListener::bindWith(ENode * pParentNode) +{ + WARN_IF(m_pParentScene != nullptr || m_pParentNode != nullptr, "EListener cannot bind with two object."); + + if (pParentNode != nullptr && m_pParentScene == nullptr) + { + EMsgManager::bindListener(this, pParentNode); + } +} diff --git a/Easy2D/Msg/Listener/EMousePressListener.cpp b/Easy2D/Listener/EMousePressListener.cpp similarity index 97% rename from Easy2D/Msg/Listener/EMousePressListener.cpp rename to Easy2D/Listener/EMousePressListener.cpp index 81d94344..1f71b219 100644 --- a/Easy2D/Msg/Listener/EMousePressListener.cpp +++ b/Easy2D/Listener/EMousePressListener.cpp @@ -1,4 +1,4 @@ -#include "..\..\emsg.h" +#include "..\emsg.h" e2d::EMousePressListener::EMousePressListener() : EMouseListener() diff --git a/Easy2D/Tool/EActionManager.cpp b/Easy2D/Manager/EActionManager.cpp similarity index 66% rename from Easy2D/Tool/EActionManager.cpp rename to Easy2D/Manager/EActionManager.cpp index 8c70df05..cecf5ab5 100644 --- a/Easy2D/Tool/EActionManager.cpp +++ b/Easy2D/Manager/EActionManager.cpp @@ -1,23 +1,18 @@ #include "..\etools.h" #include "..\eactions.h" +#include "..\Win\winbase.h" static e2d::EVector s_vActions; -void e2d::EActionManager::bindAction(EAction * action, ENode * pTargetNode) +void e2d::EActionManager::addAction(EAction * action) { - ASSERT( - (!action->m_pTarget), - "The action is already running, it cannot running again!" - ); WARN_IF(action == nullptr, "EAction NULL pointer exception!"); - WARN_IF(pTargetNode == nullptr, "EAction's target is NULL!"); - if (action && pTargetNode) + if (action) { action->start(); action->retain(); - action->m_pTarget = pTargetNode; s_vActions.push_back(action); } } @@ -130,67 +125,22 @@ void e2d::EActionManager::clearAllActions() EActionManager::clearAllActionsBindedWith(EApp::getCurrentScene()); } -void e2d::EActionManager::_waitAllActionsBindedWith(EScene * pParentScene) +void e2d::EActionManager::_clearManager() { - if (pParentScene) - { - for (const auto &child : pParentScene->getChildren()) - { - EActionManager::_waitAllActionsBindedWith(child); - } - } + s_vActions.clear(); } -void e2d::EActionManager::_notifyAllActionsBindedWith(EScene * pParentScene) +void e2d::EActionManager::_resetAllActions() { - if (pParentScene) + for (const auto & action : s_vActions) { - for (const auto &child : pParentScene->getChildren()) - { - EActionManager::_notifyAllActionsBindedWith(child); - } - } -} - -void e2d::EActionManager::_waitAllActionsBindedWith(ENode * pTargetNode) -{ - if (pTargetNode) - { - for (const auto &action : s_vActions) - { - if (action->getTarget() == pTargetNode) - { - action->_wait(); - } - } - for (const auto &child : pTargetNode->getChildren()) - { - EActionManager::_waitAllActionsBindedWith(child); - } - } -} - -void e2d::EActionManager::_notifyAllActionsBindedWith(ENode * pTargetNode) -{ - if (pTargetNode) - { - for (const auto &action : s_vActions) - { - if (action->getTarget() == pTargetNode) - { - action->_notify(); - } - } - for (const auto &child : pTargetNode->getChildren()) - { - EActionManager::_notifyAllActionsBindedWith(child); - } + action->m_tLast = GetNow(); } } void e2d::EActionManager::ActionProc() { - if (s_vActions.empty()) + if (EApp::isPaused() || s_vActions.empty()) return; EAction * action; @@ -199,7 +149,8 @@ void e2d::EActionManager::ActionProc() { action = s_vActions[i]; // 获取动作运行状态 - if (action->isRunning()) + if (action->isRunning() || + (action->getTarget() && action->getTarget()->getParentScene() == EApp::getCurrentScene())) { if (action->_isEnding()) { diff --git a/Easy2D/Msg/EMsgManager.cpp b/Easy2D/Manager/EMsgManager.cpp similarity index 78% rename from Easy2D/Msg/EMsgManager.cpp rename to Easy2D/Manager/EMsgManager.cpp index 8229bcea..612f6d65 100644 --- a/Easy2D/Msg/EMsgManager.cpp +++ b/Easy2D/Manager/EMsgManager.cpp @@ -1,659 +1,558 @@ -#include "..\emsg.h" -#include "..\enodes.h" -#include "..\Win\winbase.h" - - -// 鼠标消息 -e2d::EMouseMsg s_MouseMsg; -// 按键消息 -e2d::EKeyboardMsg s_KeyboardMsg; -// 鼠标消息监听器 -e2d::EVector s_vMouseListeners; -// 按键消息监听器 -e2d::EVector s_vKeyboardListeners; - - -DWORD e2d::EMouseMsg::getPosX() -{ - return LOWORD(s_MouseMsg.m_lParam); -} - -DWORD e2d::EMouseMsg::getPosY() -{ - return HIWORD(s_MouseMsg.m_lParam); -} - -e2d::EPoint e2d::EMouseMsg::getPos() -{ - return EPoint(LOWORD(s_MouseMsg.m_lParam), HIWORD(s_MouseMsg.m_lParam)); -} - -bool e2d::EMouseMsg::isLButtonDown() -{ - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_LBUTTON; -} - -bool e2d::EMouseMsg::isMButtonDown() -{ - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_MBUTTON; -} - -bool e2d::EMouseMsg::isRButtonDown() -{ - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_RBUTTON; -} - -bool e2d::EMouseMsg::isShiftDown() -{ - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_SHIFT; -} - -bool e2d::EMouseMsg::isCtrlDown() -{ - return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_CONTROL; -} - -DWORD e2d::EMouseMsg::getWheelDelta() -{ - return GET_WHEEL_DELTA_WPARAM(s_MouseMsg.m_wParam); -} - -e2d::EMouseMsg::MOUSE_MSG e2d::EMouseMsg::getMsg() -{ - return MOUSE_MSG(s_MouseMsg.m_nMsg); -} - - - -e2d::EKeyboardMsg::KEYBOARD_MSG e2d::EKeyboardMsg::getMsg() -{ - return KEYBOARD_MSG(s_KeyboardMsg.m_nMsg); -} - -e2d::EKeyboardMsg::KEY e2d::EKeyboardMsg::getVal() -{ - return KEY(s_KeyboardMsg.m_wParam); -} - -DWORD e2d::EKeyboardMsg::getCount() -{ - return (((DWORD)s_KeyboardMsg.m_lParam) & 0x0000FFFF); -} - -bool e2d::EKeyboardMsg::isKeyDown(KEY key) -{ - if (::GetAsyncKeyState((int)key) & 0x8000) - { - return true; - } - return false; -} - -bool e2d::EKeyboardMsg::isCapitalLockOn() -{ - if (::GetKeyState(VK_CAPITAL) & 0x0001) - { - return true; - } - return false; -} - -bool e2d::EKeyboardMsg::isNumpadLockOn() -{ - if (::GetKeyState(VK_NUMLOCK) & 0x0001) - { - return true; - } - return false; -} - -bool e2d::EKeyboardMsg::isScrollLockOn() -{ - if (::GetKeyState(VK_SCROLL) & 0x0001) - { - return true; - } - return false; -} - - - -void e2d::EMsgManager::MouseProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - // 保存鼠标消息 - s_MouseMsg.m_nMsg = message; - s_MouseMsg.m_wParam = wParam; - s_MouseMsg.m_lParam = lParam; - // 执行鼠标消息监听函数 - for (auto mlistener : s_vMouseListeners) - { - if (mlistener->isRunning()) - { - mlistener->_callOn(); - } - } -} - -void e2d::EMsgManager::KeyboardProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - // 保存按键消息 - s_KeyboardMsg.m_nMsg = message; - s_KeyboardMsg.m_wParam = wParam; - s_KeyboardMsg.m_lParam = lParam; - // 执行按键消息监听函数 - for (auto klistener : s_vKeyboardListeners) - { - if (klistener->isRunning()) - { - klistener->_callOn(); - } - } -} - -void e2d::EMsgManager::bindListener(e2d::EMouseListener * listener, EScene * pParentScene) -{ - ASSERT( - (!listener->m_pParentNode) && (!listener->m_pParentScene), - "The listener is already binded, it cannot bind again!" - ); - WARN_IF(listener == nullptr, "EMouseListener NULL pointer exception!"); - WARN_IF(pParentScene == nullptr, "Bind EMouseListener with a NULL EScene pointer!"); - - if (listener && pParentScene) - { - listener->start(); - listener->retain(); - listener->m_pParentScene = pParentScene; - s_vMouseListeners.push_back(listener); - } -} - -void e2d::EMsgManager::bindListener(EKeyboardListener * listener, EScene * pParentScene) -{ - ASSERT( - (!listener->m_pParentNode) && (!listener->m_pParentScene), - "The listener is already binded, it cannot bind again!" - ); - WARN_IF(listener == nullptr, "EKeyboardListener NULL pointer exception!"); - WARN_IF(pParentScene == nullptr, "Bind EKeyboardListener with a NULL EScene pointer!"); - - if (listener && pParentScene) - { - listener->start(); - listener->retain(); - listener->m_pParentScene = pParentScene; - s_vKeyboardListeners.push_back(listener); - } -} - -void e2d::EMsgManager::bindListener(EMouseListener * listener, ENode * pParentNode) -{ - ASSERT( - (!listener->m_pParentNode) && (!listener->m_pParentScene), - "The listener is already binded, it cannot bind again!" - ); - WARN_IF(listener == nullptr, "EMouseListener NULL pointer exception!"); - WARN_IF(pParentNode == nullptr, "Bind EMouseListener with a NULL ENode pointer!"); - - if (listener && pParentNode) - { - listener->start(); - listener->retain(); - listener->m_pParentNode = pParentNode; - s_vMouseListeners.push_back(listener); - } -} - -void e2d::EMsgManager::bindListener(EKeyboardListener * listener, ENode * pParentNode) -{ - ASSERT( - (!listener->m_pParentNode) && (!listener->m_pParentScene), - "The listener is already binded, it cannot bind again!" - ); - WARN_IF(listener == nullptr, "EKeyboardListener NULL pointer exception!"); - WARN_IF(pParentNode == nullptr, "Bind EKeyboardListener with a NULL ENode pointer!"); - - if (listener && pParentNode) - { - listener->start(); - listener->retain(); - listener->m_pParentNode = pParentNode; - s_vKeyboardListeners.push_back(listener); - } -} - -void e2d::EMsgManager::startMouseListeners(const EString & name) -{ - for (auto l : s_vMouseListeners) - { - if (l->getName() == name) - { - l->start(); - } - } -} - -void e2d::EMsgManager::stopMouseListeners(const EString & name) -{ - for (auto l : s_vMouseListeners) - { - if (l->getName() == name) - { - l->stop(); - } - } -} - -void e2d::EMsgManager::delMouseListeners(const EString & name) -{ - // 删除鼠标消息监听器 - EVector::iterator mIter; - for (mIter = s_vMouseListeners.begin(); mIter != s_vMouseListeners.end();) - { - if ((*mIter)->getName() == name) - { - SafeRelease(&(*mIter)); - mIter = s_vMouseListeners.erase(mIter); - } - else - { - mIter++; - } - } -} - -void e2d::EMsgManager::startKeyboardListeners(const EString & name) -{ - // 启动按键消息监听器 - for (auto l : s_vKeyboardListeners) - { - if (l->getName() == name) - { - l->start(); - } - } -} - -void e2d::EMsgManager::stopKeyboardListeners(const EString & name) -{ - // 停止按键消息监听器 - for (auto l : s_vKeyboardListeners) - { - if (l->getName() == name) - { - l->stop(); - } - } -} - -void e2d::EMsgManager::delKeyboardListeners(const EString & name) -{ - // 删除按键消息监听器 - EVector::iterator kIter; - for (kIter = s_vKeyboardListeners.begin(); kIter != s_vKeyboardListeners.end();) - { - if ((*kIter)->getName() == name) - { - SafeRelease(&(*kIter)); - kIter = s_vKeyboardListeners.erase(kIter); - } - else - { - kIter++; - } - } -} - -void e2d::EMsgManager::startAllMouseListenersBindedWith(EScene * pParentScene) -{ - for (auto l : s_vMouseListeners) - { - if (l->getParentScene() == pParentScene) - { - l->start(); - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::startAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::stopAllMouseListenersBindedWith(EScene * pParentScene) -{ - for (auto l : s_vMouseListeners) - { - if (l->getParentScene() == pParentScene) - { - l->stop(); - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::stopAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::startAllMouseListenersBindedWith(ENode * pParentNode) -{ - for (auto l : s_vMouseListeners) - { - if (l->getParentNode() == pParentNode) - { - l->start(); - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::startAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::stopAllMouseListenersBindedWith(ENode * pParentNode) -{ - for (auto l : s_vMouseListeners) - { - if (l->getParentNode() == pParentNode) - { - l->stop(); - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::stopAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::startAllKeyboardListenersBindedWith(EScene * pParentScene) -{ - for (auto l : s_vKeyboardListeners) - { - if (l->getParentScene() == pParentScene) - { - l->start(); - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::startAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::stopAllKeyboardListenersBindedWith(EScene * pParentScene) -{ - for (auto l : s_vKeyboardListeners) - { - if (l->getParentScene() == pParentScene) - { - l->stop(); - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::stopAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::startAllKeyboardListenersBindedWith(ENode * pParentNode) -{ - for (auto l : s_vKeyboardListeners) - { - if (l->getParentNode() == pParentNode) - { - l->start(); - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::startAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::stopAllKeyboardListenersBindedWith(ENode * pParentNode) -{ - for (auto l : s_vKeyboardListeners) - { - if (l->getParentNode() == pParentNode) - { - l->stop(); - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::stopAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::clearAllMouseListenersBindedWith(EScene * pParentScene) -{ - for (size_t i = 0; i < s_vMouseListeners.size();) - { - auto t = s_vMouseListeners[i]; - if (t->getParentScene() == pParentScene) - { - SafeRelease(&t); - s_vMouseListeners.erase(s_vMouseListeners.begin() + i); - } - else - { - i++; - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::clearAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::clearAllKeyboardListenersBindedWith(EScene * pParentScene) -{ - for (size_t i = 0; i < s_vKeyboardListeners.size();) - { - auto t = s_vKeyboardListeners[i]; - if (t->getParentScene() == pParentScene) - { - SafeRelease(&t); - s_vKeyboardListeners.erase(s_vKeyboardListeners.begin() + i); - } - else - { - i++; - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::clearAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::clearAllMouseListenersBindedWith(ENode * pParentNode) -{ - for (size_t i = 0; i < s_vMouseListeners.size();) - { - auto t = s_vMouseListeners[i]; - if (t->getParentNode() == pParentNode) - { - SafeRelease(&t); - s_vMouseListeners.erase(s_vMouseListeners.begin() + i); - } - else - { - i++; - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::clearAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::clearAllKeyboardListenersBindedWith(ENode * pParentNode) -{ - for (size_t i = 0; i < s_vKeyboardListeners.size();) - { - auto t = s_vKeyboardListeners[i]; - if (t->getParentNode() == pParentNode) - { - SafeRelease(&t); - s_vKeyboardListeners.erase(s_vKeyboardListeners.begin() + i); - } - else - { - i++; - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::clearAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::_waitAllMouseListenersBindedWith(EScene * pParentScene) -{ - for (auto l : s_vMouseListeners) - { - if (l->getParentScene() == pParentScene) - { - l->_wait(); - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::_waitAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::_notifyAllMouseListenersBindedWith(EScene * pParentScene) -{ - for (auto l : s_vMouseListeners) - { - if (l->getParentScene() == pParentScene) - { - l->_notify(); - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::_notifyAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::_waitAllMouseListenersBindedWith(ENode * pParentNode) -{ - for (auto l : s_vMouseListeners) - { - if (l->getParentNode() == pParentNode) - { - l->_wait(); - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::_waitAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::_notifyAllMouseListenersBindedWith(ENode * pParentNode) -{ - for (auto l : s_vMouseListeners) - { - if (l->getParentNode() == pParentNode) - { - l->_notify(); - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::_notifyAllMouseListenersBindedWith(child); - } -} - -void e2d::EMsgManager::_waitAllKeyboardListenersBindedWith(EScene * pParentScene) -{ - for (auto l : s_vKeyboardListeners) - { - if (l->getParentScene() == pParentScene) - { - l->_wait(); - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::_waitAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::_notifyAllKeyboardListenersBindedWith(EScene * pParentScene) -{ - for (auto l : s_vKeyboardListeners) - { - if (l->getParentScene() == pParentScene) - { - l->_notify(); - } - } - for (auto child : pParentScene->getChildren()) - { - EMsgManager::_notifyAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::_waitAllKeyboardListenersBindedWith(ENode * pParentNode) -{ - for (auto l : s_vKeyboardListeners) - { - if (l->getParentNode() == pParentNode) - { - l->_wait(); - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::_waitAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::_notifyAllKeyboardListenersBindedWith(ENode * pParentNode) -{ - for (auto l : s_vKeyboardListeners) - { - if (l->getParentNode() == pParentNode) - { - l->_notify(); - } - } - for (auto child : pParentNode->getChildren()) - { - EMsgManager::_notifyAllKeyboardListenersBindedWith(child); - } -} - -void e2d::EMsgManager::startAllMouseListeners() -{ - EMsgManager::startAllMouseListenersBindedWith(EApp::getCurrentScene()); -} - -void e2d::EMsgManager::stopAllMouseListeners() -{ - EMsgManager::stopAllMouseListenersBindedWith(EApp::getCurrentScene()); -} - -void e2d::EMsgManager::clearAllMouseListeners() -{ - EMsgManager::clearAllMouseListenersBindedWith(EApp::getCurrentScene()); -} - -void e2d::EMsgManager::startAllKeyboardListeners() -{ - EMsgManager::startAllKeyboardListenersBindedWith(EApp::getCurrentScene()); -} - -void e2d::EMsgManager::stopAllKeyboardListeners() -{ - EMsgManager::stopAllKeyboardListenersBindedWith(EApp::getCurrentScene()); -} - -void e2d::EMsgManager::clearAllKeyboardListeners() -{ - EMsgManager::clearAllKeyboardListenersBindedWith(EApp::getCurrentScene()); +#include "..\emsg.h" +#include "..\enodes.h" +#include "..\Win\winbase.h" + + +// 鼠标消息 +e2d::EMouseMsg s_MouseMsg; +// 按键消息 +e2d::EKeyboardMsg s_KeyboardMsg; +// 鼠标消息监听器 +e2d::EVector s_vMouseListeners; +// 按键消息监听器 +e2d::EVector s_vKeyboardListeners; + + +void e2d::EMsgManager::MouseProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (EApp::isPaused()) + return; + + // 保存鼠标消息 + s_MouseMsg.m_nMsg = message; + s_MouseMsg.m_wParam = wParam; + s_MouseMsg.m_lParam = lParam; + // 执行鼠标消息监听函数 + for (auto mlistener : s_vMouseListeners) + { + if (mlistener->isRunning()) + { + if (mlistener->getParentScene() == EApp::getCurrentScene() || + (mlistener->getParentNode() && mlistener->getParentNode()->getParentScene() == EApp::getCurrentScene())) + { + mlistener->_callOn(); + } + } + } +} + +void e2d::EMsgManager::KeyboardProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (EApp::isPaused()) + return; + + // 保存按键消息 + s_KeyboardMsg.m_nMsg = message; + s_KeyboardMsg.m_wParam = wParam; + s_KeyboardMsg.m_lParam = lParam; + // 执行按键消息监听函数 + for (auto klistener : s_vKeyboardListeners) + { + if (klistener->isRunning()) + { + if (klistener->getParentScene() == EApp::getCurrentScene() || + (klistener->getParentNode() && klistener->getParentNode()->getParentScene() == EApp::getCurrentScene())) + { + klistener->_callOn(); + } + } + } +} + + +DWORD e2d::EMouseMsg::getPosX() +{ + return LOWORD(s_MouseMsg.m_lParam); +} + +DWORD e2d::EMouseMsg::getPosY() +{ + return HIWORD(s_MouseMsg.m_lParam); +} + +e2d::EPoint e2d::EMouseMsg::getPos() +{ + return EPoint(LOWORD(s_MouseMsg.m_lParam), HIWORD(s_MouseMsg.m_lParam)); +} + +bool e2d::EMouseMsg::isLButtonDown() +{ + return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_LBUTTON; +} + +bool e2d::EMouseMsg::isMButtonDown() +{ + return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_MBUTTON; +} + +bool e2d::EMouseMsg::isRButtonDown() +{ + return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_RBUTTON; +} + +bool e2d::EMouseMsg::isShiftDown() +{ + return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_SHIFT; +} + +bool e2d::EMouseMsg::isCtrlDown() +{ + return GET_KEYSTATE_WPARAM(s_MouseMsg.m_wParam) == MK_CONTROL; +} + +DWORD e2d::EMouseMsg::getWheelDelta() +{ + return GET_WHEEL_DELTA_WPARAM(s_MouseMsg.m_wParam); +} + +e2d::EMouseMsg::MOUSE_MSG e2d::EMouseMsg::getMsg() +{ + return MOUSE_MSG(s_MouseMsg.m_nMsg); +} + + + +e2d::EKeyboardMsg::KEYBOARD_MSG e2d::EKeyboardMsg::getMsg() +{ + return KEYBOARD_MSG(s_KeyboardMsg.m_nMsg); +} + +e2d::EKeyboardMsg::KEY e2d::EKeyboardMsg::getVal() +{ + return KEY(s_KeyboardMsg.m_wParam); +} + +DWORD e2d::EKeyboardMsg::getCount() +{ + return (((DWORD)s_KeyboardMsg.m_lParam) & 0x0000FFFF); +} + +bool e2d::EKeyboardMsg::isKeyDown(KEY key) +{ + if (::GetAsyncKeyState((int)key) & 0x8000) + { + return true; + } + return false; +} + +bool e2d::EKeyboardMsg::isCapitalLockOn() +{ + if (::GetKeyState(VK_CAPITAL) & 0x0001) + { + return true; + } + return false; +} + +bool e2d::EKeyboardMsg::isNumpadLockOn() +{ + if (::GetKeyState(VK_NUMLOCK) & 0x0001) + { + return true; + } + return false; +} + +bool e2d::EKeyboardMsg::isScrollLockOn() +{ + if (::GetKeyState(VK_SCROLL) & 0x0001) + { + return true; + } + return false; +} + +void e2d::EMsgManager::bindListener(e2d::EMouseListener * listener, EScene * pParentScene) +{ + ASSERT( + (!listener->m_pParentNode) && (!listener->m_pParentScene), + "The listener is already binded, it cannot bind again!" + ); + WARN_IF(listener == nullptr, "EMouseListener NULL pointer exception!"); + WARN_IF(pParentScene == nullptr, "Bind EMouseListener with a NULL EScene pointer!"); + + if (listener && pParentScene) + { + listener->start(); + listener->retain(); + listener->m_pParentScene = pParentScene; + s_vMouseListeners.push_back(listener); + } +} + +void e2d::EMsgManager::bindListener(EKeyboardListener * listener, EScene * pParentScene) +{ + ASSERT( + (!listener->m_pParentNode) && (!listener->m_pParentScene), + "The listener is already binded, it cannot bind again!" + ); + WARN_IF(listener == nullptr, "EKeyboardListener NULL pointer exception!"); + WARN_IF(pParentScene == nullptr, "Bind EKeyboardListener with a NULL EScene pointer!"); + + if (listener && pParentScene) + { + listener->start(); + listener->retain(); + listener->m_pParentScene = pParentScene; + s_vKeyboardListeners.push_back(listener); + } +} + +void e2d::EMsgManager::bindListener(EMouseListener * listener, ENode * pParentNode) +{ + ASSERT( + (!listener->m_pParentNode) && (!listener->m_pParentScene), + "The listener is already binded, it cannot bind again!" + ); + WARN_IF(listener == nullptr, "EMouseListener NULL pointer exception!"); + WARN_IF(pParentNode == nullptr, "Bind EMouseListener with a NULL ENode pointer!"); + + if (listener && pParentNode) + { + listener->start(); + listener->retain(); + listener->m_pParentNode = pParentNode; + s_vMouseListeners.push_back(listener); + } +} + +void e2d::EMsgManager::bindListener(EKeyboardListener * listener, ENode * pParentNode) +{ + ASSERT( + (!listener->m_pParentNode) && (!listener->m_pParentScene), + "The listener is already binded, it cannot bind again!" + ); + WARN_IF(listener == nullptr, "EKeyboardListener NULL pointer exception!"); + WARN_IF(pParentNode == nullptr, "Bind EKeyboardListener with a NULL ENode pointer!"); + + if (listener && pParentNode) + { + listener->start(); + listener->retain(); + listener->m_pParentNode = pParentNode; + s_vKeyboardListeners.push_back(listener); + } +} + +void e2d::EMsgManager::startMouseListeners(const EString & name) +{ + for (auto l : s_vMouseListeners) + { + if (l->getName() == name) + { + l->start(); + } + } +} + +void e2d::EMsgManager::stopMouseListeners(const EString & name) +{ + for (auto l : s_vMouseListeners) + { + if (l->getName() == name) + { + l->stop(); + } + } +} + +void e2d::EMsgManager::delMouseListeners(const EString & name) +{ + // 删除鼠标消息监听器 + EVector::iterator mIter; + for (mIter = s_vMouseListeners.begin(); mIter != s_vMouseListeners.end();) + { + if ((*mIter)->getName() == name) + { + SafeRelease(&(*mIter)); + mIter = s_vMouseListeners.erase(mIter); + } + else + { + mIter++; + } + } +} + +void e2d::EMsgManager::startKeyboardListeners(const EString & name) +{ + // 启动按键消息监听器 + for (auto l : s_vKeyboardListeners) + { + if (l->getName() == name) + { + l->start(); + } + } +} + +void e2d::EMsgManager::stopKeyboardListeners(const EString & name) +{ + // 停止按键消息监听器 + for (auto l : s_vKeyboardListeners) + { + if (l->getName() == name) + { + l->stop(); + } + } +} + +void e2d::EMsgManager::delKeyboardListeners(const EString & name) +{ + // 删除按键消息监听器 + EVector::iterator kIter; + for (kIter = s_vKeyboardListeners.begin(); kIter != s_vKeyboardListeners.end();) + { + if ((*kIter)->getName() == name) + { + SafeRelease(&(*kIter)); + kIter = s_vKeyboardListeners.erase(kIter); + } + else + { + kIter++; + } + } +} + +void e2d::EMsgManager::startAllMouseListenersBindedWith(EScene * pParentScene) +{ + for (auto l : s_vMouseListeners) + { + if (l->getParentScene() == pParentScene) + { + l->start(); + } + } + for (auto child : pParentScene->getChildren()) + { + EMsgManager::startAllMouseListenersBindedWith(child); + } +} + +void e2d::EMsgManager::stopAllMouseListenersBindedWith(EScene * pParentScene) +{ + for (auto l : s_vMouseListeners) + { + if (l->getParentScene() == pParentScene) + { + l->stop(); + } + } + for (auto child : pParentScene->getChildren()) + { + EMsgManager::stopAllMouseListenersBindedWith(child); + } +} + +void e2d::EMsgManager::startAllMouseListenersBindedWith(ENode * pParentNode) +{ + for (auto l : s_vMouseListeners) + { + if (l->getParentNode() == pParentNode) + { + l->start(); + } + } + for (auto child : pParentNode->getChildren()) + { + EMsgManager::startAllMouseListenersBindedWith(child); + } +} + +void e2d::EMsgManager::stopAllMouseListenersBindedWith(ENode * pParentNode) +{ + for (auto l : s_vMouseListeners) + { + if (l->getParentNode() == pParentNode) + { + l->stop(); + } + } + for (auto child : pParentNode->getChildren()) + { + EMsgManager::stopAllMouseListenersBindedWith(child); + } +} + +void e2d::EMsgManager::startAllKeyboardListenersBindedWith(EScene * pParentScene) +{ + for (auto l : s_vKeyboardListeners) + { + if (l->getParentScene() == pParentScene) + { + l->start(); + } + } + for (auto child : pParentScene->getChildren()) + { + EMsgManager::startAllKeyboardListenersBindedWith(child); + } +} + +void e2d::EMsgManager::stopAllKeyboardListenersBindedWith(EScene * pParentScene) +{ + for (auto l : s_vKeyboardListeners) + { + if (l->getParentScene() == pParentScene) + { + l->stop(); + } + } + for (auto child : pParentScene->getChildren()) + { + EMsgManager::stopAllKeyboardListenersBindedWith(child); + } +} + +void e2d::EMsgManager::startAllKeyboardListenersBindedWith(ENode * pParentNode) +{ + for (auto l : s_vKeyboardListeners) + { + if (l->getParentNode() == pParentNode) + { + l->start(); + } + } + for (auto child : pParentNode->getChildren()) + { + EMsgManager::startAllKeyboardListenersBindedWith(child); + } +} + +void e2d::EMsgManager::stopAllKeyboardListenersBindedWith(ENode * pParentNode) +{ + for (auto l : s_vKeyboardListeners) + { + if (l->getParentNode() == pParentNode) + { + l->stop(); + } + } + for (auto child : pParentNode->getChildren()) + { + EMsgManager::stopAllKeyboardListenersBindedWith(child); + } +} + +void e2d::EMsgManager::clearAllMouseListenersBindedWith(EScene * pParentScene) +{ + for (size_t i = 0; i < s_vMouseListeners.size();) + { + auto t = s_vMouseListeners[i]; + if (t->getParentScene() == pParentScene) + { + SafeRelease(&t); + s_vMouseListeners.erase(s_vMouseListeners.begin() + i); + } + else + { + i++; + } + } + for (auto child : pParentScene->getChildren()) + { + EMsgManager::clearAllMouseListenersBindedWith(child); + } +} + +void e2d::EMsgManager::clearAllKeyboardListenersBindedWith(EScene * pParentScene) +{ + for (size_t i = 0; i < s_vKeyboardListeners.size();) + { + auto t = s_vKeyboardListeners[i]; + if (t->getParentScene() == pParentScene) + { + SafeRelease(&t); + s_vKeyboardListeners.erase(s_vKeyboardListeners.begin() + i); + } + else + { + i++; + } + } + for (auto child : pParentScene->getChildren()) + { + EMsgManager::clearAllKeyboardListenersBindedWith(child); + } +} + +void e2d::EMsgManager::clearAllMouseListenersBindedWith(ENode * pParentNode) +{ + for (size_t i = 0; i < s_vMouseListeners.size();) + { + auto t = s_vMouseListeners[i]; + if (t->getParentNode() == pParentNode) + { + SafeRelease(&t); + s_vMouseListeners.erase(s_vMouseListeners.begin() + i); + } + else + { + i++; + } + } + for (auto child : pParentNode->getChildren()) + { + EMsgManager::clearAllMouseListenersBindedWith(child); + } +} + +void e2d::EMsgManager::clearAllKeyboardListenersBindedWith(ENode * pParentNode) +{ + for (size_t i = 0; i < s_vKeyboardListeners.size();) + { + auto t = s_vKeyboardListeners[i]; + if (t->getParentNode() == pParentNode) + { + SafeRelease(&t); + s_vKeyboardListeners.erase(s_vKeyboardListeners.begin() + i); + } + else + { + i++; + } + } + for (auto child : pParentNode->getChildren()) + { + EMsgManager::clearAllKeyboardListenersBindedWith(child); + } +} + +void e2d::EMsgManager::_clearManager() +{ + s_vMouseListeners.clear(); + s_vKeyboardListeners.clear(); +} + +void e2d::EMsgManager::startAllMouseListeners() +{ + EMsgManager::startAllMouseListenersBindedWith(EApp::getCurrentScene()); +} + +void e2d::EMsgManager::stopAllMouseListeners() +{ + EMsgManager::stopAllMouseListenersBindedWith(EApp::getCurrentScene()); +} + +void e2d::EMsgManager::clearAllMouseListeners() +{ + EMsgManager::clearAllMouseListenersBindedWith(EApp::getCurrentScene()); +} + +void e2d::EMsgManager::startAllKeyboardListeners() +{ + EMsgManager::startAllKeyboardListenersBindedWith(EApp::getCurrentScene()); +} + +void e2d::EMsgManager::stopAllKeyboardListeners() +{ + EMsgManager::stopAllKeyboardListenersBindedWith(EApp::getCurrentScene()); +} + +void e2d::EMsgManager::clearAllKeyboardListeners() +{ + EMsgManager::clearAllKeyboardListenersBindedWith(EApp::getCurrentScene()); } \ No newline at end of file diff --git a/Easy2D/Tool/EObjectManager.cpp b/Easy2D/Manager/EObjectManager.cpp similarity index 96% rename from Easy2D/Tool/EObjectManager.cpp rename to Easy2D/Manager/EObjectManager.cpp index 6f113d0f..9414e5f7 100644 --- a/Easy2D/Tool/EObjectManager.cpp +++ b/Easy2D/Manager/EObjectManager.cpp @@ -47,9 +47,9 @@ void e2d::EObjectManager::add(e2d::EObject * nptr) void e2d::EObjectManager::clearAllObjects() { - for (auto o : s_vPool) + for (const auto &obj : s_vPool) { - delete o; + delete obj; } s_vPool.clear(); } diff --git a/Easy2D/Tool/ETimerManager.cpp b/Easy2D/Manager/ETimerManager.cpp similarity index 78% rename from Easy2D/Tool/ETimerManager.cpp rename to Easy2D/Manager/ETimerManager.cpp index 2c5ab30f..109e8086 100644 --- a/Easy2D/Tool/ETimerManager.cpp +++ b/Easy2D/Manager/ETimerManager.cpp @@ -181,55 +181,16 @@ void e2d::ETimerManager::clearAllTimersBindedWith(ENode * pParentNode) } } -void e2d::ETimerManager::_notifyAllTimersBindedWith(EScene * pParentScene) +void e2d::ETimerManager::_clearManager() { - for (auto t : s_vTimers) - { - if (t->getParentScene() == pParentScene) - t->_notify(); - } - for (auto child : pParentScene->getChildren()) - { - _notifyAllTimersBindedWith(child); - } + s_vTimers.clear(); } -void e2d::ETimerManager::_waitAllTimersBindedWith(EScene * pParentScene) +void e2d::ETimerManager::_resetAllTimers() { - for (auto t : s_vTimers) + for (const auto & t : s_vTimers) { - if (t->getParentScene() == pParentScene) - t->_wait(); - } - for (auto child : pParentScene->getChildren()) - { - _waitAllTimersBindedWith(child); - } -} - -void e2d::ETimerManager::_notifyAllTimersBindedWith(ENode * pParentNode) -{ - for (auto t : s_vTimers) - { - if (t->getParentNode() == pParentNode) - t->_notify(); - } - for (auto child : pParentNode->getChildren()) - { - _notifyAllTimersBindedWith(child); - } -} - -void e2d::ETimerManager::_waitAllTimersBindedWith(ENode * pParentNode) -{ - for (auto t : s_vTimers) - { - if (t->getParentNode() == pParentNode) - t->_notify(); - } - for (auto child : pParentNode->getChildren()) - { - _waitAllTimersBindedWith(child); + t->m_tLast = GetNow(); } } @@ -250,14 +211,21 @@ void e2d::ETimerManager::clearAllTimers() void e2d::ETimerManager::TimerProc() { + if (EApp::isPaused()) + return; + for (auto t : s_vTimers) { if (t->isRunning()) { - if (GetInterval(t->m_tLast) >= t->m_nInterval) + if (t->getParentScene() == EApp::getCurrentScene() || + (t->getParentNode() && t->getParentNode()->getParentScene() == EApp::getCurrentScene())) { - t->_callOn(); - t->m_tLast = GetNow(); + if (GetInterval(t->m_tLast) >= t->m_nInterval) + { + t->_callOn(); + t->m_tLast = GetNow(); + } } } } diff --git a/Easy2D/Node/ENode.cpp b/Easy2D/Node/ENode.cpp index 1b68da43..50513be3 100644 --- a/Easy2D/Node/ENode.cpp +++ b/Easy2D/Node/ENode.cpp @@ -106,11 +106,6 @@ void e2d::ENode::_onEnter() if (!this->m_bDisplayedInScene && this->isVisiable()) { this->m_bDisplayedInScene = true; - - ETimerManager::_notifyAllTimersBindedWith(this); - EMsgManager::_notifyAllMouseListenersBindedWith(this); - EMsgManager::_notifyAllKeyboardListenersBindedWith(this); - EActionManager::_notifyAllActionsBindedWith(this); this->onEnter(); for (const auto &child : m_vChildren) @@ -125,11 +120,6 @@ void e2d::ENode::_onExit() if (this->m_bDisplayedInScene) { this->m_bDisplayedInScene = false; - - ETimerManager::_waitAllTimersBindedWith(this); - EMsgManager::_waitAllMouseListenersBindedWith(this); - EMsgManager::_waitAllKeyboardListenersBindedWith(this); - EActionManager::_waitAllActionsBindedWith(this); this->onExit(); for (const auto &child : m_vChildren) @@ -462,18 +452,6 @@ void e2d::ENode::setAnchor(float anchorX, float anchorY) m_bTransformChildrenNeeded = true; } -void e2d::ENode::setParent(ENode * parent) -{ - if (m_pParent) - { - m_pParent->addChild(this); - } - else - { - removeFromParent(); - } -} - void e2d::ENode::addChild(ENode * child, int order /* = 0 */) { WARN_IF(child == nullptr, "ENode::addChild NULL pointer exception."); @@ -639,7 +617,12 @@ void e2d::ENode::clearAllChildren(bool release /* = true */) void e2d::ENode::runAction(EAction * action) { - EActionManager::bindAction(action, this); + ASSERT( + (!action->getTarget()), + "The action is already running, it cannot running again!" + ); + action->setTarget(this); + EActionManager::addAction(action); } void e2d::ENode::resumeAction(EAction * action) diff --git a/Easy2D/Node/ESprite.cpp b/Easy2D/Node/ESprite.cpp index ad9747af..aa877370 100644 --- a/Easy2D/Node/ESprite.cpp +++ b/Easy2D/Node/ESprite.cpp @@ -3,8 +3,8 @@ e2d::ESprite::ESprite() - : m_fSourcePosX(0) - , m_fSourcePosY(0) + : m_fSourceClipX(0) + , m_fSourceClipY(0) , m_pTexture(nullptr) { } @@ -44,7 +44,7 @@ void e2d::ESprite::setTexture(ETexture * texture) m_pTexture = texture; m_pTexture->retain(); - m_fSourcePosX = m_fSourcePosY = 0; + m_fSourceClipX = m_fSourceClipY = 0; ENode::_setWidth(m_pTexture->getSourceWidth()); ENode::_setHeight(m_pTexture->getSourceHeight()); } @@ -55,12 +55,18 @@ void e2d::ESprite::setTexture(ETexture * texture, float x, float y, float width, clipTexture(x, y, width, height); } +void e2d::ESprite::loadFromSpriteFrame(ESpriteFrame * frame) +{ + setTexture(frame->m_pTexture); + clipTexture(frame->m_fSourceClipX, frame->m_fSourceClipY, frame->m_fSourceClipWidth, frame->m_fSourceClipHeight); +} + void e2d::ESprite::clipTexture(float x, float y, float width, float height) { - m_fSourcePosX = max(x, 0); - m_fSourcePosY = max(y, 0); - ENode::_setWidth(min(max(width, 0), m_pTexture->getSourceWidth() - m_fSourcePosX)); - ENode::_setHeight(min(max(height, 0), m_pTexture->getSourceHeight() - m_fSourcePosX)); + m_fSourceClipX = min(max(x, 0), m_pTexture->getSourceWidth()); + m_fSourceClipY = min(max(y, 0), m_pTexture->getSourceHeight()); + ENode::_setWidth(min(max(width, 0), m_pTexture->getSourceWidth() - m_fSourceClipX)); + ENode::_setHeight(min(max(height, 0), m_pTexture->getSourceHeight() - m_fSourceClipX)); } void e2d::ESprite::_onRender() @@ -73,7 +79,12 @@ void e2d::ESprite::_onRender() D2D1::RectF(0, 0, getRealWidth(), getRealHeight()), m_fDisplayOpacity, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, - D2D1::RectF(m_fSourcePosX, m_fSourcePosY, getRealWidth(), getRealHeight()) + D2D1::RectF( + m_fSourceClipX, + m_fSourceClipY, + m_fSourceClipX + getRealWidth(), + m_fSourceClipY + getRealHeight() + ) ); } } diff --git a/Easy2D/Node/ESpriteFrame.cpp b/Easy2D/Node/ESpriteFrame.cpp index 6de60dab..77bb45ee 100644 --- a/Easy2D/Node/ESpriteFrame.cpp +++ b/Easy2D/Node/ESpriteFrame.cpp @@ -1 +1,85 @@ -#include "..\enodes.h" \ No newline at end of file +#include "..\enodes.h" + +e2d::ESpriteFrame::ESpriteFrame() + : m_fSourceClipX(0) + , m_fSourceClipY(0) + , m_fSourceClipWidth(0) + , m_fSourceClipHeight(0) + , m_pTexture(nullptr) +{ +} + +e2d::ESpriteFrame::ESpriteFrame(ETexture * texture) + : ESpriteFrame() +{ + _setTexture(texture); +} + +e2d::ESpriteFrame::ESpriteFrame(const EString & imageFileName) + : ESpriteFrame() +{ + _setTexture(new ETexture(imageFileName)); +} + +e2d::ESpriteFrame::ESpriteFrame(const EString & resourceName, const EString & resourceType) + : ESpriteFrame() +{ + _setTexture(new ETexture(resourceName, resourceType)); +} + +e2d::ESpriteFrame::ESpriteFrame(ETexture * texture, float x, float y, float width, float height) + : ESpriteFrame() +{ + _setTexture(texture); + _clipTexture(x, y, width, height); +} + +e2d::ESpriteFrame::ESpriteFrame(const EString & imageFileName, float x, float y, float width, float height) + : ESpriteFrame() +{ + _setTexture(new ETexture(imageFileName)); + _clipTexture(x, y, width, height); +} + +e2d::ESpriteFrame::ESpriteFrame(const EString & resourceName, const EString & resourceType, float x, float y, float width, float height) + : ESpriteFrame() +{ + _setTexture(new ETexture(resourceName, resourceType)); + _clipTexture(x, y, width, height); +} + +e2d::ESpriteFrame::~ESpriteFrame() +{ + if (m_pTexture) + { + m_pTexture->release(); + } +} + +void e2d::ESpriteFrame::_setTexture(ETexture * texture) +{ + if (texture) + { + if (m_pTexture) + { + m_pTexture->release(); + } + m_pTexture = texture; + m_pTexture->retain(); + m_fSourceClipX = 0; + m_fSourceClipY = 0; + m_fSourceClipWidth = texture->getSourceWidth(); + m_fSourceClipHeight = texture->getSourceHeight(); + } +} + +void e2d::ESpriteFrame::_clipTexture(float x, float y, float width, float height) +{ + if (m_pTexture) + { + m_fSourceClipX = min(max(x, 0), m_pTexture->getSourceWidth()); + m_fSourceClipY = min(max(y, 0), m_pTexture->getSourceHeight()); + m_fSourceClipWidth = min(max(width, 0), m_pTexture->getSourceWidth() - m_fSourceClipX); + m_fSourceClipHeight = min(max(height, 0), m_pTexture->getSourceHeight() - m_fSourceClipY); + } +} diff --git a/Easy2D/Node/ETexture.cpp b/Easy2D/Node/ETexture.cpp index 5f91721a..b4836bfb 100644 --- a/Easy2D/Node/ETexture.cpp +++ b/Easy2D/Node/ETexture.cpp @@ -42,7 +42,6 @@ e2d::ETexture::ETexture(const EString & resourceName, const EString & resourceTy e2d::ETexture::~ETexture() { - SafeReleaseInterface(&m_pBitmap); } void e2d::ETexture::loadFromFile(const EString & fileName) @@ -52,8 +51,6 @@ void e2d::ETexture::loadFromFile(const EString & fileName) if (fileName.empty()) return; - SafeReleaseInterface(&m_pBitmap); - if (!e2d::ETexture::preload(fileName)) { WARN_IF(true, "Load ETexture from file failed!"); @@ -73,8 +70,6 @@ void e2d::ETexture::loadFromResource(const EString & resourceName, const EString if (resourceName.empty() || resourceType.empty()) return; - SafeReleaseInterface(&m_pBitmap); - if (!e2d::ETexture::preload(resourceName, resourceType)) { WARN_IF(true, "Load ETexture from resource failed!"); diff --git a/Easy2D/Tool/EMusicUtils.cpp b/Easy2D/Tool/EMusicUtils.cpp new file mode 100644 index 00000000..11746935 --- /dev/null +++ b/Easy2D/Tool/EMusicUtils.cpp @@ -0,0 +1,6 @@ +#include "..\etools.h" + + +void e2d::EMusicUtils::play(LPCTSTR musicFileName, bool loop) +{ +} \ No newline at end of file diff --git a/Easy2D/Transition/ETransitionFade.cpp b/Easy2D/Transition/ETransitionFade.cpp new file mode 100644 index 00000000..ef210534 --- /dev/null +++ b/Easy2D/Transition/ETransitionFade.cpp @@ -0,0 +1,36 @@ +#include "..\etransitions.h" +#include "..\eactions.h" + +e2d::ETransitionFade::ETransitionFade(float fadeOutDuration, float fadeInDuration) + : m_fFadeOutDuration(fadeOutDuration) + , m_fFadeInDuration(fadeInDuration) +{ +} + +void e2d::ETransitionFade::_setTarget(EScene * prev, EScene * next, bool & enterNextScene, bool & transitional) +{ + // 第一个场景淡出 + auto action1 = new EActionFadeOut(m_fFadeOutDuration); + if (prev) + { + action1->setTarget(prev->getRoot()); + } + + // 切换至第二场景,并将第二场景透明度设为 0 + auto action2 = new EActionCallback([&, next] { + enterNextScene = true; + next->getRoot()->setOpacity(0); + }); + + // 第二个场景淡入 + auto action3 = new EActionFadeIn(m_fFadeInDuration); + action3->setTarget(next->getRoot()); + + // 标志动画结束 + auto action4 = new EActionCallback([&] { + transitional = false; + }); + + // 添加顺序动作 + EActionManager::addAction(new EActionSequence(4, action1, action2, action3, action4)); +} \ No newline at end of file diff --git a/Easy2D/Win/winbase.cpp b/Easy2D/Win/winbase.cpp index 9a36412e..c54a2ce8 100644 --- a/Easy2D/Win/winbase.cpp +++ b/Easy2D/Win/winbase.cpp @@ -49,7 +49,7 @@ ID2D1HwndRenderTarget * &GetRenderTarget() // Create a Direct2D render target. HRESULT hr; - hr = s_pDirect2dFactory->CreateHwndRenderTarget( + hr = GetFactory()->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(s_HWnd, size), &s_pRenderTarget @@ -79,7 +79,12 @@ ID2D1SolidColorBrush * &GetSolidColorBrush() { if (!s_pSolidBrush) { - s_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &s_pSolidBrush); + HRESULT hr; + hr = GetRenderTarget()->CreateSolidColorBrush( + D2D1::ColorF(D2D1::ColorF::White), + &s_pSolidBrush + ); + ASSERT(SUCCEEDED(hr), "Create Solid Color Brush Failed!"); } return s_pSolidBrush; } diff --git a/Easy2D/eactions.h b/Easy2D/eactions.h index 0538722a..a8d96ff2 100644 --- a/Easy2D/eactions.h +++ b/Easy2D/eactions.h @@ -9,6 +9,7 @@ class EActionTwo; class EActionLoop; class EActionSequence; class EActionTwoAtSameTime; +class ETransitionFade; class EAction : public EObject @@ -45,13 +46,18 @@ public: // 获取一个新的逆向动作 virtual EAction * reverse() const; + // 获取执行该动作的目标 + virtual ENode * getTarget(); + // 设置动作每一帧的时间间隔 virtual void setInterval( LONGLONG milliSeconds ); - // 获取执行该动作的目标 - virtual ENode * getTarget(); + // 设置动作执行目标 + virtual void setTarget( + ENode * node + ); protected: // 初始化动作 @@ -66,30 +72,23 @@ protected: // 重置动作 virtual void _reset(); - // 进入等待状态 - virtual void _wait(); - - // 唤醒 - virtual void _notify(); - protected: bool m_bRunning; - bool m_bWaiting; bool m_bEnding; bool m_bInit; ENode * m_pTarget; EScene * m_pParentScene; LONGLONG m_nAnimationInterval; - std::chrono::steady_clock::time_point m_nLast; + std::chrono::steady_clock::time_point m_tLast; }; -class EAnimation : +class EActionGradual : public EAction { public: // 创建时长动画 - EAnimation( + EActionGradual( float duration ); @@ -113,7 +112,7 @@ protected: class EActionMoveBy : - public EAnimation + public EActionGradual { public: // 创建相对位移动画 @@ -170,7 +169,7 @@ protected: class EActionScaleBy : - public EAnimation + public EActionGradual { public: // 创建相对缩放动画 @@ -232,7 +231,7 @@ protected: class EActionOpacityBy : - public EAnimation + public EActionGradual { public: // 创建透明度相对渐变动画 @@ -311,7 +310,7 @@ public: class EActionRotateBy : - public EAnimation + public EActionGradual { public: // 创建相对旋转动画 @@ -537,19 +536,19 @@ protected: }; -class EActionFrames : +class EAnimation : public EAction { public: // 创建帧动画 - EActionFrames(); + EAnimation(); // 创建特定帧间隔的帧动画 - EActionFrames( + EAnimation( LONGLONG frameDelay /* 帧间隔(毫秒) */ ); - virtual ~EActionFrames(); + virtual ~EAnimation(); // 添加帧 void addFrame( @@ -557,10 +556,10 @@ public: ); // 获取该动画的拷贝对象 - virtual EActionFrames * clone() const override; + virtual EAnimation * clone() const override; // 获取该动画的逆动画 - virtual EActionFrames * reverse() const override; + virtual EAnimation * reverse() const override; protected: // 初始化动作 diff --git a/Easy2D/easy2d.h b/Easy2D/easy2d.h index 6c8486ae..76c3a9de 100644 --- a/Easy2D/easy2d.h +++ b/Easy2D/easy2d.h @@ -23,6 +23,7 @@ #include "emsg.h" #include "etools.h" #include "eactions.h" +#include "etransitions.h" #if defined(DEBUG) || defined(_DEBUG) diff --git a/Easy2D/ebase.h b/Easy2D/ebase.h index 11ad3fb9..95e544dd 100644 --- a/Easy2D/ebase.h +++ b/Easy2D/ebase.h @@ -13,6 +13,7 @@ class ENode; class EObjectManager; class EMouseListener; class EKeyboardListener; +class ETransition; class EApp { @@ -21,6 +22,13 @@ public: virtual ~EApp(); + enum WINDOW_STYLE + { + NO_CLOSE = 1, /* 禁用关闭按钮 */ + NO_MINI_SIZE = 2, /* 禁用最小化按钮 */ + TOP_MOST = 4 /* 窗口置顶 */ + }; + // 初始化游戏界面 bool init( const EString &title, /* 窗口标题 */ @@ -41,13 +49,8 @@ public: // 启动程序 void run(); - // 预设画面帧数 - void setFPS( - UINT32 fps - ); - // 重写这个函数,它将在窗口激活时执行 - virtual void onActivate(); + virtual bool onActivate(); // 重写这个函数,它将在窗口非激活时执行 virtual bool onInactive(); @@ -55,27 +58,58 @@ public: // 重写这个函数,它将在关闭窗口时执行 virtual bool onCloseWindow(); - // 释放所有内存资源 - void free(); - // 获取程序实例 static EApp * get(); - // 显示或隐藏控制台(默认隐藏) + // 暂停游戏 + static void pause(); + + // 继续游戏 + static void resume(); + + // 获取游戏是否暂停 + static bool isPaused(); + + // 切换场景 + static void enterScene( + EScene * scene, /* 下一个场景的指针 */ + bool saveCurrentScene = true /* 是否保存当前场景 */ + ); + + // 切换场景 + static void enterScene( + EScene * scene, /* 下一个场景的指针 */ + ETransition * transition, /* 场景切换动画 */ + bool saveCurrentScene = true /* 是否保存当前场景 */ + ); + + // 返回上一场景 + static void backScene(); + + // 返回上一场景 + static void backScene( + ETransition * transition /* 场景切换动画 */ + ); + + // 清空保存的所有场景 + static void clearScene(); + + // 隐藏窗口 + static void hideWindow(); + + // 显示窗口 + static void showWindow(); + + // 是否打开控制台 static void showConsole( bool show ); - // 修改窗口大小 - static void setWindowSize( - UINT32 width, - UINT32 height - ); + // 终止程序 + static void quit(); - // 设置窗口标题 - static void setWindowTitle( - const EString &title - ); + // 终止程序 + static void end(); // 获取窗口标题 static EString getTitle(); @@ -86,18 +120,6 @@ public: // 获取窗口高度 static UINT32 getHeight(); - // 切换场景 - static void enterScene( - EScene * scene, /* 下一个场景的指针 */ - bool saveCurrentScene = true /* 是否保存当前场景 */ - ); - - // 返回上一场景 - static void backScene(); - - // 清空保存的所有场景 - static void clearScene(); - // 获取当前场景 static EScene * getCurrentScene(); @@ -110,6 +132,17 @@ public: // 获取 AppName static EString getAppName(); + // 修改窗口大小 + static void setWindowSize( + UINT32 width, + UINT32 height + ); + + // 设置窗口标题 + static void setWindowTitle( + const EString & title + ); + // 设置 AppName static void setAppName( const EString &appname @@ -125,17 +158,10 @@ public: bool value ); - // 隐藏窗口 - static void hideWindow(); - - // 显示窗口 - static void showWindow(); - - // 终止程序 - static void quit(); - - // 终止程序 - static void end(); + // 预设画面帧数 + static void setFPS( + UINT32 fps + ); protected: // 创建设备无关资源 @@ -154,7 +180,7 @@ protected: void _onControl(); // 渲染游戏画面 - bool _onRender(); + void _onRender(); // 进入下一场景 void _enterNextScene(); @@ -165,6 +191,9 @@ protected: UINT32 height ); + // 释放所有内存资源 + void _free(); + // 窗口程序 static LRESULT CALLBACK WndProc( HWND hWnd, @@ -174,19 +203,48 @@ protected: ); protected: - bool m_bRunning; + bool m_bEnd; bool m_bPaused; + bool m_bManualPaused; + bool m_bTransitional; + bool m_bEnterNextScene; + bool m_bTopMost; EString m_sTitle; EString m_sAppName; EColor m_ClearColor; LONGLONG nAnimationInterval; - EScene * m_pCurrentScene; EScene * m_pNextScene; }; -class EScene +class EObject +{ + friend EObjectManager; + +public: + EObject(); + + virtual ~EObject(); + + // 引用计数加一 + void retain(); + + // 引用计数减一 + void release(); + + // 让引擎自动释放这个对象 + void autoRelease(); + +private: + int m_nRefCount; + bool m_bManaged; + bool m_bAutoRelease; +}; + + +class EScene : + public EObject { friend EApp; @@ -202,7 +260,7 @@ public: virtual void onExit(); // 重写这个函数,它将在窗口激活时执行 - virtual void onActivate(); + virtual bool onActivate(); // 重写这个函数,它将在窗口非激活时执行 virtual bool onInactive(); @@ -239,6 +297,9 @@ public: const EString &childName ); + // 获取根节点 + ENode * getRoot() const; + // 清空所有子成员 void clearAllChildren(); @@ -252,41 +313,10 @@ protected: // 渲染场景画面 void _onRender(); - // 进入场景时需调用该函数 - virtual void _onEnter(); - - // 退出场景时需调用该函数 - virtual void _onExit(); - protected: bool m_bSortNeeded; bool m_bWillSave; ENode * m_pRoot; }; - -class EObject -{ - friend EObjectManager; - -public: - EObject(); - - virtual ~EObject(); - - // 引用计数加一 - void retain(); - - // 引用计数减一 - void release(); - - // 让引擎自动释放这个对象 - void autoRelease(); - -private: - int m_nRefCount; - bool m_bManaged; - bool m_bAutoRelease; -}; - } \ No newline at end of file diff --git a/Easy2D/emsg.h b/Easy2D/emsg.h index 688ae077..edd47dff 100644 --- a/Easy2D/emsg.h +++ b/Easy2D/emsg.h @@ -153,9 +153,6 @@ public: // 获取监听器状态 bool isRunning() const; - // 获取监听器挂起状态 - bool isWaiting() const; - // 启动监听 void start(); @@ -187,19 +184,12 @@ public: ) = 0; protected: - // 进入等待状态 - void _wait(); - - // 唤醒 - void _notify(); - // 执行监听器回调函数 virtual void _callOn() = 0; protected: EString m_sName; bool m_bRunning; - bool m_bWaiting; EScene * m_pParentScene; ENode * m_pParentNode; }; @@ -605,46 +595,8 @@ public: static void clearAllKeyboardListeners(); private: - // 挂起绑定在场景上的所有鼠标消息监听器 - static void _waitAllMouseListenersBindedWith( - EScene * pParentScene - ); - - // 重启绑定在场景上的所有鼠标消息监听器 - static void _notifyAllMouseListenersBindedWith( - EScene * pParentScene - ); - - // 挂起绑定在节点上的所有鼠标消息监听器 - static void _waitAllMouseListenersBindedWith( - ENode * pParentNode - ); - - // 重启绑定在节点上的所有鼠标消息监听器 - static void _notifyAllMouseListenersBindedWith( - ENode * pParentNode - ); - - - // 挂起绑定在场景及其子节点上的所有按键监听器 - static void _waitAllKeyboardListenersBindedWith( - EScene * pParentScene - ); - - // 重启绑定在场景及其子节点上的所有按键监听器 - static void _notifyAllKeyboardListenersBindedWith( - EScene * pParentScene - ); - - // 挂起绑定在节点上的所有按键监听器 - static void _waitAllKeyboardListenersBindedWith( - ENode * pParentNode - ); - - // 重启绑定在节点上的所有按键监听器 - static void _notifyAllKeyboardListenersBindedWith( - ENode * pParentNode - ); + // 清除所有监听器 + static void _clearManager(); // 鼠标消息程序 static void MouseProc( diff --git a/Easy2D/enodes.h b/Easy2D/enodes.h index 9e517fb0..2b82173d 100644 --- a/Easy2D/enodes.h +++ b/Easy2D/enodes.h @@ -222,11 +222,6 @@ public: float anchorY ); - // 设置父节点 - virtual void setParent( - ENode* parent - ); - // 添加子节点 virtual void addChild( ENode * child, @@ -422,6 +417,84 @@ protected: }; +class ESpriteFrame : + public EObject +{ + friend ESprite; + +public: + // 创建空的精灵帧 + ESpriteFrame(); + + // 创建空的精灵帧 + ESpriteFrame( + ETexture * texture + ); + + // 创建空的精灵帧 + ESpriteFrame( + const EString & imageFileName + ); + + // 创建空的精灵帧 + ESpriteFrame( + const EString & resourceName, + const EString & resourceType + ); + + // 创建空的精灵帧 + ESpriteFrame( + ETexture * texture, + float x, + float y, + float width, + float height + ); + + // 创建空的精灵帧 + ESpriteFrame( + const EString & imageFileName, + float x, + float y, + float width, + float height + ); + + // 创建空的精灵帧 + ESpriteFrame( + const EString & resourceName, + const EString & resourceType, + float x, + float y, + float width, + float height + ); + + virtual ~ESpriteFrame(); + +protected: + // 获取纹理 + void _setTexture( + ETexture * texture + ); + + // 裁剪纹理 + void _clipTexture( + float x, + float y, + float width, + float height + ); + +protected: + float m_fSourceClipX; + float m_fSourceClipY; + float m_fSourceClipWidth; + float m_fSourceClipHeight; + ETexture * m_pTexture; +}; + + class ESprite : public ENode { @@ -475,6 +548,11 @@ public: float height ); + // 从 ESpriteFrame 加载资源 + void loadFromSpriteFrame( + ESpriteFrame * frame + ); + // 裁剪纹理 void clipTexture( float x, @@ -488,20 +566,12 @@ protected: virtual void _onRender() override; protected: - float m_fSourcePosX; - float m_fSourcePosY; + float m_fSourceClipX; + float m_fSourceClipY; ETexture * m_pTexture; }; -class ESpriteFrame : - public EObject -{ -protected: - ETexture * texture; -}; - - class EFont : public EObject { diff --git a/Easy2D/etools.h b/Easy2D/etools.h index edb18eaf..51eea928 100644 --- a/Easy2D/etools.h +++ b/Easy2D/etools.h @@ -59,9 +59,6 @@ public: // 获取定时器状态 bool isRunning() const; - // 获取定时器挂起状态 - bool isWaiting() const; - // 启动监听 void start(); @@ -98,19 +95,12 @@ public: ); protected: - // 进入等待状态 - void _wait(); - - // 唤醒 - void _notify(); - // 执行回调函数 virtual void _callOn(); protected: EString m_sName; bool m_bRunning; - bool m_bWaiting; int m_nRunTimes; EScene * m_pParentScene; ENode * m_pParentNode; @@ -195,25 +185,11 @@ public: static void clearAllTimers(); private: - // 挂起绑定在场景及其子节点上的所有定时器 - static void _waitAllTimersBindedWith( - EScene * pParentScene - ); + // 清空定时器管理器 + static void _clearManager(); - // 重启绑定在场景及其子节点上的所有定时器 - static void _notifyAllTimersBindedWith( - EScene * pParentScene - ); - - // 挂起绑定在节点上的所有定时器 - static void _waitAllTimersBindedWith( - ENode * pParentNode - ); - - // 重启绑定在节点上的所有定时器 - static void _notifyAllTimersBindedWith( - ENode * pParentNode - ); + // 重置定时器状态 + static void _resetAllTimers(); // 定时器执行程序 static void TimerProc(); @@ -228,10 +204,9 @@ class EActionManager friend ENode; public: - // 绑定动作到节点 - static void bindAction( - EAction * action, - ENode * pTargetNode + // 添加动作 + static void addAction( + EAction * action ); // 启动绑定在场景子节点上的所有动作 @@ -274,31 +249,25 @@ public: static void clearAllActions(); private: - // 挂起绑定在场景子节点上的所有动作 - static void _waitAllActionsBindedWith( - EScene * pParentScene - ); + // 清空动画管理器 + static void _clearManager(); - // 重启绑定在场景子节点上的所有动作 - static void _notifyAllActionsBindedWith( - EScene * pParentScene - ); - - // 挂起绑定在节点上的所有动作 - static void _waitAllActionsBindedWith( - ENode * pTargetNode - ); - - // 重启绑定在节点上的所有动作 - static void _notifyAllActionsBindedWith( - ENode * pTargetNode - ); + // 重置所有动作状态 + static void _resetAllActions(); // 动作执行程序 static void ActionProc(); }; +class EMusicUtils +{ +public: + // 播放音效 + static void play(LPCTSTR musicFileName, bool loop = false); +}; + + class EFileUtils { public: diff --git a/Easy2D/etransitions.h b/Easy2D/etransitions.h new file mode 100644 index 00000000..5f6066cd --- /dev/null +++ b/Easy2D/etransitions.h @@ -0,0 +1,49 @@ +#pragma once +#include "ebase.h" + +namespace e2d +{ + +class ETransition : + public EObject +{ + friend EApp; +public: + ETransition() {} + +protected: + // 保存当前场景和下一场景的指针,和控制场景切换的变量 + virtual void _setTarget( + EScene * prev, + EScene * next, + bool &enterNextScene, + bool &transitional + ) = 0; +}; + + +class ETransitionFade : + public ETransition +{ +public: + // 创建淡入淡出式的场景切换动画 + ETransitionFade( + float fadeOutDuration, /* 前一场景淡出动画持续时长 */ + float fadeInDuration /* 后一场景淡入动画持续时长 */ + ); + +protected: + // 保存当前场景和下一场景的指针,和控制场景切换的变量 + virtual void _setTarget( + EScene * prev, + EScene * next, + bool &enterNextScene, + bool &transitional + ) override; + +protected: + float m_fFadeOutDuration; + float m_fFadeInDuration; +}; + +} \ No newline at end of file