From 1e11c8584e6da0b51daff3ee99edda43649aaec5 Mon Sep 17 00:00:00 2001 From: CrusherNotDrip <90648119+CrusherNotDrip@users.noreply.github.com> Date: Tue, 5 Nov 2024 22:19:08 -0500 Subject: [PATCH 1/4] Initial commit 2 --- .vscode/extensions.json | 6 ++++++ .vscode/launch.json | 21 +++++++++++++++++++++ .vscode/settings.json | 14 ++++++++++++++ .vscode/tasks.json | 13 +++++++++++++ Project.xml | 42 +++++++++++++++++++++++++++++++++++++++++ hxformat.json | 15 +++++++++++++++ src/Main.hx | 13 +++++++++++++ src/PlayState.hx | 16 ++++++++++++++++ 8 files changed, 140 insertions(+) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 Project.xml create mode 100644 hxformat.json create mode 100644 src/Main.hx create mode 100644 src/PlayState.hx diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..89e20ed --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "openfl.lime-vscode-extension", + "redhat.vscode-xml" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5e9a7a1 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Build + Debug", + "type": "lime", + "request": "launch" + }, + { + "name": "Debug", + "type": "lime", + "request": "launch", + "preLaunchTask": null + }, + { + "name": "Macro", + "type": "haxe-eval", + "request": "launch" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d0535ae --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "search.exclude": { + "export/**/*.*": true + }, + "[haxe]": { + "editor.formatOnSave": true, + "editor.formatOnSaveMode":"modifications", + "editor.formatOnPaste": false, + "editor.codeActionsOnSave": { + "source.sortImports": "explicit" + } + }, + "haxe.enableExtendedIndentation": true +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..16a7764 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,13 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "lime", + "command": "test", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/Project.xml b/Project.xml new file mode 100644 index 0000000..e882b79 --- /dev/null +++ b/Project.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hxformat.json b/hxformat.json new file mode 100644 index 0000000..66cb386 --- /dev/null +++ b/hxformat.json @@ -0,0 +1,15 @@ +{ + "lineEnds": { + "leftCurly": "both", + "rightCurly": "both", + "objectLiteralCurly": { + "leftCurly": "after" + } + }, + "sameLine": { + "ifElse": "next", + "doWhile": "next", + "tryBody": "next", + "tryCatch": "next" + } +} diff --git a/src/Main.hx b/src/Main.hx new file mode 100644 index 0000000..efa0e2d --- /dev/null +++ b/src/Main.hx @@ -0,0 +1,13 @@ +package; + +import flixel.FlxGame; +import openfl.display.Sprite; + +class Main extends Sprite +{ + public function new() + { + super(); + addChild(new FlxGame(0, 0, PlayState)); + } +} diff --git a/src/PlayState.hx b/src/PlayState.hx new file mode 100644 index 0000000..80ac510 --- /dev/null +++ b/src/PlayState.hx @@ -0,0 +1,16 @@ +package; + +import flixel.FlxState; + +class PlayState extends FlxState +{ + override public function create() + { + super.create(); + } + + override public function update(elapsed:Float) + { + super.update(elapsed); + } +} From 110ca81ce7057b29ed728fb1a3ec9b8584c3d3ad Mon Sep 17 00:00:00 2001 From: CrusherNotDrip <90648119+CrusherNotDrip@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:32:13 -0500 Subject: [PATCH 2/4] ZIndex + Icons + Paths System + Conductor (Bare minimum needed for right now) Co-authored-by: TechnikTil --- .gitignore | 13 ++ .vscode/settings.json | 3 +- Project.xml | 19 +- checkstyle.json | 139 ++++++++++++++ README.md => docs/README.md | 0 extras/appicons/icon.png | Bin 0 -> 75711 bytes extras/appicons/icon16.png | Bin 0 -> 251 bytes extras/appicons/icon32.png | Bin 0 -> 1991 bytes extras/appicons/icon64.png | Bin 0 -> 5162 bytes src/Main.hx | 38 +++- src/PlayState.hx | 16 -- src/funkin/Conductor.hx | 149 +++++++++++++++ src/funkin/import.hx | 18 ++ src/funkin/macros/ZProperty.hx | 28 +++ src/funkin/states/FunkinState.hx | 60 ++++++ src/funkin/states/ui/TitleState.hx | 14 ++ src/funkin/util/paths/Paths.hx | 40 ++++ src/funkin/util/paths/PathsCache.hx | 254 +++++++++++++++++++++++++ src/funkin/util/paths/PathsContent.hx | 90 +++++++++ src/funkin/util/paths/PathsLocation.hx | 86 +++++++++ 20 files changed, 945 insertions(+), 22 deletions(-) create mode 100644 .gitignore create mode 100644 checkstyle.json rename README.md => docs/README.md (100%) create mode 100644 extras/appicons/icon.png create mode 100644 extras/appicons/icon16.png create mode 100644 extras/appicons/icon32.png create mode 100644 extras/appicons/icon64.png delete mode 100644 src/PlayState.hx create mode 100644 src/funkin/Conductor.hx create mode 100644 src/funkin/import.hx create mode 100644 src/funkin/macros/ZProperty.hx create mode 100644 src/funkin/states/FunkinState.hx create mode 100644 src/funkin/states/ui/TitleState.hx create mode 100644 src/funkin/util/paths/Paths.hx create mode 100644 src/funkin/util/paths/PathsCache.hx create mode 100644 src/funkin/util/paths/PathsContent.hx create mode 100644 src/funkin/util/paths/PathsLocation.hx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be46446 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +.DS_STORE +RECOVER_*.fla + +.haxelib/ +.vs/ +.vscode/ + +!.vscode/extensions.json +!.vscode/launch.json +!.vscode/settings.json +!.vscode/tasks.json + +export/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index d0535ae..3279906 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,8 +4,7 @@ }, "[haxe]": { "editor.formatOnSave": true, - "editor.formatOnSaveMode":"modifications", - "editor.formatOnPaste": false, + "editor.formatOnPaste": true, "editor.codeActionsOnSave": { "source.sortImports": "explicit" } diff --git a/Project.xml b/Project.xml index e882b79..f4eb3ca 100644 --- a/Project.xml +++ b/Project.xml @@ -19,12 +19,23 @@ - + + + + + + + + + + + + @@ -36,7 +47,9 @@ - + - + + + diff --git a/checkstyle.json b/checkstyle.json new file mode 100644 index 0000000..0a52a63 --- /dev/null +++ b/checkstyle.json @@ -0,0 +1,139 @@ +{ + "defaultSeverity": "INFO", + "checks": [ + { + "props": {}, + "type": "AvoidStarImport" + }, + { + "props": { + "thresholdSimilar": 100, + "thresholdIdentical": 60 + }, + "type": "CodeSimilarity" + }, + { + "props": {}, + "type": "CommentedOutCode" + }, + { + "props": { + "allowSingleline": true, + "policy": "aligned" + }, + "type": "ConditionalCompilation" + }, + { + "props": { + "format": "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$", + "tokens": ["INLINE"] + }, + "type": "ConstantName" + }, + { + "props": {}, + "type": "DefaultComesLast" + }, + { + "props": { + "option": "empty", + "tokens": [ + "ABSTRACT_DEF", + "CATCH", + "CLASS_DEF", + "ENUM_DEF", + "FOR", + "FUNCTION", + "IF", + "INTERFACE_DEF", + "OBJECT_DECL", + "SWITCH", + "TRY", + "TYPEDEF_DEF", + "WHILE" + ] + }, + "type": "EmptyBlock" + }, + { + "props": { + "enforceEmptyPackage": true + }, + "type": "EmptyPackage" + }, + { + "props": { + "excludeNames": ["new", "toString"], + "fieldType": "BOTH", + "ignoreOverride": true, + "modifier": "PUBLIC", + "requireParams": true, + "requireReturn": true, + "tokens": [ + "ABSTRACT_DEF", + "CLASS_DEF", + "ENUM_DEF", + "INTERFACE_DEF" + ] + }, + "type": "FieldDocComment" + }, + { + "props": { + "modifiers": [ + "OVERRIDE", + "PUBLIC_PRIVATE", + "STATIC", + "EXTERN", + "MACRO", + "INLINE", + "DYNAMIC", + "FINAL" + ] + }, + "type": "ModifierOrder" + }, + { + "props": {}, + "type": "SimplifyBooleanExpression" + }, + { + "props": {}, + "type": "SimplifyBooleanReturn" + }, + { + "props": { + "spaceIfCondition": "should", + "spaceAroundBinop": true, + "spaceForLoop": "should", + "ignoreRangeOperator": true, + "spaceWhileLoop": "should", + "spaceCatch": "should", + "spaceSwitchCase": "should", + "noSpaceAroundUnop": true + }, + "type": "Spacing" + }, + { + "props": {}, + "type": "TrailingWhitespace" + }, + { + "props": {}, + "type": "UnusedLocalVar" + }, + { + "props": { + "typeHintPolicy": "enforce_all" + }, + "type": "VarTypeHint" + }, + { + "props": { + "allowTrailingComma": false, + "tokens": [",", ";"] + }, + "type": "WhitespaceAfter" + } + ] +} diff --git a/README.md b/docs/README.md similarity index 100% rename from README.md rename to docs/README.md diff --git a/extras/appicons/icon.png b/extras/appicons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5778aa32c6fc0a9a7701eee36eb5d41d75202e62 GIT binary patch literal 75711 zcmc$lV{|0n*S5onZQIslV%s(+P9`=dc4lH*9Zigh?TKyMcAonEzrUZ~TB}x9_v%&M zRcF`P_rCUhB9#@Tkl^v*!N9DZJ>?n zpq#%Yi({jLSwt?)5&4%3=Q>plE~rX(HQkJP67rJSj5H*R`!MVC75x8keJ9e`Y`-P= zuO82u4vF9HkNlJ_idA*_AB}W!(uLX{?`;c5?}qlCX^o()rzAyf?38s1U(GZRCwAY2P&H zm^=09n0;I4*NtRCOVDoh^z41SY%We^t*;AjW1SMW_V3a|#_vXzSyA1mvoH{DjgV#0am%=bc}l2YPxXK>-f zl=6n*QXlm;Dcx2wsrC3=0ZsqSKWgHc7L!Qx#8=+cim9@Yo3*2@w*aAC-` zvKNoZEr_ zG^OIoV9s@KN@4 zQP^M_xekqqrz;IhQ3b_T;L6D~(6_&I^d&w<6{RLy3!uBRN#KxU1b&EM{dH?2C#0YX8g2i!S%4sci@How0}~R`QLgh*a{OvWRbZXpd6;X5xE5 zH15k5QQfLZdAO4aITuO`1Qc=bt)`3}thnf`3jEL!UsH6aFr^?*q4+Sq{LsmS?_-Vm zoRD!zm@6u)O0j`yRCc;Suo{@$BIP|LC0EBeR>r|`I@_XD&3fbh#^Z{HQyX0$)B?)W z;7h``wLN19Q?w6CDDq=&>Fm8-TRY@w$G%2paU$XP7Aq4|NQ^-X8)TdrR&g1d?^3JX zmwn)@A~zX6G*j3U&$+rO&#^C?!Hjk6SeA9euk^HNZ;U1P6k(ax$CcH~=ClY*F{l9u zVJ6ir>c>jAVy`nD2OFHLLQ}}9QZG^N49S*WqBL)jZoYju?Y$Uly_kx|q|_RyP$Ivs z3qd(C`vmqwK4s7Ag~u1&j(qY4EH>5!bBp%Hb&PUH7J5tF@EfM!D2{lEpus)(Akw3o zhjNWSe}+Vneb%d!4USD*DAz0J12*LvGs~(pZTMOuu{CQWxIJSK(u9d;8DWF+qI>6c zT_z8;Crnsg%5;@H@WrfKtEIJWRPiV46uH#0KN?zs7SsB?}qK=PJ5`@EV_r>Be;J$_9$V-J*b2#NsF zDiqNg!yq_gwdFxz7a5?|P8B_dxRR z)jjHVaZzTVQd>^Ejx$gG$v0MFMh3QrR@1elF+-b5q=>vQ*J&Y*M(E_zR5~SC|KCuH zV?mM-4uLq2&Q6Ywj%(%-@76z_g)Q}ad~9@taV<_D+2pI-D$bHDl@XI(ggrqGSIXY4 zFOz!Iv?)-FiwV!xF~UO?{@;L&{=ma65XEzFTK`^^Vn}HGAW9Lh+|#;sl1RnM*VyWr zymuoDX*1lrhv6GGd=)XVq0RNCfnb}PVTQ6k6E35dBQ&fpl%X%q{?^vkQ(I@nREvi1 z5=Y$5&k5laxcB57R*m&z!3=rzGWDzL>%ivb=5|I+V@z@(!I+~vPc|tmG(ZyZzvO-_Hxi>)ERPNMwPRdwP>7d+E9R~VE3KLVPIhR8ad>t z@O?^NzwBZtxoKdi?;Tw1??YE5w^MCsm zN5}(FF(0K_r91M$r;di*A2%9Iwd+AS(Z#G1*MFB;V+JmR5E#OPgC^jK6qHKf! z@$ptmHDtUV7cq|;J}5?h_gDwx>A@Nmn(>b4rcvzb#l^+n9Jj#W5fJFqs6Gfp)~IX7 zE$ZJG({-bVe_@l!plf?j-hYX#&5(oQ5$+u~Lgnz~=-teqfLa_%+P;D37CR<@56$rI z(a-h^A}q^V61!p%NfRFOumqkSW+e9cs9;`5FBQMC>oVD(sEoCiJKvXacNAz6Q7EpuL%LlHhl)c!Jo(tMkEs3ieNiaQsJd_p|EzJkx5|cDm zJ41`nZ_=w>J}wv-sd)yZmvAD>>Fzg-!#Q2XD}-Weq3tw7bMa)uYAJPf%#*pY;DstZ zwK9jb7ANf{JG`$B8!-lL?k1lf@88_daFL04#h2;gLtkJ-sKkuVhsCl>P}GkOV>~@R zh@evVd(34LUz)H3iT~X)Q}~a{^doKtO$n+Qdp==V{rk6tg|CDW#r*NwM*SpHBQk35 zhBk)Ekb-JNZqgJJ!qJzRjHQB52AQ`apKFCaALgyvTmW zpVD1af&mJ!e{xZIjOl`Mh~aZf4D#8yDNvYELhI<$vaw;Q5e(5eal~)3vx0;Bu%I;& zu+hhj1j+_|UNzGXT&pzYg37IDOO93=8Q}gqP`OM(RiZ2q*NpmTci0p}R}(dh$E|~; ztkL{27T)RA90gbDp-O6Ab0)l;+o5;d3@Wl3p`4b;jV90%r5gRINYYy>g9F;d7tX(z zKw9MX5+F}T7eeKyj@Xx&2g3T#%u;8%goGQ*`*BUbP>gq(zP@_AK@jb8{H6Ns!N2Qq zj!EOK?!Yu&H+s!VZ4pt~lT318K;)Mtj1|^vNCZ(j^w|QbUW$tlQwsACwMNo33GrAt8im&Z8C@OQc9PnZm?TM@9@6w-RcRZ6KixmR;7Q={^k_aUK-Mp zKvqIXQ6u<%P3ueI(;@n~P{VB@imp9D^`3HmNXiE*M@`#?bw8pS0^hU0_@H2ADRDNs3!ykBxUb&lILvze(RjNuph9ylvqm4M!z^qtk@h{`6 zmMgltSU7UyGL>?e&EZ7$9v>BOIHDAGs$xS8A4k%mbP`n@6hpfR9FfJS!cIuf((|<793dQc8N0R_?eN zWuOFEOk_p6oi4>bh}i1hKR3k8_^t&x65M^!}!K?b?@3A|inb!YV1U84na{N@VJ0u=I;q+P@C< zMW+}r=r!^EOgNdmvD3-XSvBBpHWH{Y1}OaO6g%NhHt`z>$vQd%^EFsNvG>Y-T#HXh za;CQVTP`AcfjLTuKnygQgZvAkGUh%DufwLfO5d&MoKu+%u8vD{O-GaHwA($|Zf)1a%fED4`GV_kiHt<$dLsI*KI+?^#^i5YBpIaAFFGqYHK_db>v@<{M#mUArr zm<*@|p=>|k#lc+EIkhXO#UUEVyG){n#0c+@lOk9;7_trlbIP;^|CSn*YxLEuQWEv2+=>n zsYu|_%gAdGL?Kjp`dZ_W3mNIvT6}(W=;l8}rwrWRSYp>tpX-u{yQS8vf75D1yB48_ zXhqCBOVI+s5gRhkOL-a^V=*R_pk-c-5(D>s!cc=vg=#cl4rHiT>{eVyvP{$9uu1ID ze*ML~O!JSvwVs`PuP7`%x~6JMl%Uo+EheV+<4%5-vpCW!{4e-Bf@i@Q0=Rk>*lQ7p ziWTEpyljgPWI1e*j-bf|Pk%rFtV(W`_|OZPDJVy~?I0_0e>eFCH9+zvNkje#m`xVqC)0=@V#rRzlTCfX!>>@&`_GcA@6EID}NCm_21~o zbQOJT$Tg9n2ppIyIML(Op(8&2e!CVu*M`Mo3>Red7KN?B;1{GXVP}BzM!&=ySw##X zBhDhX&3qURGcIDkg8KIuSQWl8 znm1dB1bohNCLf8WSLH&jLSaCo+{*O#Y=@C~S9{mBI5D@mb^d18V0HqdO_t4gIh`xR zko-lg;Pd|V$BJtkh&&|ER7E53;9=hjW{UlkUD`O74-C+7&xvVVdcAk=D%vwT#_t^a z0rJ$UJR1B)2Ya>=x!&-SWHx=93RtG6c(i_EDq_dS^u&6l(3wz|urciz@xgrxbz0{B zWTiTL-*PZ?1$5{Uuhe_?APj{B1qCA_BSnCj|N4H>==;A6F7+1-i(E#~MS|!_8@W?x z-vBgj^ER$cX>w1NJHquQN$`ac%E-q%Xg70-ot?4fLc_5*sfYhGOQAAhiM_!W+;H21 zw!vEqRWB8~6v{eCF~~76NQoXfjvkj=BO_ez|KJjY4G)NulVz`~<$Yn6Q4hgxy?ZlY@n^I)r)gdo4O zC)cA2opV-2#S0YU2R(?Hb*nPxQv>oQ4>im@r|%HoWQy1i_x~fXT7hq z)3wkpQ9OxG>7tI(U;}DSH@ZGO^w)bT{ozyiw5Yijs)lz*&caOl-Hcoss|kdcnhbR= zV>vx(i7ZsHs5B8Bb2s>PnwD~e2Hzuv?W>6VrY~;cLUuPzg@13G(3^bk$#Zd6p3EQ? zrL>?DT)ltsS>#z=6&dazn`Y)MPc)@ZM3t+^3Ri!uP{fso>ek`~(~*rJEXtu?zJ6-| z0(y@RP!pmE_5gV!BY#B|#Gzd89V9CA?_{D$&1$2aXT$&XhkOR-$U+ey(-T4=Qa?Td z$$L6i+0|YjbZbpK*i>EQ*xYy75Ow|FKMkF}OftP=DKWPH)YM5;F(RBRNpi-8c0w=N zbEbT=<`%Z!_y4h()CHwiCVB?q$JTzp)SJQ2Es|fw&vovPWr`nH5DKHtr{mA!8+pyl z)34EDmAYaiNOyK@vC@wyoBtK6yzi`R*)8rM1)v8`!PZCLnWek5*UXCw5TqZ2N zNYtpYN={`daUvsY+1NiK@%9yfoVAPR)!?R%^hG3Q17u`mlFCL$M+-)}-rjtrH`M1< z)v-R1e5fiD>b*M~QS}}$DSUk3sO@>_>r{odB~)g7C|}Vt%=JYm$ck)AQ>J?eQg3j` z+?tX1bx5mA;NdE_^>mDR6ztw5bMy}WrVcYxoXjR)`R$o|LW>7IQ1G(I`N=uQ8BuuZ zZjHrW6B4ei85Z*ta2VIfMmO7db|1B82h6FNbK?J3+>%mJLAQBahRxelX}+r`dA+!p z{-Q-+f||Ps65YeXB;)SF%?ycnF*)=fU-ph*SH1jv;_zntfJU(}5It|O1yPBsD+EfQ zE5gz3hxn3Fxm#mIVa0Ne9~7jK|fVP2`4{m8PHT zV%y{63lKet5Q*K<1K2R(kfXue^R1_hDSIyJ6+^6z6V|<>v$Khsb93by2nMaLJrQUW zHGq-;s^&EO`E?C>tkt}jIm67f0_Tkqf!7-K2vEbCs{D$tx>-ToZeMcg)u=OB0k)y= zYz%|zmBd6_@N%FczSL_!(+`vF6Q&OUwTq zgc!TekJ0=`s0_z;vrG8o@u3`1wV>?z+SfN`jj*aDhY?W?w*$>PVdLbeZu(|ZE|d#B z_i52(R=rh;p4Z&W4QQjQehek!r5cmr;o&^V`|m?>(@>H9O7T5EsvN1fnS?(nXM&#OKo%nc1s>vC#XwKbzDS#S zMac=|Rb;6eH8{W+#Id|I{BA~Qv|Aj>njALcW@c0gd0ivyuqrielm98o1i@>T8QJLh zvn`yjgeR?uJx#V^c=|o#xuWiOymD0M`M+?bmG#qz$!i!`ku%xr!*L$GniJBb#zKX7Q~6c3X;jV35FbL6czQLi zt^4_qXeM;;VBwQ+(sL^_uhIjI+sx?iByXZ?x<#~1-`!t^Wg#~4%PkV8&f?3`AH9b~ z*sPO+lMoeAVhYzfKdB(iUX9;MV0#3*0vDWx_#w$bJR5ML74pAno}{l>0)=wZ2nn$= ziL*v}%fB=oAx>Cnm!jw8=8|}6xSg*gQ-gV&uSmq6Kr9<-Of-wt1hrHJ$eNW<5`;hw zZ}_9mekBK-k>YJf%Ok(1gRaF`eowE9D`>vRl zSS|aZ+mRn<3s&s$v%XIE5PB0~1=bWQ$Jg80aV?*pmR&owyaLpkH)Gn~Tpb(=jGzh} zD;pacpt<}0tAGHUByv*bY;Frp#~@K*8nGk#LRcAe{w%Ram)u!}naEAlv&BU-?X!$$ zBV3*B9XskXos|4if1R}zoSfIkMR4W!g!K$zP%PFPQ*SrFm9lh3Y_E(rT?ZDC>4{6m z@(Tl^9br!8Gf1?;Bdlvdq0DzlPuVE%P#}Vku-)eh1=;oY02Mz?r$8hhv1ZOZ8S-gTSZ7FP`R^DGdvqD)R zO&E2$e}lFGP{rKEw3OgDjdidey1a8jO%FZb3*xM8%vzb{cx4#@SR^)~L#&kvtU zgSM2n@{mRdu8KC}6j@yh{hz@QWghUE?l=^dFglc57}n+0>%GxdSx(7N8X(STOL^wQ z$~l3w*e{Q7_*|GbG$Z|cWC)cuVtDAY4h09~za4bfJYG>h6xrW++aY7CLXHS_5cA!X z>%5Psq%l2jk4II`$ATB%`r_K!YF;F&`sDpc6ZkcdJC2`TUlZZ1eh~{?oi}fqF4viJ z-h1ry!`W!#Pzk4IKro_5oMFP1L#lozrJYb@hFlZ;+V0aRy}sLVv0@taQ(*r?O1972 zTU^%pt;}Jx7iOzNG%U%)VIokpFtv-h)QB2=R@+#EL3PxwAOp&4##H&c@7eGustu*H^~aAAkpJt0>pDL-@SM#R;wveGfPWg z8Y5~Z2y9IO(XYvwcg++)ym;>Bm@;Aq*<=hWBWb(Auj72$Fg(U91htf@eX19kCH^L@ zsR7kRtX-j&0fJBg@|Qb?y43aA%7OGWUlnpBLQB;$E+e`|k2 zBWBDHzv$)5?hlmkKQ;LqDO)qz7ga)nRkS3xeqiO@fXf|mx z?SAMw&Pw*O9Z2UzM(-5{K~HI~psYX%!rvt_L-|qi34TN`jb7Q%*tgv7D9y$rV3AcJ z%ZI4X*QQTG({VVu3 z+5zW{i>%f&ly<94v03w>HO}Q7K^n@QdL+r7MU#hEm?qX6;J#hQw8`(@%&*W@^(;LJ zx?yQTOc+bdJ?6AHNg_mx%Kl#(r*~_L)^`r$p7pH2L?f6+?TSB{d^Gd*h3Z;A`)_EaTxW= zc(PwWj-WJgEUr?Ar4AJ9RoQ{j^u(i%H%4B@R^iy=lBCm!jG-ntW@Lr%)QLRLF1^Q@Q9_wD2XgyVF$HvwlEoGmm zyXc?P_4erOQPUHluDOxqdV_6*0y7Ou`8Vcg4J_K(t<~1%wbLZu-&Vdt$+>(bK|ZKB z%cJ3kXs_nPqK27>xg|=XSUE>l`EJ_3DbiCHc5ld}lH**Q?j<#-Ox%PmyHj;Z`h92# zuT4wsG{TXIK8~sqsKLvu*CUZnlk$00vy?v62|RGV``gn=Rtv=iRDTP8Kw!yJ8Pu37 znla)j&{5Yoj;zVE4DS;=Ab=|t1S^S@S}G6x`wG_&O*)MwbPQV{Xb92ua4DR52gYCI z^C$Ql(-QfU{1q5qzl-|6kBXmH6dEGh`=^MwB@4W=+S4Z)h8^A}Z%@~NNP&#RC#%fj zfs?MV3Wy(Vp{+u(~FWMhbhhSu47B=)JTc-8B+O>AY zDeeNa2Pxe>@3ZoNOn*JdxlQFY4ec+`m)VD7j71@bVXoKVzj7H;m(9gy%2X^pg)6zH zia1Jz{v6s2w=`~`2wgxLq4ICq(g{pZazw_~_875%@zy@R_vXK!Q+v8-yR0!CfFD(q zDTsnf+0~l;Erca-!AvXeZBHkt>jrP&JdwCuYVMCGZ&oZE6qPx*-YzuA`3#lB8{8f` znM2P`&}bF}gatZX>9IPxZcqqb7peCWHI$$LVtLw1+{G*}oi?MVO5S#2Rv*=_b6Qzx z1zbg}ZU;pOmI9=txcC;pGK(a}^qTDQE!@yG;+nNdcPG)U18;~=4c}U9NhB-z0_}Oe z!rU`}l64=X!sr8kV3uQ9kbydacJ~ZciHWZQb|5LuYr9R)tnPoiC$j4u@ZgxdwW8*K z=D-_txW_S*Lqyi&F4MA=Eu{LjMqMtE6f+*T~sr-WQtX_UMWkDSK&SctA1!t!FvWw1be!%t}J zU9cHYNJKyI2eunG6iL_&NP9o3C$Z!;azF9?R>gW zb^RYgoiEoIo}3J)tjzif?Wqo1VXz=tw4b6{|FRoBk(do}&+90J<)Sy(J$1wLY*C2B zM`}%mz&JSFq1&b6((X0E5`ou>21o^w?|(_Sl8{%yUn`8m^SbhwbFT;$vq{_YuR9MI zO&YaMYU>`=jjgO`Tis42-!%#lrT2x%%Cq(jB#=(Squ^^~%qj-$zlANPZeKZ!nYRV!G*->%8o&3AvZWkQKhbH*EVh#scfD0Q;*^t2|VYG8)Hf$D=s zdTuxbF(X|x{PY5iez+r;n3#CJ-!HQHJlNT-w`;i!x4&YUVnry-+??E(id^mh3fz7 zod7;Nw{YP~A7f7r8>R7S?$A*$P@|l~xM+}o8U>}Tv&Pia^y>LA_xnf!)zV)Vnn-%f zb7;n-_KJt|MsliVOcoZt=+Jj=h+QJy7_qBlStE#;* zk^2wg^&_qZb(ac;&It9Yh@Q3@cWwEI@aKLIy8l98Ykc96)&JLAEkdgRmGRHwq#B*U z4%9U&(<_Uvp@|tSwaVPRtcM(LsS$ivAuZ2TZ(gab&4x8$oK8&`8a^XelIcTA{$knJ zn-~%kZQcl?Gc?W=7EV`?mNcOaEoR)!3@;f|YMe1vw@LF8SLcVk4?;zwuE55< z@={fxLB)K5Vm2=>n<TD?=^Qbw3@b({Qx>qUBC zgy}4;$*sA$z7|QOR$z5KQm)fMU8XOMpqJ5}PS}Sat4uln_S3{xsX$}Fd{jMMN1H8~ zs>UKa*rTJV&WIv#y=zNGv?NM6_L_C_@6Rg_we49D1^+t*5m|#hJUn!@%kl3*RT|i8 z0*HVzI}rZ^0ht$7lNZ)Y z=C5lDF!V2hLGuvdYS0T#RXKJzG47+<0xw5}|D%K2$tfwk16}3H1=2PC9&BOJ?8b*# zx1daaq}mZ~V^foXB^+-{lIv}V=G<@=lOwlGAkmx$)eu-{@q8$niq3CU1Hn}gLQFSnP}wh}p-?pL+mkLw=R*|AoJ zG$#AqVQwRsb5ZLHqKs?)zwNMBnA?9IdF``Oy9BfDqEEFwgy31`cYWe5S62g=_IJ`h zh-fEU48uAKnY8B$S|WcKgKR0F(XwT-8TM2hgbV@sXzBEp`^~bvxruzorcu-AxR;)e z4$h(D9=oc6$NLT>=2IC3^$K4_iwR+?=Z|(^ClKP#pj4=_KqWrW7O0J_8B-xr5@UW9 z@aFd%JzDMr2hONW`Ig2(=5P0L`n3McAAQ>oJC= zS;{4t%u5DRrbR_V3)C|5!%9z2PpU;v3`8E+*7?yJ^-}TmjCrsHNov~Vn5Bhf7hYQ1 zX_j|))FMWwi=yQacln(fTnRbI%Re2}($|1v-W+$&gOcfsJka7i`?owb?*LOw)}OP? zSg|D_f@xX*ZP=_~ZS}G@yMI1R_Ms6T5s{LmLZ{xM$EI-yz*>9e`+2IQRkh0$A@e5& zudLqhPOiGH#BQ^H$avF3vDB#Y=DE=>OMCj{C?*k311;lOZ*eF~oFr4q47KY-`jvPC zYdY)mDrWJ4Hg1QwX8IP4h)X*LxR#^-!LqkK5RyFZC0;cVcVLyW; zNEx%`W~b~BEb~ftU4&XQDY&pd0+CWU`ojO_*y$k$Yimr)k>_fN-cEV%}q6XvAz`Hs}`FEMn(pE+(`O zgn@lUU|@Ja=%;wr`nT+jOY-)_0r2RiWboy#sIn7fYI^^b$*FmN@f_$VSxc90i+Yu? zcy`^Le_s?9G6s{Ce--d{Ms^^|u^@D!&mAQ5G1g2yZm`g<;Az)eDBN9c=DL63?RF2e z!VyqH~ zs;ODI-bjM+m1sb2Y+|Q#oPn}3hOrX&F_=GKxLo9b(!}f&x~9kl1-tLH2l#d zgZstMB0*gK5P%rcoUl~v8oOJ#)i+?h%nAA1_c~UQPuRqL4e*3K5N{u+2!0nySUvHpMB^;(2W88H*;{1W;-U8$SrT=t8tWG8+qkjn3|MWyvnd zWKWUMA~0h+b`u+D(i?-mpQ<+vx6(aZ2nt~8S6{ej8(v1SbzdoQJee3UxFc_C8-+e9x--gAe*3BXhv)%Y-9v+69#J4nROK)O zZGT9t)HK&2zm04!y~&3gwx+yWnC8K7lZ~=>LLXAsdY3{pseiNX;)HatLF&rg zj&3-3s<4U}o4M@}N9PQEXc)iaqB6e*MMOta1WN3T3hFSRYsuZpUWL`@Sta==kN$*v zGquE(F$VWP-$-(J0$_CYm`R$?&vEZrhxloS?!??~4%Sw7i3O$}co7CoT6@|WW_9Cy z7ino&Y$jcCh4Tj|lV;PCgFc{>0Wtpd@ZOC12kZC`?&eyM+4;qyWp#^XzXx zJgLFG>i~5N8bCcfxld>vGPDGrgX}9+*CdTK)~wX47rz6ERh_&+isO}=ATIuuHyLu- zInd;T#kv{wewm(Doi|+*NzB9~aDX*A`CkDyPYGN&>fM^Or-U}Wni&yV`?&1DKd6N^ zV)*5;Oc+F5<>eGaPO7K%!S4X*gLYc$o?!iaQe5HuK*h9i(5cqhl=7}$rtMRA|H^>D zI@uNjQVIy!4m|wtTo|0@jXRPMwn5FgX9!!%mbnA*6jJmG`pKBOY<^=Voc~&SD}LZg zemU5y0E(c|dK+n*5rka4LBS?E@wZ1Qw6{@hPuc1bS<>M7C<3@jlJ~y7j~(mydPloz zL?;RJ9uoHpsnt*%w4t3S6SJ=12m2+F91XFE_(wGM7$T$SBr?TL$rNOOfogkid zDxtH-_!%XJSkE{?xe`HzPB^kaoMz-vGhlP0YGeIyRg#zQPoR<;HoG%q!UGtI@a`Rh zU0*lr4OuPbie*&gVuk2oc$!IO3re)fnIezES;nD(h?9uPI?i%+=4_3EkXub;t zn&k8I1Z0}6SrA71 z0QmlToZV_VR~N)&2eFJxZyY^dP}Vr`8ot0U~|xDwews4c4w5K zBsJ#?eZ}VC;qmw}uS}`kx(hb`5K#JAy7~uIV_NJh>Cth%a^_`Xh&odEHsGPXd^ty( zG6w_NRlm}aPq*JyOG2*1+r1O0rX-FnnNXYBjZ9F6iw2C)rG;>b>Z9>>s zKlP281iq@8aFPL`0)sn(ee-wR@BX=tZ>2M<;Xe@YM%oy#G zA*l|k2QXrmjl3IH;!9Qu1-9(n$Z~kp7j25S4?~2u^J8a(yqdu>q=u9za>6P6SEq{m zx1e4phAw4zz+sP$ukUp-eVN;3JJrG^_B34J+W!<6qGU1yM43}Rs_fbmI$+>;Hq6ZQ zvZ=v``(N&@!hbkhc3IR!0_5i{IOkYP%#+WA?s|~d0uLY{z8IW`=PQ>TTe`wv3VvL{ zbN4-Nrvl#FNK`!qaHzW}ylz11SX>mK#8!YTY#P3GKy)+Gv;(s5X z{#MGD$Nw(@yO}inSjFaZKWjNHo|J&7*h-u)HI}6df3^?Ncwt(3#pD~5h3M~#E+JjV zMk%J5t92`j!R0VzkjMBn(`5uJFJtF~SBoz~)m5`tI)=Xl82*rEi!j;~f18{kbPNJ| zX0)Rk#oSyq7HR=KJ@x`S8angqk5;`vi8Gc4)B8Vuo~F}Y=sH++`gtSWxu`3zKAtkM zo%2Wr=TfLIC!T=EIqJ!}w3tY{+0IADVz2$9Vn3&pN;K8i5<6DI|~V0i{p8 z)&K#<(-na94kU&kewRw9^AFA+;K0&}#TXy$kKOS->w>?etdX>7H#Z>N^u7H@BpY(` zP1$T9U?Cf*Y)%6fqp8vzQz*QzcyU8+y^&sc(G^r!`pDctE%R3U_k^pr0Ayz9GjH6jTH{ohL*Wu<|K>P+MM;%O_iQt&WO?-N;SB7J!?Tg01XopDsd#_ z<^Hr#rBKrIC_fyO{&_t_BDMI(V7m6Z6hDAXJg<6SrYm(gIPI2D-A?8Lm+d40)4X4Y zW`!GF{yrWm+-2CW*-_%%=FotmT8!Bi*P|~}=!f0*xg&LyaA#~GrHX(EnbN_U4gkj# z40OJntcSwaq_W36l)q11lQDj;ypA{jwo;}>gD(9jYqD)c;{hE$0iL0c1mwzNe*=5pkb7@4oct2T|bq$X5yG;3c!Ub12P@ zTFRme;Y~gx!ldI`-Ku2rx~K=;>;B$bQRC!Q*`S7Zp`CY5!1k`*Y1=9*fmi-txvy3t zUmHn9?-sQ`-|!*zZ4QHqit6tA$J8O^$5Q}QL#m3efFDWxJcSCi_Z%qZ<>U2I?Tfrw zht;pb;S?SvJ1<&b;Z7Lfa3QmJ!lo>lGUU_yMSxI6zj8z@V25B%e|gnbIxl~nsOXrU zW^!iw=7aq5+N!bVzZQxWxq5Fr|Dhe%{UUwrHiXbWIf()d4V_F~6IR6++Rxa1_s$08 z{;9tKs_>;voNM=T0SZqNxm4zNF;+Me@qaG~-&&&)^~uOOb5J*h#GIsCsh@s7rpV1>yGMrZ*be?A_nrH0q|`5!KOTJl_0# zpb5~pAHW##&O!nG97%QS@!x_Stq7Tm_eXvu)K(LHWRCkJikbslh<&plY0kCpB-rLX z$guJC)Ssy1h0gg7*Nh4R8oGVWl49?wkY5n<5;pS1!lmD&g__sn`%@Ln;+J@V1ss33 zShQ=vHvJy6t5RdV+ko{-BOkrnNY^D{ut#@freQyVye=fP>vXI%$UxHunRBXPDpjdf z{Nr7EVYR^mVozqZqh4@#;b>j60Qs1d@2M+vF5tJKKi+$-_5Oxn1uMd{4R; z73$Z(GYx92=!G! z!6%6*gEiUGb6XT{+>79h-ooWKizP`t2MQqvL^Utlis4MQys@8AYYvIff|b(crQPH& zqgLo7oK~pGOBb3}u<;^DdnD0ks`9R`#gU?0pxLfnyLkc?i%j-j-NIe zi(fdt>?EHa7c7Q2!Y4Cc$xIE9VBhA{8uGdz9#@n+M_jmYwEN6jrXK)b_UI1}m9G>k zwSX(M{i+w?>hZCfFtNySJmlU!WLV zZ0v)yGO~sF8nD;zLx3uzBdLvRt zPkN~=$DA>vHvd8uX!S~X-xf>6hwb-rmw&iUCMvfJsbJ~?G|`}(Fp%>P$mt1gz|VE5 z;8(`z`pN_OrvdeP-4E1f$VuxcKHn`QE-J!Xde&oi+iM@}c_2>fQV$gUw9Urp@SFDG z@#w?hw#7D7VhOna%o$d&biK`_G#12UH1rM;)NotZyrCz_H)|9y6 zAhaXZ_3Blg-H`wXMwDaYo&U^zKDfI$@wcr!jg-eeRCk{ zueoZf93}dCNlD2Sp~C%Ll*=#YXdj07<1WlU7cPrjW*ZpVqrdWBRU-E3Kmth+=<}t? zdVfy@$R8~dRvo77_6Nh`SAuL>En|g;=b;VSlk5z^_s?372R4;OC&J4KK4kyHz#XTb zuxm~;a8&kpFlKs<vIs7}=g(9OG|e7_&GsRO$MIW_Q%aa;k$$jR+l(e{ z_obM+{8301_~)AZa{TJ|%ca$=3+B=T`(ZP2~6|>qktIr@fiedqLE|W zP8#7j**6i^Z9*Dk0b;dYF}4j0pqVH#+`Zdh6GV4sMG_T7zF-D)xs%e;aOs9cHPZ#S z!oyO#q&FUYU?Z>i<)6Z+WGve|H5OaV+gqW#0@i;uQq%fx==cVCh!6NuJpQW}#Yh)@ zq9nUZT^I3B7OBG)xtJ|gD#f5t46#8FMM6R<+2iHORxGco3f<=O{BixQ(ss4xX48s< zS+^mAS}`kP?tM7>n`=U!mh{Dt5US*p|L7`Zg-%v3*V51Z*FCAaB`${4G%2s_UFRwE ziB-l1=uPwegw@!}v@eWQpMn&RWB&P^C8%F28N6BiK_}5Am6c}!x~`yd<0M4`1EOx) zwb-@O``#rc=X%E<*Pe(PWSm>Gy)MAC#_aWiYRFY7RwOJZLvC&dSNzY0Y|qk(%T`%0 zq;OR+k;1mpU0v+>{{U-2l)ke@17rbFW44v)jn?)DlX4dO2mi)rEo6w{svZ zD+b3@`93~Mwqb^%b9VB8X9lcm)Sl>8ebE#Z6~P09YSLA3wSWJ9nl^13{6J=8TeY{h z%WHGh%D5>W5}<{&_=<`OvfJ$u8zw!(HG*74Q;`UdmLU%p9u&aJUHu!m?yl5aBPIWS zV+Rx9*SbLNns+JQS18suMVjSt;2|y}PXOC&856;W9ayn99;f~bvN&|_Z=wd#fmWDBI%(zqXzd!m_TA9s^MEBRjgNSp+PA%H5F;&BHs#dwR`t& zs;;gM7p^etaK?-ov}eyA2?yK~G!L}!T|h8SfEE`QLh9h1BEj_Kaq`Y@TdNd7_DOmYxtMcpf5cZUyTSGOiq1cdEl~ zT!JvFuf`^!ay@{O@6%%#m82{5cUYR(bh^cL`EUa(swGd);*f{_`GZh1lLs5!Lu$6l zi>I=(5^)Vyt2LZW7^8PuT3Y0W&n>}0R&ajfjvYH_?%cUlP*4ydf0m7uJ0GC*7uOGf z0arZCI@L6~?F_k!Dl|dYUDb&8pZ2HpZnOt=t*gyW8LxfAS!k?iKTslcfs#sR8M^PW z|B3-iRm&4YW+@?ODU7xt^0dZ{8%OKbt&?!Yz;lB`OM}C>>+9>u?RH~*%mpnA4RN_C z>A{)us55(a%rUwnSvq<0T=-2k?$N!D3Ash&Z#~7?XRIg&tjm;Ew=(!4 zMz1~*ieu`CCBX8IecLEt?RL4$s$xkqJTk62J3AS!Zhp{`twVs;{Q2|Yl?$UKtP&yM zp|n|Tms zewhFh_SD~ok?W?CxfaFzfFYAdBTJV)ZN|9aCK`L;o;BPxpODg)YQ<( zks~7#R_ZFQq|CQ>5vp11F0wyMrviYYUr8x=Nd5gcViaXA{0{97El=0*NiP^$yOA$% z;tCckYTsY}6(`A&ZRh~dIiX@E4mP^$(mRS0&gLn-JV+7m>gr;+x`k&Q9zTAZT3cJG zw6v65E|=;4EL%zzrA+&f{3}k$iU@DoIu+PJFtKaRjZB}j7A-}sv}#YSh|Du!4H!|m zkb#&Ljgt2vWcgW!7_v$174k80#GujrpLpkaqky$YQNn_&DO08(?Om9t8CF85Z$O8F z>Jw0Nl@47Ieh&3PgImq&@9#%YX=7s}f=ZQe;5&qd7C%a(7IaYVnsXH3YL+geyQj99 zEVekcnUOM&48N;-t*?kOUfMub=WxC2g$NEYwuje(6_qD-Jx?w%dJkJEHo4Fj$wO`3$E!vd}tpa4$2bXe$!(9r=M#?N~3dk1@^`sjdAPf!Q12>*W& z3SPGtuob-C5eSa~7>fXe$tonOS=+a7r-p_GN>5KWy=`bu%^~+=jRV!J%k0fk^$1=sCJi2$ zqp6MYPV$D~xtctAGTMRyu2B7mu}aicAO+w79PK@D=s)((AT;SHj^nHd+D4fjb}`DS zbBq~LRF^2IB*kLTB|2>#f-W68jKCEUSceK?L`AJj!A#x3(P%kmiOtHb=~@dlr(3l( zi;A^kA|B$~^M`-u1gA1j`h+ja2Q?g zY20;x!VT99t~kHq@{2i~AB>{i9;H_Ah@yjueNNwBcg@oMU9YBL@DqOu-Q7avV3gf49!Q-- z$>PkiTj9Lv6*eAdr5LxBK&X)g^(r3zMosg%O!=qoO&J5~r>Ig+JvR*{N9r_)u07@CR>TQcx?r&)5j*eiHp&WsYN) zC5FS+zc|r1k2AI(xb%DuH($=s*iYV0V!#`sIkCCX9Miy+R?*N!v0348mrPQp1BBv)h_6f><|1zNKN(6ZTVRG(5Jk(Bs*l#DDhA13HTGYvU%Hw&}@kdN0d{A|2^X5kW*nAV?7r6i`r6=`|pN zpi(0!NGF6eiXhSjq=a^O!ByrWGNfY|vhaap>T(Q_V0w6s2-+NFGwH|_M;m#ABuIsn%JiWZ~5>-VM zDP&O|g@Oo!xOrGCl`BPbMp%sTw(vG#+n6d#Z?XVHUQL%PD3)9ga-7Q zMNg;-j~+VuML?kL#D1g47R~##>L)GA=o3sB=q)-w1=a(OWfxs-DW8M8V6;#fq7G|w zLE`F)lbXt@9OYj8_=1YUXKNXM!{Xv-_5p~C0|c?bQK}U`Lp*FdO&_j5PwkP4tCw~i zq9u<47v7<8JVqy3PE-XEFy8i1!}jZz+~W5Wzv>dbx9$(F^_sWi1g92v@8^0h7MRDf z53uOU$||zkkcUY3>(`HTI-R0L@G3WN@_x1#7h^+UK`@Ba6!rs)ry{2PkLf-&fE=jzm!Xv}^R@ip$jd`wKK4k-Ei*aBV^{{m%!oIihv^fdI`$ zDzN~ug(7%%gP%WtJ~upQG#W*tS?UUn;q8<}x&@aE{!Y0zU56Dr_b+mIOebMrpZSj+ z`i%c)ONS>MoTSuYaf%Y+OkA7=7EfF{AyPh?V%W zc8Jp>hSciAHCu>m^6`=Dc*|u^``%y*iEAQrS z^K7*ue8sp%D+J?jRBk@fyvzI|DSYfs(M>3@_}Z(Oxqp(2zP?odt6@T2h{c8Ox4iw& z^Dt*uPub!sARvGyO`61o&4^rCP!}KzD>@3`8AY?MCk;_(nV4H4zsz58bxH*Oq9J{2`5 z^^fKV4F*SZh#!MmZLh6-@V7-rnX0y6Q_!M1{?KIzp|o9U{R!821@`<}qzMHUO&n@E z!$xmKbUa*YfqO%tF2v%suEkq@e$WKV7FS+gUX+lKz$qY0h+Jg@gL68ItnXpW`3a&f zUC=>SEA{##76-9O;v^#lwv71K9)d+!`n+4ykUhrf*QhgkPv!Dsgw6E!}xXO+Ac=o^#<{n4uLYD)9u0;_nqbe+>-; zDxYA<```PyckmpygoTE{vPVyKpKcsIRb0*kccCoAda&#~)E*;ToLuC!$~!sH`|rPR zG@3M9QI%XK zVi{LEa1M|hI(P2O1AmbkG;3jnqH7jbTlOBNueP72?rZ+!G?oq#DqQ?U`mc1NTihHF z4&XG;U6}8#y@0grDcXo`#6viSem#;+E7Mb`eSCZJ^z>A&0A3qLnwJN|pXnqQts*jG z^)*F$%X@5o6yu=__EpD+y3tn!M9EPEGsa>qQwuo3GCqQYRZ zdCQukSdX3lAJ}KXxlRZxvmn;+_kiHyIf@O^uF{+6 z+)Ui{2d(<~Fr_b9NL}OGkh`l|F`?xgR+0Q(`;0s2tT?*D0y1>iT6)6XzR-Q4X*=8? zGINW((70A?B5Pl}*Jw?#^Ztg26Eh|LZD^IrpJAu()s*?~dex~!1Dzdt1=CbBCx>=?|*!|EWxZ;5B;8HH8( z2OVuoZi~Wo3nTWSf!A@k@HbwOOC45Tq|TF;QO&37DA#4EawIkUZ9<29M{(9?Ov-g; zF<+e_*DB2mkLE>HLnQA?(E=;=KE&u7viEb~J9F{;B7!Bbtj|vLjMEbB8JJGMPRI<~ zT`z;bWqAuZI?|9KLyUF|<}%8L#nraGhj>WwGZ0qjR)esD#exu4mfwX4k%hk{*YVU! zzfIL=9-=2Z4k8yfHw6pe!%5qDJn0r)=V*5;kfxj(K~j^9Sn+iDA2|5;y`#4xKu6qP=_fa`eg!Qi05lecALG zir1gXxXP)(7-0x%mFO6V0NhztTy%xP`lpjRs)|w~i!BR08+GL|J606UVjrJ?9*KpE zBYZz{QZ`4Jin^N*=rs$qT(X9Avq>pB5k;Z9z_KPG#3x8S*0+IRAv0`qX~23wa%j?| z3D1x#Yp*L|;QIx+~3?yE@UsV&s1A!N|EMG8ti{x7(H22!dH^7gI01BDJ>M|x4{F0c@E zNjFJdPI5WI6kso;hV3m!FcaJbB$e{z%hT%BtIJ$m9W|JQF4%d3x~~3{Dm~~56mILb z2_i0VAmzt<;`Q*fLTB8wwBDlb3MbQnXib1t$#v2-t=s40iZIl6kG?^)aF)1rOB zAdJF3-o|qt_J$)=s;Qjx$aLiW)1MCYK{GaAt>L=2mj6+CsrGJ8G^Siu^niBFlp7 zvasFyl-uN1^Top6D;Kash!y!9(bJFf*d6)S7?lXN7^2u+VD@lIyw5zTHHW{6`GdB( z8iC&dNky$z)A;e@*^U84?PXSL_4EELN`MLF)2OpTDo_-!3-XHy?)v$ad|w(!PpBM~ z5m`uWIY(AS3T-8K(pjp=id#;*OZb8CI^uX0 zn7zG;XZ?;+kMZrmN5~D^S`lC?AUSmF)~(ED3}%6Bkc@eOZB||)bOs8$1wj$8$l@qT zP`?y%@Q+e1W$1~NVaHEMmvoCGFqY^@9n^OLJJ}aDMhN?@XaTwS1~~=kci<(FU3M5(+L`^+H?$uh7ol2!x0lY`O4ir7}R~B-39g9kNL{8jC4w{gHqf4It z*k6Y^-CC5ua*3^F(mr&p{4A_6u8B0Ez-&Q;l^Zft?mkkE?HiznkQ}zPddd}7F)=ap z?YG~ScHI>huA3Ldzk==2?a-~FjJrtCi+7#%+5M^Wr9Fl$>AO^1)AcFdjy9@mD=?NmjRyw>Qn4Ig{(IO4W%S9fIqAIYRHRJx_5s&|`$S5||$DXQ37J{t|MD zs#=g~pln|!%qZh%42r`oCQazkuv4MYIsexuJ$5dmcZ+vTjsgbs_!2&2LSPBZw3c&e zuAH$@yDd~yd4tBF3+N7B0u_KtNT|YBB>11K3x`TYg9Z(vqeqXHny|`2)M_81R@1kh zrk2b9!Qfv}XC+Yhq?t~bhj)-ue0GWzz^lmnxjqz~c)}72;8_Uzzd55&vrw;R-YmL4 z3hz(bX`IRX&9hM#LcNz5{wy$0OB0yxI)_)1a!lU`6M!Wx2T&Izfy;m%VlU_qyo8j> zzudq#vYf0@gxbD+d)l{eA9oCv)|i{kdk#}ySTDdV6yi!mtpp|38N|L;+E>SN(Ym3d z&SYGlY(`)#tE}?iU#i4CwW>$@|MGv;swaaZq#<3d{|T ztRmWNYz8SVcR*uc3CkXMf{(zF$B4!mz(q)^f0qjM0=FgKjpJfdyLN5bv}seRqz1FW zfy{$6ABLf=R{TRzi*rRvP*5s&sQRUMDP+hRQpeUd)>)X0Q$P#__LL_24$IEYG<4`t zI(hOWWo2cRWYmfuzegc^hgE-5G!E(*G2%v0R$X-|_qa1o`|8K!;2o%#1H4Dwb`*($ z(RdAT$L!v>f49knS~Xy1VWAy~mqi&@|%;MTtUofw{~x z%peRhUdAahJB5ZuyTm?4A@I^Ex9GZ|%P`kmqIVpnLN{e09e#=I`d-MuXZ8Sd3M!|7 z-Gx0aX1fUKT5${t%mO{qgF){umU=AT0kwcRE-mN@eg`CzTi^{~v&$ZIlIwR>ty(qO zzI}U%39M{GA^XmKIW&6nS*nt9Llm+L%q^mclX373C4X2F=;mGG zyJNhLSqQ9{S!WBY!{RYR=p-!Sch8YJuD&As2h9e;a8zI}=K$_(^?vRhsmF0P(3+wB zLL5j0WFmQ>AF$a~9h?Frm5`7SN=iziBS(&ugt%h+g>0}EDZyUfU*rQhQWUZa%oII@ zMGWevH0?%09EB)j<>2ChdZQ1y-V2eevKJJ1eck*^JjA+S3x(H6mvp0G3k3+Q*g1b1 zJ%UU|U7;}{MJtXyfqC3`eDyo*8J?7S98U+%W;VU0DcA@|0d9d;flV%dumX@&+}zw~ zMtNA_7kVs zP|H-dwP(QZwa*H+oT%6oV(>JJ!2-qEf-B_p?AuE06RzcooSY;4umol?N-AR9Pf|bc z_drKrF3Sh>0!IKT#NR*%Y;HM$5#XL2GtpOHeU<&LFlVr2#@!sqqR+PcM)lLKQ`q7> ziWMJXf#sZRxh^a6^ZmqKhH4K*PFBuQ)nQMt46kvE1x#6r$k1WyP;=#+zmqT|4mDbP zxRbEpaXYt36F)|=h5-LJrU*YQL7Brh9bLbWdi9) zB$b*qYts7l>lIH8W*NlQ4%Ax>-EfX7C*PzOQSLAk<~?^Xp4FMW*Lks=vs+Zua9ddP+(03upG?_OV~ngHC|AxF3Y1%I|@hL2SipW*Jb6BKJ6}P+9wpaU7B_y zj2E7Q(~CpD=Xr+8h)q`t>@`aae-@M-`0NFLm?m`){523?#@0+7KsKNf;s|g8HnrXa zcjb)2Y1_6f?ccwji`tbGS6L8Ov$vn5=az{<%>wJ5Qx-k_1P^#td1#gCq|?`@kp9a! zN(P}-n(u`R`R&vm1$Gj~&ik9UsUU$BK4u%)yZb7161O9-r@K=eN6bXTTTnIzqu$MW zNxWVt&zAt{z&}&v4|ffQu0q z!8>A`l{%5T=xP&EG$KtXD2wzUk8E<1p8j7|M)nLkFcn+}RD#?F4S>xo4afi_6^%wi zUw-)|rv?$dQq+cF(zaizW-81>MZJ~4cJ6rDS|DWLN^-6Aj3OsAm6t#Hwi(Pq14f^v zx*%Z|H93bnB9%Ist2{ImGU!{8CKQxDXxa$>csr@2MP%=Q z1W?-RDXKiDuNZ2p~UrCz5fA+7{A zI97wBK%XCAD~BiS?G^Baa^>_~#Kb)iStaiL&aVOI_Waw9a)OBQy9*Xrh%&{@{Egfy zH&^t8u4y|0ua_s%go4t9KLeWfqsUI>AmwH>;P0s46~*5U{i1gkW`vB zZAv?L?&Q>JdzAUdv5 z(0hwfn-rr=T~mb)$jsM{cRZY1eJgx+SN8R69426!^KrZF#DB}^O2_Pk=N zHvp~Hl5~r%v!E(4wb*8e;wScip0kJ}cFE%0A}F2oV9@(Z$lk?G>aqGVDCyM#Y&F$9 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 literal 0 HcmV?d00001 diff --git a/extras/appicons/icon32.png b/extras/appicons/icon32.png new file mode 100644 index 0000000000000000000000000000000000000000..f7893863836390e2f9e257e9f3f1313596dd7a7f GIT binary patch literal 1991 zcmV;&2RQhNP)%WZ8DQT`kDFs^S(2`=leeU>~Hs# z|MRP+s*!t}TD{X6tGz>!GPlabV_}W6OI!J+d9KxYTXpt1Xfz;FM~%|%79t7PL<~QF zaXYO^6~2!M_4%!GgK~~?q+VC<=8W&*{}t@)PSh=0sEk*R@pNI*z#b&5 zoX7FMU18CZS?C5VA@Eow-jkAO{6@bYwT)a4iO6WB$4@`KPS@o{(K6*aEr}#uyGzo2m{TNe3Cf0uix8Rz#)Km{n1b$$NVGIWj7V18$s=R} zvg!`fYb`Q88}GwaM4W@5G%NnQEw&H`P(H%_?ZIm8o@za6-M05H_gd6mC2Eg|5?dIr z5sML#kEA{hh@`JgJ3!yWbbNweCt>n9rhG7vus6CP13sZ?riJiA2uQ6~53eTpI4Zyt z%o~ddJq`Z5Do};%YU|1l3z1i##lo$KNVwF;Q<3;^XIDm!9u5z$1GP|7&Nsz*Bu^Pe z$EXNA=I$fxBD76^PVfn6K06iHsQ#D|vj{$kYQ3fY5c?oBA6#C0_pc4kLKBhk^N05b zYAC$*h#?u@(^j>y<1v_U8)6Tf!yFlfbFY!=^c6&21=GqroZ57y*{DQRckoZO)Z2le zEL4cUW9R7lxio-Z=N_G(0K}aK*=^IH^x0jDQ%W^Wv!VTYFbtlJL#q%1)4xLv7;fFC z;?kizK}Rj9*{Bo1Hk4rn&~jNOq7ErG7AWV*3;bL9=2bm?$e`~)c3Cm4yGhu=$F$7{ za~7ym5SUtl|2``bm%+5`Fb+mP%zrpTtJTG5bgpU^E@Ash)(uce#0BsiJnx=}xEfou zSZ6ky5s{DOMVhaRPLZ5_842iLVG4<=bsQdx#?&5h^Tl`kYQnR@f4|i>*}JL;D?$z9 zbs9zXQiC`d5uxem1j0*D`xaCP+dQON2tEvc`^yn=xZSUP>ypdG1%!l0q>Bn8iq|`I z=s%nbuX5!lEUEJP` z#_Pj{hzO0}9E@?%ejHl*VQ=n$dD?oShR(pT&n%jbT0qmGvFII}B7+tq?@ucek=F7G zKFmL!LC)8uNasnoEX~Dx(LtJh5J#i--7yTCgK0%E;WxoI=_vhMc@dtlh0r_DCb<-! zRfTxnf#RCyjJg8)+-DeK=Hb2bE4+*WEEkz6ucBw9Uvcq0Xnq@Y>SUqhR+pauC8ySu7h($EZsinhTK%82#cimDRUpq^q zcc$Z)2cCy2==x4yzDkM5FQhY5mhYehSh3+#+_&W7vG6lWMUG2DwDs{wyii_4lL>2{ zh{#&qpy_21la^C_`6|(?bJ!C*gx6vdkjO4*N3P?&Ed{La=8a)cJi&LtY3?pkVq+*s zSwq)}Gmw~V%#B|_(#I2!&>qP8Q|u7QmxdTSX4KW`bK($@uF6=gv&)a7ZSg36at!M) zm9aMYbCM?xK)TN$suX-uA7KCXLV}Mx!~awbh86*g89t0AOAjO259r#ZH%TJ2adehNT Z{3izTS!nlsu=xN0002ovPDHLkV1k5=#^wM3 literal 0 HcmV?d00001 diff --git a/extras/appicons/icon64.png b/extras/appicons/icon64.png new file mode 100644 index 0000000000000000000000000000000000000000..8224264c1c566e7585fade3d8c441a798b262dd8 GIT binary patch literal 5162 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 Ye}2j%&=$!ff&c&j07*qoM6N<$g2{69mH+?% literal 0 HcmV?d00001 diff --git a/src/Main.hx b/src/Main.hx index efa0e2d..2a3d60c 100644 --- a/src/Main.hx +++ b/src/Main.hx @@ -1,13 +1,49 @@ package; +import flixel.FlxG; import flixel.FlxGame; +import flixel.util.typeLimit.NextState; +import funkin.states.ui.TitleState; +import openfl.Assets; import openfl.display.Sprite; class Main extends Sprite { + var flxGameData:FlxGameInit = { + width: 1280, + height: 720, + initState: TitleState.new, + framerate: 144, + showSplash: false, + startFullscreen: false + }; + public function new() { super(); - addChild(new FlxGame(0, 0, PlayState)); + + initGame(); + } + + function initGame():Void + { + var flxGame:FlxGame = new FlxGame(flxGameData.width, flxGameData.height, flxGameData.initState, flxGameData.framerate, flxGameData.framerate, + !flxGameData.showSplash, flxGameData.startFullscreen); + addChild(flxGame); + + Assets.cache.enabled = false; + + FlxG.mouse.useSystemCursor = true; + FlxG.mouse.visible = false; } } + +typedef FlxGameInit = +{ + var width:Int; + var height:Int; + var initState:InitialState; + var framerate:Int; + var showSplash:Bool; + var startFullscreen:Bool; +} diff --git a/src/PlayState.hx b/src/PlayState.hx deleted file mode 100644 index 80ac510..0000000 --- a/src/PlayState.hx +++ /dev/null @@ -1,16 +0,0 @@ -package; - -import flixel.FlxState; - -class PlayState extends FlxState -{ - override public function create() - { - super.create(); - } - - override public function update(elapsed:Float) - { - super.update(elapsed); - } -} diff --git a/src/funkin/Conductor.hx b/src/funkin/Conductor.hx new file mode 100644 index 0000000..5613e9f --- /dev/null +++ b/src/funkin/Conductor.hx @@ -0,0 +1,149 @@ +package funkin; + +import flixel.util.FlxDestroyUtil.IFlxDestroyable; +import flixel.util.FlxSignal; + +/* + CONDUCTOR TODO: + * Add time changes, so most things arent hardcoded + */ +class Conductor implements IFlxDestroyable +{ + /** + * Signal fired when this instance advances to a new step. + */ + public var stepHit:FlxSignal; + + /** + * Signal fired when this instance advances to a new beat. + */ + public var beatHit:FlxSignal; + + /** + * Signal fired when this instance advances to a new section. + */ + public var sectionHit:FlxSignal; + + /** + * The current step. + */ + public var curStep:Int; + + /** + * The current beat. + */ + public var curBeat:Int; + + /** + * The current section. + */ + public var curSection:Int; + + /** + * Timestamp of the music that the conductor will follow. + * Should be in miliseconds. + */ + public var time(default, set):Float; + + /** + * The bpm of the music that the conductor will follow. + * TODO: tie this to a time change instead. + */ + public var bpm:Float; + + /** + * How many steps in a beat there are. + * TODO: tie this to a time change. + */ + public var beatSteps:Int = 4; + + /** + * How many beats in a section there are. + * TODO: tie this to a time change. + */ + public var sectionBeats:Int = 4; + + /** + * The length between a beat, in miliseconds. + */ + public var crochet(get, null):Float; + + function get_crochet():Float + { + return calculateCrochet(bpm); + } + + /** + * The length between a step, in miliseconds. + */ + public var stepCrochet(get, null):Float; + + function get_stepCrochet():Float + { + return crochet / beatSteps; + } + + /** + * The length between a section, in miliseconds. + */ + public var sectionCrochet(get, null):Float; + + function get_sectionCrochet():Float + { + return crochet * sectionBeats; + } + + public function new() + { + stepHit = new FlxSignal(); + beatHit = new FlxSignal(); + sectionHit = new FlxSignal(); + + bpm = 100; + time = 0; + } + + function set_time(value:Float):Float + { + time = value; + + var oldStep:Int = curStep; + var oldBeat:Int = curBeat; + var oldSection:Int = curSection; + + curStep = Math.floor(time / stepCrochet); + curBeat = Math.floor(time / crochet); + curSection = Math.floor(time / sectionCrochet); + + if (oldStep != curStep) + stepHit.dispatch(); + + if (oldBeat != curBeat) + beatHit.dispatch(); + + if (oldSection != curSection) + sectionHit.dispatch(); + + return value; + } + + /** + * Cleans up this Conductor to the best of our abilities. + */ + public function destroy():Void + { + stepHit.destroy(); + beatHit.destroy(); + sectionHit.destroy(); + } + + /** + * Calculate the crochet, which is the length between a beat. + * @param bpm The bpm to use for calculating. + * @return The crochet, in miliseconds. + */ + public static function calculateCrochet(bpm:Float):Float + { + return ((60 / bpm) * 1000); + } +} diff --git a/src/funkin/import.hx b/src/funkin/import.hx new file mode 100644 index 0000000..c36879c --- /dev/null +++ b/src/funkin/import.hx @@ -0,0 +1,18 @@ +package funkin; + +#if !macro +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.math.FlxMath; +import flixel.sound.FlxSound; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxTimer; +import funkin.util.paths.Paths; +import haxe.Exception; + +using Lambda; +using StringTools; +#end diff --git a/src/funkin/macros/ZProperty.hx b/src/funkin/macros/ZProperty.hx new file mode 100644 index 0000000..783bf18 --- /dev/null +++ b/src/funkin/macros/ZProperty.hx @@ -0,0 +1,28 @@ +package funkin.macros; + +#if !display +import haxe.macro.Context; +import haxe.macro.Expr; + +class ZProperty +{ + /** + * Builds the field for the `z` property. + * @return New z field. + */ + public static macro function build():Array + { + var fields:Array = Context.getBuildFields(); + + fields.push({ + name: 'z', + doc: 'Z position of this object in world space.', + access: [Access.APublic], + kind: FieldType.FVar(macro :Int, macro $v{0}), + pos: Context.currentPos(), + }); + + return fields; + } +} +#end diff --git a/src/funkin/states/FunkinState.hx b/src/funkin/states/FunkinState.hx new file mode 100644 index 0000000..c9a1fd7 --- /dev/null +++ b/src/funkin/states/FunkinState.hx @@ -0,0 +1,60 @@ +package funkin.states; + +import flixel.FlxBasic; +import flixel.FlxState; +import flixel.util.FlxSort; + +/** + * A FunkinState is a regular FlxState which adds more music functionality for it (etc. making objects play an animation on a beat hit). + */ +class FunkinState extends FlxState +{ + /** + * The conductor that controls everything music-wise inside this state. + */ + public var conductor:Conductor = null; + + public function new() + { + conductor = new Conductor(); + conductor.stepHit.add(stepHit); + conductor.beatHit.add(beatHit); + conductor.sectionHit.add(sectionHit); + + super(); + } + + override public function destroy():Void + { + conductor.destroy(); + conductor = null; + + super.destroy(); + } + + /** + * This function is called after the conductor step changes. + */ + public function stepHit():Void {} + + /** + * This function is called after the conductor beat changes. + */ + public function beatHit():Void {} + + /** + * This function is called after the conductor section changes. + */ + public function sectionHit():Void {} + + /** + * Rearranges all FlxBasic objects by their Z value. + */ + public function rearrange():Void + { + sort((i:Int, basic1:FlxBasic, basic2:FlxBasic) -> + { + return FlxSort.byValues(i, basic1.z, basic2.z); + }, FlxSort.ASCENDING); + } +} diff --git a/src/funkin/states/ui/TitleState.hx b/src/funkin/states/ui/TitleState.hx new file mode 100644 index 0000000..f97cee3 --- /dev/null +++ b/src/funkin/states/ui/TitleState.hx @@ -0,0 +1,14 @@ +package funkin.states.ui; + +class TitleState extends FunkinState +{ + override public function create():Void + { + super.create(); + } + + override public function update(elapsed:Float):Void + { + super.update(elapsed); + } +} diff --git a/src/funkin/util/paths/Paths.hx b/src/funkin/util/paths/Paths.hx new file mode 100644 index 0000000..74aac9f --- /dev/null +++ b/src/funkin/util/paths/Paths.hx @@ -0,0 +1,40 @@ +package funkin.util.paths; + +/** + * I wanted to name this FunkinPath but that would mess up my muscle memory. + */ +class Paths +{ + /** + * The extension used for audio files. + * + * @default ogg (mp3 For web) + */ + public static inline final AUDIO_EXT:String = #if web 'mp3' #else 'ogg' #end; + + /** + * The extenstion used for image files. + * + * @default png + */ + public static inline final IMAGE_EXT:String = 'png'; + + /** + * The extension used for scripting files. + * + * We don't have scripting support yet nor an idea on what haxelib we use for it. + * + * @default hx + */ + public static inline final SCRIPT_EXT:String = 'hx'; + + /** + * The helper for returning content and objects from files. + */ + public static var content:PathsContent = new PathsContent(); + + /** + * The helper for returning strings of locations. + */ + public static var location:PathsLocation = new PathsLocation(); +} diff --git a/src/funkin/util/paths/PathsCache.hx b/src/funkin/util/paths/PathsCache.hx new file mode 100644 index 0000000..9654fe7 --- /dev/null +++ b/src/funkin/util/paths/PathsCache.hx @@ -0,0 +1,254 @@ +package funkin.util.paths; + +import flixel.graphics.FlxGraphic; +import openfl.Assets; +import openfl.display.BitmapData; +import openfl.media.Sound; +import openfl.system.System; + +/** + * A caching system for PathsContent. + * + * This caches content like audios and images for faster returning rather than taking a long time each time. + */ +class PathsCache +{ + /** + * The content that doesn't get wiped from a cache clean. + * + * You should only put something here if you use it on a daily basis. + */ + final removeExcludeKeys:Array = []; + + var cachedAudioKeys:Array; + var cachedImageKeys:Array; + + var cachedAudio:Map; + var cachedBitmapData:Map; + var cachedFlxGraphic:Map; + + /** + * Initializes all variables for use with this class. + */ + public function new() + { + cachedAudioKeys = []; + cachedImageKeys = []; + + cachedAudio = new Map(); + cachedBitmapData = new Map(); + cachedFlxGraphic = new Map(); + } + + /** + * Caches and returns an Sound instance. + * @param key Audio key to cache and return. + * @return Sound Instance from cache. + */ + public function getAudio(key:String):Sound + { + if (cachedAudio.get(key) == null) + { + var audio:Sound = null; + + try + { + audio = Assets.getSound(key, false); + } + catch (e:Exception) + { + trace('[WARNING]: Audio could not be loaded! ($key) More details: ${e.message}'); + return null; + } + + cachedAudio.set(key, audio); + + if (!cachedAudioKeys.contains(key)) + cachedAudioKeys.push(key); + } + + return cachedAudio.get(key); + } + + // TODO: Maybe add gpu caching to images when we get options? + + /** + * Caches and returns an BitmapData instance. + * @param key Image key to cache and return. + * @return BitmapData Instance from cache. + */ + public function getBitmapData(key:String):BitmapData + { + if (cachedBitmapData.get(key) == null) + { + var bitmapData:BitmapData = null; + + try + { + bitmapData = Assets.getBitmapData(key, false); + } + catch (e:Exception) + { + trace('[WARNING]: Image could not be loaded! ($key) More details: ${e.message}'); + return null; + } + + cachedBitmapData.set(key, bitmapData); + + if (!cachedImageKeys.contains(key)) + cachedImageKeys.push(key); + } + + return cachedBitmapData.get(key); + } + + /** + * Caches and returns an FlxGraphic instance. + * @param key Image key to cache and return. + * @return FlxGraphic Instance from cache. + */ + public function getFlxGraphic(key:String):FlxGraphic + { + if (cachedFlxGraphic.get(key) == null) + { + var flxGraphic:FlxGraphic = null; + var bitmapData:BitmapData = null; + + try + { + bitmapData = getBitmapData(key); + } + catch (e:Exception) + { + return null; + } + + flxGraphic = FlxGraphic.fromBitmapData(bitmapData, false, key, false); + flxGraphic.persist = true; + flxGraphic.destroyOnNoUse = false; + + cachedFlxGraphic.set(key, flxGraphic); + + if (!cachedImageKeys.contains(key)) + cachedImageKeys.push(key); + } + + return cachedFlxGraphic.get(key); + } + + /** + * Clears out the cached objects inside of this instance. + * @param runGarbageCollecter Whether to run the garbage collector after clearing all objects. + * @param bypassExcludeKeys Whether to remove the objects even if it's inside of the exclude list. + */ + public function clear(?runGarbageCollecter:Bool = true, ?bypassExcludeKeys:Bool = false):Void + { + clearImages(false, bypassExcludeKeys); + clearAudios(false, bypassExcludeKeys); + + if (runGarbageCollecter) + System.gc(); + } + + /** + * Clears out the cached audios inside of this instance. + * @param runGarbageCollecter Whether to run the garbage collector after clearing all audios. + * @param bypassExcludeKeys Whether to remove the audios even if it's inside of the exclude list. + */ + public function clearAudios(?runGarbageCollecter:Bool = true, ?bypassExcludeKeys:Bool = false):Void + { + for (audio in cachedAudioKeys) + { + removeAudio(audio, bypassExcludeKeys); + } + + if (runGarbageCollecter) + System.gc(); + } + + /** + * Clears out the cached images inside of this instance. + * @param runGarbageCollecter Whether to run the garbage collector after clearing all images. + * @param bypassExcludeKeys Whether to remove the images even if it's inside of the exclude list. + */ + public function clearImages(?runGarbageCollecter:Bool = true, ?bypassExcludeKeys:Bool = false):Void + { + for (image in cachedImageKeys) + { + removeImage(image, bypassExcludeKeys); + } + + FlxG.bitmap.reset(); // Flixel likes to cache all texts and transitions, nothing wrong with it but this is a graphic clear. + + if (runGarbageCollecter) + System.gc(); + } + + /** + * Removes and destroys an audio inside the audio cache. + * @param key The audio key you want to remove. + * @param bypassExcludeKeys Whether to remove the audio even if it's inside of the exclude list. + * @return Whether an object was successfully removed or not. + */ + public function removeAudio(key:String, ?bypassExcludeKeys:Bool = false):Bool + { + if (removeExcludeKeys.contains(key) && !bypassExcludeKeys) + return false; + + var wasRemoved:Bool = false; + + if (cachedAudio.get(key) != null) + { + cachedAudio.remove(key); + + wasRemoved = true; + } + + cachedAudioKeys.remove(key); + + return wasRemoved; + } + + /** + * Removes and destroys an image inside the audio cache. + * @param key The image key you want to remove. + * @param bypassExcludeKeys Whether to remove the image even if it's inside of the exclude list. + * @return Whether an object was successfully removed or not. + */ + public function removeImage(key:String, ?bypassExcludeKeys:Bool = false):Bool + { + if (removeExcludeKeys.contains(key) && !bypassExcludeKeys) + return false; + + var wasRemoved:Bool = false; + + if (cachedBitmapData.get(key) != null) + { + var bitmapData:BitmapData = cachedBitmapData.get(key); + bitmapData.dispose(); + cachedBitmapData.remove(key); + + wasRemoved = true; + } + + if (cachedFlxGraphic.get(key) != null) + { + var flxGraphic:FlxGraphic = cachedFlxGraphic.get(key); + flxGraphic.persist = false; + flxGraphic.destroyOnNoUse = true; + cachedFlxGraphic.remove(key); + + if (FlxG.bitmap.checkCache(key)) + FlxG.bitmap.remove(flxGraphic); + + if (flxGraphic != null) + flxGraphic.destroy(); + + wasRemoved = true; + } + + cachedImageKeys.remove(key); + + return wasRemoved; + } +} diff --git a/src/funkin/util/paths/PathsContent.hx b/src/funkin/util/paths/PathsContent.hx new file mode 100644 index 0000000..3e679d3 --- /dev/null +++ b/src/funkin/util/paths/PathsContent.hx @@ -0,0 +1,90 @@ +package funkin.util.paths; + +import flixel.graphics.FlxGraphic; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.graphics.frames.FlxFramesCollection; +import haxe.io.Bytes; +import openfl.Assets; +import openfl.display.BitmapData; +import openfl.media.Sound; + +/** + * A Paths class that helps returning objects or content based on stuff inside files. + */ +class PathsContent +{ + public var cache:PathsCache = null; + + /** + * Initializes all variables for use with this class. + */ + public function new() + { + cache = new PathsCache(); + } + + /** + * Returns an Sound instance with `key`'s audio file information inside of it. + * @param key The audio key to use for returning information. + * @return Sound instance with the key's information inside of it. + */ + public function audio(key:String):Sound + { + var assetKey:String = Paths.location.audio(key); + return cache.getAudio(assetKey); + } + + /** + * Returns an BitmapData instance with `key`'s image file information inside of it. + * @param key The image key to use for returning information. + * @return BitmapData instance with the image's information inside of it. + */ + public function imageBitmap(key:String):BitmapData + { + var assetKey:String = Paths.location.image(key); + return cache.getBitmapData(assetKey); + } + + /** + * Returns an FlxGraphic instance with `key`'s image file information inside of it. + * @param key The image key to use for returning information. + * @return FlxGraphic instance with the image's information inside of it. + */ + public function imageGraphic(key:String):FlxGraphic + { + var assetKey:String = Paths.location.image(key); + return cache.getFlxGraphic(assetKey); + } + + /** + * Returns an sparrow atlas information. + * @param key The image and xml key to use for returning information. + * @return Sparrow atlas into FlxFramesCollection with content inside of the image and xml. + */ + public function sparrowAtlas(key:String):FlxFramesCollection + { + return FlxAtlasFrames.fromSparrow(imageGraphic(key), xml(key)); + } + + /** + * Returns text from a file. + * @param key The text key to use for returning the text inside. + * @return A string with text from a file. + */ + public function text(key:String):String + { + var assetKey:String = Paths.location.get(key); + return Assets.getText(assetKey); + } + + /** + * Returns an xml object that is parsed from a file. + * @param key The xml key to use for returning the data inside. + * @return A Xml object parsed from text in a file. + */ + public function xml(key:String):Xml + { + var fileText:String = text(key + '.xml'); + return Xml.parse(fileText); + } +} diff --git a/src/funkin/util/paths/PathsLocation.hx b/src/funkin/util/paths/PathsLocation.hx new file mode 100644 index 0000000..01fd251 --- /dev/null +++ b/src/funkin/util/paths/PathsLocation.hx @@ -0,0 +1,86 @@ +package funkin.util.paths; + +import openfl.Assets; + +/** + * A Paths class that helps returning strings of paths. + */ +class PathsLocation +{ + /** + * This just ensures that the paths existence is here. + * + * There is no variables that need to be initialized however u will need to call this to be able to call functions from this class otherwise its null. + */ + public function new() + { + // + } + + /** + * Returns a path with the audio extenstion at the end. + * @param key The path to get. + * @return assets/`key`.`Paths.AUDIO_EXT` + */ + public function audio(key:String):String + { + return get(key + '.' + Paths.AUDIO_EXT); + } + + /** + * Returns a path with the image extenstion at the end. + * @param key The path to get. + * @return assets/`key`.`Paths.IMAGE_EXT` + */ + public function image(key:String):String + { + return get(key + '.' + Paths.IMAGE_EXT); + } + + /** + * Returns a path with the script extenstion at the end. + * @param key The path to get. + * @return assets/`key`.`Paths.SCRIPT_EXT` + */ + public function script(key:String):String + { + return get(key + '.' + Paths.SCRIPT_EXT); + } + + /** + * Returns a path that adds `.xml` to the end. + * @param key The path to get + * @return assets/`key`.xml + */ + public function xml(key:String):String + { + return get(key + '.xml'); + } + + /** + * Returns a path. Only returns assets/ + key since theres no mod support (yet.) + * @param key The path to get. + * @return assets/`key` + */ + public function get(key:String):String + { + return 'assets/' + key; + } + + /** + * Checks to see if a file exists inside the game. + * @param key The path to check the existence on. + * @return True if the file exists inside the game. + */ + public function exists(key:String):Bool + { + var path:String = get(key); + + if (Assets.exists(path)) + { + return true; + } + + return false; + } +} From 154818ea5ec09833df2235dceccb2ad9ad8910ab Mon Sep 17 00:00:00 2001 From: CrusherNotDrip <90648119+CrusherNotDrip@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:00:02 -0500 Subject: [PATCH 3/4] Switch from Project.xml to Project.hxp --- Project.hxp | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Project.xml | 55 ---------------------- 2 files changed, 132 insertions(+), 55 deletions(-) create mode 100644 Project.hxp delete mode 100644 Project.xml diff --git a/Project.hxp b/Project.hxp new file mode 100644 index 0000000..a63e89a --- /dev/null +++ b/Project.hxp @@ -0,0 +1,132 @@ +package; + +import hxp.*; +import lime.tools.*; + +using StringTools; + +/** + * This is the main project file for TechNotDrip Engine. + * + * This works exactly like an Project.xml but in Haxe Syntax. + */ +class Project extends HXProject +{ + public function new() + { + super(); + + setupApplicationSettings(); + setupWindowSettings(); + setupPathSettings(); + setupHaxelibs(); + setupHaxeDefines(); + setupHaxeFlags(); + } + + public function setupApplicationSettings():Void + { + meta.title = 'Friday Night Funkin\': TechNotDrip Engine'; + app.file = 'TechNotDrip'; + app.main = 'Main'; + meta.version = '0.1.0'; + meta.company = 'TilNotDrip'; + app.preloader = 'flixel.system.FlxPreloader'; + app.swfVersion = 11.8; + } + + public function setupWindowSettings():Void + { + window.width = 1280; + window.height = 720; + window.background = 0; + window.hardware = true; + window.vsync = false; + + if (platformType == WEB) + { + window.resizable = true; + } + + if (platformType == DESKTOP) + { + window.orientation = LANDSCAPE; + window.fullscreen = false; + window.resizable = true; + } + + if (platformType == MOBILE) + { + window.orientation = LANDSCAPE; + window.fullscreen = false; + window.width = 0; + window.height = 0; + } + } + + public function setupPathSettings():Void + { + app.path = getBuildDirectory(); + + var excludeList:Array = []; + excludeList.push((platformType == WEB) ? 'ogg' : 'mp3'); + + // TODO: Maybe scan the entire assets folder instead like base fnf. + includeAssets("assets", "assets", ['*'], excludeList); + + icons.push(new Icon('extras/appicons/icon16.png', 16)); + icons.push(new Icon('extras/appicons/icon32.png', 32)); + icons.push(new Icon('extras/appicons/icon64.png', 64)); + icons.push(new Icon('extras/appicons/icon.png')); + + sources.push('src'); + } + + public function setupHaxelibs():Void + { + haxelibs.push(new Haxelib('lime', '8.2.1')); + haxelibs.push(new Haxelib('openfl', '9.4.0')); + haxelibs.push(new Haxelib('flixel', '5.8.0')); + haxelibs.push(new Haxelib('flixel-addons', '3.2.3')); + + if (debug) + haxelibs.push(new Haxelib('hxcpp-debug-server', '1.2.4')); + } + + public function setupHaxeDefines():Void + { + if (!debug) + haxedefs.set('FLX_NO_DEBUG', ''); + + haxedefs.set('FLX_NO_HEALTH', ''); + + if (platformType == MOBILE) + { + haxedefs.set('FLX_NO_KEYBOARD', ''); + haxedefs.set('FLX_NO_MOUSE', ''); + } + + if (platformType == DESKTOP) + { + haxedefs.set('FLX_NO_TOUCH', ''); + } + + haxedefs.set('message.reporting', 'pretty'); + + if (!debug) + haxedefs.set('NAPE_RELEASE_BUILD', ''); + } + + public function setupHaxeFlags():Void + { + haxeflags.push('-dce no'); + haxeflags.push("--macro include('funkin')"); + haxeflags.push("--macro addMetadata('@:build(funkin.macros.ZProperty.build())', 'flixel.FlxBasic')"); + } + + function getBuildDirectory():String + { + var buildDir:String = 'export/' + ((debug) ? 'debug' : 'release'); + return buildDir; + } +} diff --git a/Project.xml b/Project.xml deleted file mode 100644 index f4eb3ca..0000000 --- a/Project.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 45cd880a8291f20b32e5f5e7c30d73697db28b01 Mon Sep 17 00:00:00 2001 From: Til <89487150+TechnikTil@users.noreply.github.com> Date: Mon, 13 Jan 2025 20:24:57 -0700 Subject: [PATCH 4/4] so... why a dash? --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index bb43a96..53b7e29 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,2 +1,2 @@ -# TechNotDrip-Engine +# TechNotDrip Engine fnf engine