Compare commits

...
406 Commits
Author SHA1 Message Date
Hundrec b2215482c2 Bump docs to 0.8.7
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows, windows) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (html5) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (linux) (push) Canceled after 0s
2026-08-23 10:15:12 +08:00
Hundrec 59dae0f601 Bump version to 0.8.7 2026-08-23 10:15:12 +08:00
Hundrec 4d70e13629 Changelog for 0.8.7 2026-08-23 10:15:08 +08:00
Hundrec 83bc17970a Changelog platform formatting for 0.8.6 2026-08-23 10:08:03 +08:00
EricandHundrec 72078e4fec Add note hitsounds link to rejected features 2026-08-23 10:08:02 +08:00
EliteMasterEricandHundrec f5bd835496 Fix pull request label actions overriding each other 2026-08-23 10:08:02 +08:00
Karim AkraandHundrec f2fe179109 playest menu camera reset 2026-08-23 10:08:02 +08:00
MoonDroid b1d91ab5d8 FIx compression data + TouchUtil crash 2026-08-22 12:27:42 +07:00
MAJigsaw77andMoonDroid f09e89e324 Update lime and openfl 2026-08-21 20:59:06 +07:00
MoonDroidandKarim Akra 3c8f7c08ec Rewrite the FNFC java copy function for android
The old one was randomly throwing some crashes such as
* OutOfMemory
* NegativeArraySizeException
* IllegalStateException

This new one should fix those!

Co-Authored-By: Karim Akra <144803230+KarimAkra@users.noreply.github.com>
2026-08-21 14:46:57 +07:00
Hundrec ee9d492bec Bump docs and templates to 0.8.6
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows, windows) (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (html5) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (linux) (push) Canceled after 0s
Including info about new public playtest builds
2026-08-09 06:22:48 +08:00
Hundrec afc251cde7 Bump version to 0.8.6 2026-08-09 06:14:05 +08:00
HundrecandAbnormal b7615eb8dd Changelog for 0.8.6
Co-Authored-By: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2026-08-09 06:13:15 +08:00
Hundrec d2ead0ce4c Bump assets for health icon tweaks 2026-08-09 03:28:25 +08:00
HundrecandHyper_ 22297ee6ed Bump polymod again
Co-Authored-By: Hyper_ <40342021+NotHyper-474@users.noreply.github.com>
2026-08-09 03:10:50 +08:00
Hundrec 353473a980 Replace instances of a Contributor in Changelog
VirtuGuy -> realvirtu
2026-08-08 04:24:14 +08:00
Hundrec 9e39b1bfdb Bump CharacterData version to 1.0.2
To account for the new shouldBop property added a while back
2026-08-08 04:05:53 +08:00
Hundrec ab884e1362 Bump polymod 2026-08-08 03:55:21 +08:00
EliteMasterEricandHundrec 86c6f95cae Rewrite the CompiledClassList macro to use a resource 2026-08-08 02:46:40 +08:00
MAJigsaw77andHundrec 7a3422bda6 Bump lime 2026-08-08 02:46:37 +08:00
MAJigsaw77andHundrec fdc73624cf Update libs 2026-08-08 02:45:21 +08:00
MAJigsaw77andHundrec ae5654322c Clean some stuff in ApplicationMain 2026-08-08 02:44:45 +08:00
MAJigsaw77andHundrec 1cfe8b77a4 Update libs 2026-08-08 02:44:45 +08:00
MAJigsaw77andHundrec 15bf019c2d Disable formatting on templates 2026-08-08 02:44:37 +08:00
MAJigsaw77andHundrec d47ba73464 Bump flixel 2026-08-02 21:21:28 +08:00
MAJigsaw77andHundrec 716aeef72d Update libs 2026-08-02 21:20:38 +08:00
MAJigsaw77andHundrec c48a20a03c Add @:unreflective to all mobile utils 2026-08-02 21:19:53 +08:00
MAJigsaw77andHundrec 7b2cd882d3 Backlist all mobile utils 2026-08-02 21:19:53 +08:00
MAJigsaw77andHundrec 954810903c Fix -framework ignored creating static libraries warnings on iOS 2026-08-02 21:16:32 +08:00
MAJigsaw77andHundrec 7f22a34d7e Update libs 2026-08-02 21:15:57 +08:00
MAJigsaw77andHundrec bf6b8eecb8 The death of hashlink 2026-08-02 21:14:21 +08:00
MAJigsaw77andHundrec 77d829e888 Update openfl 2026-07-26 22:57:46 +08:00
FuroandHundrec f2633bb335 Cleanup the extension blacklisting process 2026-07-25 22:41:46 +08:00
nykwonoandHundrec de36ca87e8 Apply new input system changes to offset menu 2026-07-25 22:41:46 +08:00
MAJigsaw77 9749402714 Fix StageEditor compile on Mobile 2026-07-25 13:28:03 +03:00
MAJigsaw77andHundrec 9e08f9d0bc A bunch of iOS improvements 2026-07-25 17:39:02 +08:00
KoloandHundrec e8d91e0f1f implement texture atlas support for the stage editor 2026-07-24 04:01:50 +08:00
Hyper_andHundrec 87fc681c56 Remove display check from FlxMacro
This might solve an issue where Haxe complains that "Module funkin.util.macro.FlxMacro does not define type FlxMacro" during completion.
These checks don't work like you'd expect anyway, and the Haxe developers advise you not to use it outside of macros.
2026-07-24 03:32:39 +08:00
Hyper_andHundrec 709280c9a8 Fix incorrect checks for display during macro context 2026-07-24 03:32:39 +08:00
Daniel VictorandHundrec 20d3e4fb62 Remove the offset hack on my new DropShadowShader 2026-07-24 03:32:39 +08:00
Infinite-SUDO67andHundrec 05c81bc622 Fix Chart Editor event dropdown crash 2026-07-24 03:32:39 +08:00
kiry vajiravuthandHundrec b42cd4b6e1 charteditor wont crash now 2026-07-24 03:32:39 +08:00
kiry vajiravuthandHundrec 8bbd7bc466 even more typo fixes 2026-07-24 00:51:56 +08:00
MAJigsaw77andHundrec 347df2cdea Make the debug display be added to the game itself, not the parent 2026-07-24 00:12:45 +08:00
Infinite-SUDO67andHundrec 4ff781bd3a Adjust Mobile compiling guide docs 2026-07-24 00:12:45 +08:00
MAJigsaw77andHundrec 423d80059c Update extension-admob 2026-07-24 00:12:45 +08:00
MAJigsaw77andHundrec 7bbd0e882b Update lime 2026-07-24 00:12:01 +08:00
MAJigsaw77andHundrec f9d8203238 Implement extension-agesignals 2026-07-24 00:11:45 +08:00
MAJigsaw77andHundrec a18bab932f Update lime and openfl 2026-07-24 00:10:55 +08:00
MAJigsaw77andHundrec ade57d9bb7 Simplify registering prims by doing it in ApplicationMain 2026-07-20 12:31:25 +08:00
LegendandHundrec 347f7cfecb fix(freeplay): song preview not updating after rank animation finishes (#6432) 2026-07-04 21:23:38 +08:00
Ahmed7p39andHundrec 18f5e25496 avoid increasing volume on focus if it was 0 2026-07-04 16:49:47 +08:00
MAJigsaw77andHundrec 0001be960d Update openfl and lime 2026-07-03 16:42:18 +08:00
Cameron TaylorandHundrec 38c8bc94ca bump hmm for flixel: fix for pressing TAB not focusing the flixel console 2026-07-02 05:47:19 +08:00
realvirtuandHundrec d60fe0726f Fix ghost tapping when holding multiple keys 2026-07-01 00:51:28 +08:00
JVN-PixelsandHundrec 2e4115a33c Use the window width rather than the background width 2026-06-30 12:34:31 +08:00
LasercarandHundrec bdf51dcd43 Nest the text squash timers 2026-06-23 22:58:29 +08:00
VICKandHundrec 01d4242392 fix: also clear chart-editor HaxeUI focus on right-click / scroll wheel 2026-06-22 23:52:16 +08:00
VICKandHundrec 86f2f44b46 fix: Clear HaxeUI focus when chart editor toolbox is opened or closed 2026-06-22 23:52:16 +08:00
Hyper_andHundrec ac102396d7 Fix improper fallback to default notestyle on PlayState 2026-06-22 23:52:16 +08:00
AbnormalPoofandHundrec 663e7b307c fix: Fix Thorns crashing when exiting on HTML5 2026-06-22 13:48:50 +08:00
Hundrec afd27bf183 Bump assets for Actions update 2026-06-22 13:27:21 +08:00
LegendandHundrec 90712bf1e6 perf(background-process): improve onExit cleanup / resource disposal (#7235)
- The game now disposes of cached audio / textures, alongside `openfl.Assets` to ensure a proper resource cleanup.
  * Disposing of cached audio / textures upon exiting the game will now be logged to the terminal.
- Set `onExit` handler priority to 99 to ensure cleanup runs after mod exit callbacks.
- Removed HTML5 builds from getting background processed to prevent compilation errors.
- Removed `hxvlc` disposal from background processing.
2026-06-22 12:41:32 +08:00
requazarandHundrec 2a4968115f Fix PlayStatePlaylist using incorrect script variations 2026-06-22 12:41:27 +08:00
kiry vajiravuthandHundrec 395915cb31 probabbly 2026-06-22 12:41:21 +08:00
TechnikTilandHundrec 5de97f420c Remove unused code in PlayState.popUpScore
Signed-off-by: TechnikTil <techniktil@tilnotdrip.org>
2026-06-22 12:41:15 +08:00
zxcksharks (formerly xenkap)andHundrec e51ae1098a Add Funkin' version as compilation flag
for polymod!!!!
2026-06-22 12:41:08 +08:00
zxcksharks (formerly xenkap)andHundrec da1e8e4664 Add a PlayState check to initHealthIcon() and playAnimation()
This allows stages to be fully utilized outside of PlayState.
2026-06-22 12:41:01 +08:00
Ahmed7p39andHundrec 1d82546c29 Update event descriptions to clarify cancelable status 2026-06-22 12:40:47 +08:00
JVN-PixelsandHundrec f42dcecab6 Artistic Expression + Click Sounds in the Animation Editor 2026-06-22 12:40:19 +08:00
Vinegar (Flynn Waiver)andHundrec fdf6a3a2c6 Remove safeMode definition
Removed safeMode Haxe definition from project.hxp

It was not clear on what it was for, and it wasn't referenced anywhere. I've not seen any mods make any use cases of it either.
2026-06-22 12:40:05 +08:00
RafiandHundrec e60cb6bfc5 [GITHUB] Bump some actions dependencies to use Node 24 2026-06-21 21:09:08 +08:00
sector-aandHundrec 4de27f4231 Fix character script errors in chart editor 2026-06-21 12:50:55 +08:00
MAJigsaw77andHundrec 8f952acf91 Clean the ASTC textures when using the clean flag 2026-06-21 12:49:45 +08:00
MAJigsaw77andHundrec 8b8c1cc489 Add Target prefix to the Platform Type and Architecture prints 2026-06-21 12:49:45 +08:00
MAJigsaw77andHundrec 41e10f5f21 Move displayTarget after flair 2026-06-21 12:49:45 +08:00
MAJigsaw77andHundrec f18734f0b4 Update lime to fix the install command 2026-06-21 12:49:45 +08:00
MAJigsaw77andHundrec 6949bd97e4 Dont trace anything when using the run and install commands 2026-06-21 12:49:30 +08:00
MAJigsaw77andHundrec 5ed1ef404b Update astc-compressor 2026-06-21 12:49:30 +08:00
MAJigsaw77andHundrec aa2d6db7e0 Add isRun and isInstall 2026-06-21 12:49:30 +08:00
MAJigsaw77andHundrec 801074735e Make isCleanCommand and isCleanFlag 2026-06-21 12:49:30 +08:00
MAJigsaw77andHundrec fe10c0dad6 Dont check libraries or delete assets on the clean command 2026-06-21 12:49:30 +08:00
MAJigsaw77andHundrec 0207197644 Patch run command on Android and also move the config from iOS to configureApp 2026-06-21 12:49:30 +08:00
MAJigsaw77andHundrec 9730ee1c9e Make run and install commands run faster 2026-06-21 12:49:29 +08:00
AbnormalPoofandHundrec 093eb708ed Bump newgrounds to fix a weird JSON parsing error 2026-06-21 12:42:39 +08:00
MAJigsaw77andHundrec da1933397a Update hxvlc 2026-06-17 17:10:36 +08:00
HundrecandAbnormal 47110a34b0 Bump flixel to the latest commit
Co-Authored-By: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2026-06-17 17:10:27 +08:00
Hyper_andHundrec 4f96d2c070 fix: Sort null elements by zIndex correctly 2026-06-17 17:08:26 +08:00
7oltanandHundrec bd23b5c12f make discord-rpc use characters icon data 2026-06-17 17:07:22 +08:00
MAJigsaw77andHundrec 539048b57b Bump lime and openfl 2026-06-17 17:07:15 +08:00
EliteMasterEricandHundrec 7102cda49d Rewrite some of the formatting rules to improve automatic line wrapping. 2026-06-17 17:02:01 +08:00
Cameron TaylorandHundrec 7bdcd59797 only log in preloader when percent or loading state changes 2026-06-17 17:00:18 +08:00
Cameron TaylorandHundrec 957a339676 round the numbers in preloader 2026-06-17 17:00:18 +08:00
AbnormalPoofandHundrec 5ee192439b Update polymod to the latest commit 2026-06-17 16:59:01 +08:00
MrMaderaandHundrec c239639ac7 Fix controls menu crash when changing a gamepad bind without a controller connected 2026-05-24 00:38:45 -06:00
ComedyLostandHundrec 1762affd7a fix potential freeplay crash when no music playing 2026-05-24 00:38:37 -06:00
Hyper_andHundrec a62e1c08ab feat: (and fix) Reusable and stutter-proof Timer Sequences 2026-05-24 00:38:07 -06:00
KoloandHundrec 0b6198f23a fix getting a new rank making the clip size incorrect 2026-05-24 00:38:07 -06:00
MAJigsaw77andHundrec eff4bcfdf3 Bump FlxPartialSound, openfl and lime 2026-05-24 00:35:06 -06:00
MAJigsaw77andHundrec f5f2fb0fc8 Bump lime and openfl 2026-05-24 00:34:55 -06:00
Kade-gtihubandHundrec a86ff05f69 general fixes rq 2026-05-24 00:34:16 -06:00
kade-githubandHundrec 209cdcff2a move resources to funkin.me 2026-05-24 00:34:16 -06:00
kade-githubandHundrec d25346ee39 theme branding stuff 2026-05-24 00:34:16 -06:00
kade-githubandHundrec 16376c0897 General Dox Setup/Implementation 2026-05-24 00:34:16 -06:00
MrMaderaandHundrec 6fe2089bea Fix controls menu crash when unplugging a gamepad 2026-05-19 17:45:24 -06:00
JVN-PixelsandHundrec 27fd960fb3 Fix broken rectangle size in Lag Adjustment Menu 2026-05-19 17:45:24 -06:00
LegendandHundrec adbe5ba7cb fix(options): prevent crash when hot-reloading in the lag adjustments menu (#7285)
- Added a null check for `FlxG.sound.music` before calling `fadeOut()`.
- Created `switchToOffsets()` to avoid duplicating the original code.
2026-05-19 17:45:24 -06:00
ImVeryBadandHundrec 2bb5397c2b Fix health icon angle lerping too quickly and use a Constant for the half life to allow customizability by modders. 2026-05-19 17:45:24 -06:00
ImVeryBadandHundrec 1fce75feb9 Ignore health icon offsets in Chart Editor to prevent out-of-bounds rendering. 2026-05-19 17:45:24 -06:00
ImVeryBadandHundrec 83bfccc101 Disable page navigation while Save Data prompts are open in Options. 2026-05-19 17:45:24 -06:00
VirtuGuyandHundrec f0a5188cb1 Fix hold notes not always having a cover 2026-05-19 17:45:24 -06:00
AbnormalPoofandHundrec 28cbf3767a Add discordRPCImage to Album and Song data 2026-05-19 17:45:24 -06:00
AbnormalPoofandHundrec e7cd38ee85 Disable RTT on GF Christmas on Web 2026-05-18 16:09:36 -06:00
VirtuGuyandHundrec c1be637101 Fix song restart bug 2026-05-18 15:45:35 -06:00
ImVeryBadandHundrec 6ab6bc62e7 Remove the popup error when a directory in mods has no metadata. 2026-05-18 12:17:59 -06:00
MAJigsaw77andHundrec 8592b44c72 Update hxcpp, lime and openfl 2026-05-18 12:17:59 -06:00
Nebula S. NovaandHundrec 01bce88823 Fix my stupid 2026-05-15 01:11:58 -06:00
Nebula S. NovaandHundrec 6aa8bc3ce9 [BUGFIX] Fix file naming for metadata and chart saves from difficulty toolbox. 2026-05-15 01:11:58 -06:00
LusciousandHundrec 840c0431ec Update AngleMask.hx 2026-05-15 01:11:58 -06:00
Karim AkraandHundrec 4ca9a21ec6 Use GCKeyboard instead of UITextInputContext to check for ios keyboard 2026-05-15 01:11:15 -06:00
Karim AkraandHundrec fec0f66029 Fixed gamepad detection for mobile 2026-05-15 01:11:15 -06:00
Karim AkraandHundrec 30efedb930 Fix keyboard detection for iOS 2026-05-15 01:11:15 -06:00
Karim AkraandHundrec 32c507999a Bump lime to fix the iOS keyboard freeze 2026-05-15 01:11:15 -06:00
Kade-gtihubandHundrec 9f6ea20f3e remove accurate width/height and fix calculations 2026-05-15 01:11:01 -06:00
Hundrec 5b892c8814 Batch of assets bug fixes 2026-05-09 17:33:41 -06:00
ComedyLostandHundrec 504b22126b Fix multiple wether typos 2026-05-09 04:40:42 -06:00
SuperEricandHundrec 67aec2464b Fix typo in comment about songPosition issues 2026-05-09 04:40:42 -06:00
Hundrec c99d4438db Bump assets for typo fixes 2026-05-09 04:40:37 -06:00
Honton129andHundrec ac37968f73 Add `Edit Notes` to the Chart Editor Selection Context Menu 2026-05-09 04:40:11 -06:00
charlesisfelineandHundrec 3752232e3a Blacklist haxe.Http
speedrunning a blacklist pr before kade does it heheheheha
2026-05-09 04:39:49 -06:00
MAJigsaw77andHundrec 7d5fa627cb Add support back for some libs on iOS Simulator 2026-05-09 04:39:37 -06:00
MAJigsaw77andHundrec 4db9d7718c Bump lime and flixel 2026-05-09 04:39:37 -06:00
Kade-gtihubandHundrec cf3e2e05bf Add ClipRect functionality to FunkinGroup 2026-05-09 04:39:16 -06:00
LasercarandHundrec b97012a10d Note input delay doubled when note is hit late 2026-05-05 23:00:45 -06:00
MrMaderaandHundrec e0af5e282e Fix some actions not updating the Freeplay hint properly 2026-05-04 04:14:26 -06:00
Ahmed7p39andHundrec d6ce9e2dff Update pause and resume methods for Conversation 2026-05-04 04:14:26 -06:00
Ahmed7p39andHundrec c0a483f003 Add pause and resume functions for dialogue outro 2026-05-04 04:14:26 -06:00
ComedyLostandHundrec 179d8294e4 Set variables correctly for texture swap shader 2026-05-04 04:14:26 -06:00
EliteMasterEricandHundrec c8f2056823 Disable the MagicNumber rule 2026-05-04 04:14:25 -06:00
EliteMasterEricandHundrec 89e05e200e Disable CodeSimilarity rule 2026-05-04 04:14:25 -06:00
475c7cbf80 Optimize Adjust Color
Co-Authored-By: iLauncherDev <93844852+iLauncherDev@users.noreply.github.com>
2026-05-04 04:13:09 -06:00
AbnormalPoofandHundrec 92331dd8bf Remove 2 unused blend mode shaders 2026-05-04 04:13:05 -06:00
AbnormalPoofandHundrec eba3c2b2b1 Small cleanup 2026-05-04 04:12:59 -06:00
Daniel VictorandHundrec 0e82016232 Rewrite DropShadowShader a little for performance improvement 2026-05-04 04:12:59 -06:00
MAJigsaw77andHundrec 0969465139 Bump lime to fix a couple of things on MacOS 2026-05-04 04:12:59 -06:00
VirtuGuyandHundrec 0e967ebefb Fix camera movement when pausing 2026-05-02 03:00:34 -06:00
MAJigsaw77andHundrec 8730812cf5 Use deltaWheel where possible for more accurate scrolling 2026-05-02 03:00:13 -06:00
MAJigsaw77andHundrec d7fc2ebff6 Bump flixel and openfl 2026-05-02 02:57:48 -06:00
EliteMasterEricandHundrec e4ed5b9cc8 Update polymod to latest experimental 2026-04-30 23:27:00 -06:00
Hyper_andHundrec 7f8a1ab6d0 Chart Editor: Only affect playback rate if "Use Editor Audio Settings" is enabled 2026-04-30 23:27:00 -06:00
EliteMasterEricandHundrec 5e7aaf6894 Fix an issue with HaxeUI and the compilation server. 2026-04-30 23:27:00 -06:00
MAJigsaw77andHundrec 4d501f05c3 Update lime 2026-04-30 23:27:00 -06:00
ImVeryBadandHundrec a25f3e5fb8 Fix runtime errors due to tempVocals being nullable 2026-04-30 23:27:00 -06:00
eb4d9e9323 Patch unicodes not working properly on Windows
Co-Authored-By: Karim Akra <144803230+KarimAkra@users.noreply.github.com>
2026-04-30 23:27:00 -06:00
MAJigsaw77andHundrec 970a29cd5f Bump lime and hxcpp 2026-04-30 23:27:00 -06:00
8e20209391 Update json2object to include a stable and better-formatted Dynamic object writer.
Co-Authored-By: TechnikTil <TechnikTil@users.noreply.github.com>
2026-04-30 23:26:58 -06:00
MAJigsaw77andHundrec 05b703e93d Bump lime, openfl and flixel 2026-04-29 02:07:14 -06:00
Hundrec a079593fdc Adjust some wording 2026-04-27 16:14:02 -06:00
Honton129andHundrec c08a6a86a0 [CHORE] Improve DialogueBoxData.hx Documentation 2026-04-27 16:14:02 -06:00
JVN-PixelsandHundrec dbda7e02ca Fix a few typos 2026-04-27 16:14:02 -06:00
TechnikTilandHundrec 20fc36ea59 Use Constants for time conversion equations
Signed-off-by: TechnikTil <techniktil@tilnotdrip.org>
2026-04-27 16:13:14 -06:00
Hyper_andHundrec 523b9c16eb fix: Fix midpoint not properly offsetting Nametag position 2026-04-27 16:11:27 -06:00
Ahmed7p39andHundrec b75add7c59 Use fullyQualifiedName for scripted class identification to support packages 2026-04-27 16:11:27 -06:00
Kade-gtihubandHundrec fabddc93ab More PlayState null checks 2026-04-20 19:38:33 -06:00
EliteMasterEricandHundrec 4abbd9c15c Update the docs regarding hitzones. 2026-04-20 19:04:38 -06:00
HundrecandTechnikTil a599c6513b Re-export all charts using updated json2object
Co-Authored-By: TechnikTil <techniktil@tilnotdrip.org>
2026-04-18 21:27:21 -06:00
MAJigsaw77andHundrec 05f9764236 Update extension-admob and handle the mediations config internally 2026-04-17 22:49:02 -06:00
MAJigsaw77andHundrec 5824529c12 Fix FileDialogs from not following the last dir it opened 2026-04-17 19:30:23 -06:00
Karim AkraandHundrec 54a15c7045 Set the lime extension lime.projectFile to project.hxp in the vscode settings 2026-04-17 19:30:23 -06:00
sector-aandHundrec 2136f6f5c3 A small nametag refactor 2026-04-17 19:30:23 -06:00
MAJigsaw77andHundrec b50dc69e05 Update lime again to patch a linux error 2026-04-17 19:30:23 -06:00
MAJigsaw77andHundrec fe45b409ef Update lime 2026-04-17 19:30:23 -06:00
MAJigsaw77andHundrec 9d45aeb6ce Pause audio when an Ad runs on Android aswell 2026-04-17 19:30:23 -06:00
MAJigsaw77andHundrec 778bbfd0f5 Update lime and openfl 2026-04-17 19:30:23 -06:00
MAJigsaw77andHundrec aac8f598d9 Update flixel and flixel-addons 2026-04-17 19:30:23 -06:00
EliteMasterEricandHundrec bde533def5 Add a "Chart Saved" notification to the menu option (previously only showed when pressing Ctrl-S) 2026-04-17 19:30:23 -06:00
Hundrec 5eaa248451 Fix incorrect line breaks 2026-04-17 19:30:23 -06:00
MAJigsaw77andHundrec 276e8bb248 Adjust the Path and Development Build ANSI colors in project.hxp 2026-04-17 19:30:23 -06:00
MAJigsaw77andHundrec ec4fef6424 Update lime and hxcpp 2026-04-17 19:30:23 -06:00
AbnormalPoofandHundrec 567aa28905 Bump openfl to fix DARKEN being completely broken on Windows 2026-04-09 14:26:59 -06:00
AbnormalPoofandHundrec e15d39d102 Fix the blend shader not working at all under render texture 2026-04-09 14:26:59 -06:00
MAJigsaw77andHundrec 04e120dfc9 Add svg to hmm. 2026-04-09 14:26:59 -06:00
MAJigsaw77andHundrec 9d12646452 Update lime
Update hmm.json
2026-04-09 14:26:57 -06:00
MAJigsaw77andHundrec ec59410b68 Remove this leftover to patch compile. 2026-04-06 04:18:10 -06:00
MAJigsaw77andHundrec 5ecccbf7fc Add tink_core to hmm. 2026-04-06 04:18:10 -06:00
sector-aandHundrec e17a0d047a Update the presence after enabling the RPC in Preferences 2026-04-06 04:18:10 -06:00
sector-aandHundrec afeb263ae1 Implement a way to hide song's info for Discord RPC 2026-04-06 04:18:10 -06:00
sector-aandHundrec 7af0a69584 Implement DiscordRPC preference 2026-04-06 04:18:10 -06:00
MAJigsaw77andHundrec 378001f8ea Adjustments for the Touch here to play 2026-04-06 04:18:10 -06:00
EliteMasterEricandHundrec 824bb306f9 Even more warnings cleaned up. 2026-04-06 04:18:10 -06:00
EliteMasterEricandHundrec 496cffdf99 Don't require field doc comments for enums (they're often self-explanatory) 2026-04-06 04:18:10 -06:00
EliteMasterEricandHundrec d344741f85 Tweaks to for loops 2026-04-06 04:18:10 -06:00
EliteMasterEricandHundrec 9f695a28f5 Tweak the rules to allow single-line for loops 2026-04-06 04:18:10 -06:00
EliteMasterEricandHundrec 5b7e567eb2 Rewrite string literals to use single quotes 2026-04-06 04:18:10 -06:00
EliteMasterEricandHundrec 93ccad566c Do a whole bunch of code style rewrites across a lot of classes. Still more to do! 2026-04-06 04:18:10 -06:00
EliteMasterEricandHundrec be68ebb920 Standardize doc style comments 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec b83672caab Code style fixes for funkin.api 2026-04-06 04:18:09 -06:00
HundrecandEric 56dabfd5c9 Format .hx files
Co-Authored-By: Eric <4635334+EliteMasterEric@users.noreply.github.com>
2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 71d7d929b4 Only enforce the LongNumberCheck for values over 10_000 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 866055018f Move override to the front of the modifier order 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec e4d12d2a5a Redo the rules for LongNumber checks (update your checkstyle extension!) 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec c71b06c9f2 Update doc comment style to require two stars to open and one star to close (like JavaDocs) 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 72d3d4546f Redo the NeedBraces rule to require braces on if statements with else blocks. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 17cfd2e2f8 Add a rule forbidding long numbers without separators. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 71d7fe0cf6 Re-rework rules for local variable names now that we can filter by FINAL/NOTFINAL 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 1c46c98c84 Re-rework rules for constant names now that we can filter by FINAL/NOTFINAL 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 02c49ba645 Disable the use of nested ternary operators. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec a2cd0ef4ca Use arrow functions for non-member functions (i.e. all inline functions) 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 64b99fedcc Enforce not using "== false" in code. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec f7d6ce4a98 Fix a vague comment. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 8b3372cdab The new TrailingCommas rule doesn't support forcing trailing commas off... 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec f460b604e2 Require parenthesis around the switch condition. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec f1aade4b58 Force a newline after type metadata 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec ccc2383402 Change policy for some rules that were set to "keep existing" 2026-04-06 04:18:09 -06:00
EricandHundrec 3250f28217 Enable style rule for modifier order 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 544a531434 Fix an issue where macro reification would request a newline for the curly braces. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 222eee19bf Modify naming requirements for variables to be less strict. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 47830ffaf3 Fix an issue where enum abstracts would display a message that the type wasn't documented, even if it was. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec b582826fba Update rules for line wrapping on maps. 2026-04-06 04:18:09 -06:00
EliteMasterEricandHundrec 5d14e4f667 Update rules for line wrapping on arrays. 2026-04-06 04:18:08 -06:00
MAJigsaw77andHundrec 97b09ba966 Update hxcpp 2026-04-06 04:18:08 -06:00
ember anaandHundrec e72b67df70 fix: html5 and linux ci builds ^-^ (#2455)
* fix: itch.io upload failing

* feat: the runner now rebuilds lime ndlls (and caches that build) on the fly

* chore: update all the actions used to latest

* chore: update build dependencies to latest

* chore: cleanup build outputs
2026-04-06 04:18:08 -06:00
Hundrec c382cee930 Add a contributor to 0.7.4 New Contributors 2026-04-06 04:18:08 -06:00
AbnormalandHundrec d3ad9d9311 Revert "Rework AtlasText to use FunkinGroup"
This reverts commit 2857fe14122927c2732a858862d7db9b8ff765a4.
2026-04-06 04:18:08 -06:00
LegendandHundrec 0b086689e8 fix: stop resultsMusic when hot-reloading in the chart editor's resultsScreen 2026-04-06 04:18:08 -06:00
ImVeryBadandHundrec cc91faaccc Add shouldBop in HealthIconData to allow any type of icon to bop. 2026-04-06 04:18:08 -06:00
ImVeryBadandHundrec 790e3fb097 Add Albums & Sticker Packs to Chart Editor metadata dialogues 2026-04-06 04:18:08 -06:00
EliteMasterEricandHundrec 982e2b72c1 Fix compilation issue due to currentStage being nullable 2026-04-06 04:18:08 -06:00
LasercarandHundrec e0a6253310 unmute character vocals for animations 2026-04-06 04:18:08 -06:00
EliteMasterEricandHundrec 134984ea0b Fix the return value being wrong. 2026-04-06 04:18:08 -06:00
KoloandHundrec 19610c4309 dont dispatch conductor events if substate is active 2026-04-06 04:18:08 -06:00
03f6cc1552 Implement screenshots on html5
Co-Authored-By: Cameron Taylor <cameron.taylor.ninja@gmail.com>
2026-04-06 04:18:08 -06:00
ImVeryBadandHundrec d6c6d75a45 Fix requestScores in the wrapper to be static and correct trace typo in Leaderboards.hx 2026-04-06 04:18:08 -06:00
ImVeryBadandHundrec ea4f0a4d28 Remove unused fields 2026-04-06 04:18:08 -06:00
FuroandHundrec 66d191d431 Fix Reflect Util by Adding Polymod Blacklist Protection 2026-04-06 04:18:08 -06:00
AbnormalPoofandHundrec bd99345a3c Adjust the file drop comment 2026-04-06 04:18:08 -06:00
AbnormalPoofandHundrec cfdbbb81d4 Re-enable file drop on macOS 2026-04-06 04:18:08 -06:00
EricandHundrec 7f7197f216 Update format haxelib 2026-04-06 04:18:08 -06:00
MAJigsaw77andHundrec 2f949d4af0 Update libs refs 2026-04-06 04:18:08 -06:00
AbnormalPoofandHundrec bc06e7fcc1 Rework AtlasText to use FunkinGroup 2026-04-06 04:18:08 -06:00
MAJigsaw77andHundrec a01b4ce4af Improve file dialogs 2026-04-06 04:18:08 -06:00
Hundrec 965d2053cf Bump assets 2026-04-06 04:18:08 -06:00
Hundrec bdedc0aad2 Bump docs and templates to 0.8.5
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows, windows) (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (html5) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (linux) (push) Canceled after 0s
2026-04-05 13:53:37 -06:00
Hundrec b23b008861 Bump version to 0.8.5 2026-04-05 13:53:37 -06:00
Hundrec acbfa69d48 Changelog for 0.8.5 - Android exclusive fix 2026-04-05 13:53:37 -06:00
Hundrec 648ca8fd13 Bump lime for more fixes 2026-04-05 13:53:35 -06:00
Hundrec 90eabf0b38 Bump docs and templates to 0.8.4
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows, windows) (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (html5) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (linux) (push) Canceled after 0s
2026-03-25 16:19:29 -06:00
Hundrec b3959a5935 Bump version to 0.8.4 2026-03-22 00:02:55 -06:00
HundrecandAbnormal cdca3bf307 Changelog for 0.8.4
Co-Authored-By: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2026-03-22 00:01:19 -06:00
Karim AkraandHundrec e491c5e841 [CHORE] rename mobile FNFCUtil classes for a cleaner structure 2026-03-21 16:01:13 -06:00
Karim AkraandHundrec f9b125e44a [FIX] Bump lime to fix FNFC loading on iOS 2026-03-21 16:01:13 -06:00
VirtuGuyandHundrec 1ceb4fad1a Fix ingame cutscenes crashing on mobile 2026-03-21 06:40:41 -06:00
Hyper_andHundrec 21fc59c997 Fix TextureSwap not loading ASTC assets properly 2026-03-21 06:40:33 -06:00
EliteMasterEricandHundrec 0cbde53f86 Update default value just in case resetEvents(events) doesn't get called. 2026-03-21 04:57:45 -06:00
VirtuGuyandHundrec 5119cf1b72 Fix songs crashing 2026-03-21 04:57:45 -06:00
927f3fc300 Use an optional argument for event querying
Co-Authored-By: Eric <4635334+EliteMasterEric@users.noreply.github.com>
2026-03-20 16:54:27 -06:00
EliteMasterEricandHundrec d1e4a17f46 Add null checks to some scripts 2026-03-20 16:52:53 -06:00
ec868f8ef5 Fix HTML5 not compiling due to blacklisted Polymod field
Co-Authored-By: Kolo <67389779+KoloInDaCrib@users.noreply.github.com>
Co-Authored-By: Keoiki <55053690+Keoiki@users.noreply.github.com>
2026-03-20 04:19:23 -06:00
MAJigsaw77andHundrec 1e0a238463 Patch extension-admob setup command so theres no unexpected behaviour 2026-03-20 03:58:18 -06:00
Hundrec e07e59a288 Undo No Animation hold timer change
It was making animations behave differently after a change to hold timers
2026-03-19 23:29:42 -06:00
ADA-FunniandHundrec d6410d5e42 Fallback for old song metadata files causing the song preview to go mute 2026-03-19 23:29:42 -06:00
TrayfellowandHundrec 5974c1a482 Fix freeplay percentage not fully exiting out if it has 3 digits 2026-03-19 21:02:20 -06:00
KoloandHundrec ffdcbdbf21 optimize the script event dispatching 2026-03-19 21:02:20 -06:00
KoloandHundrec 3b27ec5b66 optimization: potentially optimize how events are queried 2026-03-19 21:02:20 -06:00
FuroandHundrec 56a56dbfaa Include lime and openfl for modding 2026-03-19 20:00:18 -06:00
EliteMasterEricandHundrec 537bd5dd83 Add a few more items to the blacklist 2026-03-19 20:00:18 -06:00
charlesisfelineandHundrec b0fd471f8a Blacklist 'readObject` from scripts 2026-03-19 20:00:18 -06:00
ImVeryBadandHundrec 3633df3fdc Add makeVarArgs to ReflectUtil.hx 2026-03-19 20:00:18 -06:00
VirtuGuyandHundrec e6234397f5 Fix camera movement when paused 2026-03-19 19:34:04 -06:00
MAJigsaw77andHundrec 68ce5ce90b Update lime 2026-03-19 18:50:43 -06:00
MAJigsaw77andHundrec a6066f9905 Update flixel-addons 2026-03-19 04:21:37 -06:00
KolzeandHundrec 75506f71a9 Fix spirit trail being fps-dependent 2026-03-19 04:21:25 -06:00
RaltyandHundrec c4b5462a5a Remove duplicated code in project.hxp 2026-03-19 03:15:35 -06:00
MAJigsaw77andHundrec 47d4d77c86 Update hxcpp 2026-03-19 02:50:50 -06:00
MAJigsaw77andHundrec acf17f6165 Properly adjust the debug display math based of the supported mem usages 2026-03-19 02:50:50 -06:00
MAJigsaw77andHundrec 2db26070c6 Properly delete the assets folder on hl across all desktop targets 2026-03-19 02:50:50 -06:00
MAJigsaw77andHundrec e0f9c7336b Update libs refs 2026-03-19 02:50:50 -06:00
AbnormalPoofandHundrec a28a28ae4c Clamp the DPI scale to 1 in the blend shader 2026-03-18 00:26:45 -06:00
Hundrec 7160f748eb Tweak dropdown width 2026-03-17 23:55:20 -06:00
sector-aandHundrec c8e60bed34 Add additional adjustments in the ZoomCamerasong event for widescreen 2026-03-17 23:55:19 -06:00
sector-aandHundrec 11c826daa6 Resize ENUM dropdowns to make them fit in the frames 2026-03-17 23:55:03 -06:00
sector-aandHundrec 6c887b4632 Put some of least used event params under Advanced frame. 2026-03-17 23:55:03 -06:00
MAJigsaw77andHundrec ecfb897dae Remove useless prints 2026-03-17 22:59:20 -06:00
AbnormalPoofandHundrec 56d5767004 Fix HashLink not clearing assets on macOS 2026-03-17 22:59:12 -06:00
MAJigsaw77andHundrec 7d3bfa32ca Run clearAssets only on non display 2026-03-17 22:59:04 -06:00
KolzeandHundrec 348647f486 Fix global offset changing speed 2026-03-17 22:58:00 -06:00
ExcodeandHundrec 48ed659800 Update LevelData.hx 2026-03-17 22:57:43 -06:00
ExcodeandHundrec 8aafe62f9c Update LevelProp.hx 2026-03-17 22:57:43 -06:00
MrMaderaandHundrec 0f7859bfb6 Gamepad binds showed in Freeplay's hint
_lastDeviceUsed -> lastDeviceUsed
2026-03-17 22:56:32 -06:00
Hundrec c3d3d2e547 Move Week 6 Erect results transition further down 2026-03-17 02:52:50 -06:00
37dc3461af Re-implement curNoteKind.suffix
Co-authored-by: TechnikTil <techniktil@tilnotdrip.org>
2026-03-17 02:52:14 -06:00
MightyTheArmiddiloandHundrec c11ac1f658 Fix Compile Errors With FLX_NO_DEBUG 2026-03-17 02:52:10 -06:00
TrayfellowandHundrec 47bbf67ae6 Updated level schema version 2026-03-17 02:51:46 -06:00
TrayfellowandHundrec 528e9e4f03 Data-driven changeable capsule texts 2026-03-17 02:50:30 -06:00
echolotlandHundrec 7626700495 Consistent line width + fix min/max of easing preview graph 2026-03-16 20:34:42 -06:00
AbnormalPoofandHundrec 0d2a663346 Enable null-safety on FunkinFilterRenderer 2026-03-16 13:08:36 -06:00
TechnikTilandHundrec 22736b27da Add filters to FunkinSprite
This commit also removes `FlxFilteredSprite`

Signed-off-by: TechnikTil <techniktil@tilnotdrip.org>
2026-03-16 13:08:36 -06:00
MAJigsaw77andHundrec dcfad7b7e8 Update libs ref 2026-03-16 13:08:35 -06:00
Hundrec ef625b3d9d Bump assets for a few minor fixes 2026-03-16 04:40:11 -06:00
MAJigsaw77andHundrec 6ce3a2e93e Update hxvlc to fix a couple of issues 2026-03-16 03:47:03 -06:00
SuperEricandHundrec b8c2854007 Adjust backingImage size 2026-03-14 23:36:29 -06:00
JVNpixelsandHundrec 04fffe8ade Commas For Story Mode Score 2026-03-14 23:14:15 -06:00
MAJigsaw77andHundrec c37862445f Update lime ref 2026-03-14 23:00:45 -06:00
VirtuGuyandHundrec 0613e9d295 Fix rimlight alt masks not working on web 2026-03-14 22:24:39 -06:00
MAJigsaw77andHundrec bed249dca0 Remove the framerate options on web 2026-03-14 22:13:54 -06:00
MAJigsaw77andHundrec 139940f9ec Update libs refs 2026-03-14 17:30:27 -06:00
Hyper_andHundrec 36e2f47577 Fix Random capsule not updating OST text 2026-03-13 21:48:13 -06:00
VirtuGuyandHundrec ce493a03c9 Fix favoriting songs breaking song text cycling 2026-03-13 21:48:13 -06:00
AnimatingLegendandHundrec aabd1aa9f7 fix: miss-animation timing in no-anim events 2026-03-13 21:25:52 -06:00
KoloandHundrec 89029220e4 optimization: remove a spammy trace 2026-03-13 21:25:52 -06:00
ImVeryBadandHundrec dca54de087 Add isBlank to StringTools for easier blank string checking. 2026-03-13 21:25:52 -06:00
KoloandHundrec 15bef89d71 Script event support for Song Events 2026-03-12 01:43:08 -06:00
6c1f3800db Fix duplicate asset paths in note styles crashing when exiting PlayState in Chart Editor.
Co-authored-by: Kolo <67389779+koloindacrib@users.noreply.github.com>
2026-03-12 01:43:08 -06:00
AbnormalPoofandHundrec 8507f799a1 Update polymod to the latest commit 2026-03-12 01:43:08 -06:00
EliteMasterEricandHundrec dba2794780 Use the font family instead of the file path 2026-03-12 01:42:47 -06:00
KoloandHundrec 48752e444c softcode freeplay capsule level labels 2026-03-12 01:42:24 -06:00
8a1d74b82c Re-enable FlxG.autoPause when doing stickers
Co-Authored-By: Hyper_ <40342021+NotHyper-474@users.noreply.github.com>
2026-03-12 01:40:26 -06:00
AnimatingLegendandHundrec 0d1db6ae9e fix(ui): prevent nametag pixelation on web builds 2026-03-12 01:39:13 -06:00
EliteMasterEricandHundrec 1f1851990f Make sure to update the schema version when adding fields, people! 0.0.x versions for new fields with no breaking changes. 2026-03-12 01:36:31 -06:00
Hyper_andHundrec 67d2a9811b feat: Custom OST names 2026-03-12 01:35:51 -06:00
LasercarandHundrec a782b3f9e8 Improved context menus Directly set the item's position and for hold notes, it's length as well Values can be shown and set in milliseconds or steptime 2026-03-12 01:34:08 -06:00
EricandHundrec 74e28a18ff Add an extra space 2026-03-12 01:31:20 -06:00
MoonDroidandHundrec 220636e01e Style leftover INFO logs with Ansi 2026-03-12 01:31:02 -06:00
MightyTheArmiddiloandHundrec 4f316003af FunkinGroup 2026-03-12 01:28:15 -06:00
AbnormalPoofandHundrec 1a04e35db7 Change instances of FlxG.onMobile to use preprocessor defines 2026-03-11 02:44:30 -06:00
MAJigsaw77andHundrec d3e83dd72d Add Vungle mediation for Admob 2026-03-11 02:34:04 -06:00
c4e2b900c1 Implement SDL3
Co-Authored-By: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
Co-Authored-By: Karim Akra <144803230+KarimAkra@users.noreply.github.com>
2026-03-10 04:54:26 -05:00
AbnormalPoof ac3178118c Remove FlxColorUtil as Polymod supports FlxColor 2026-03-10 04:37:12 -05:00
AbnormalPoof 681f7a6d07 Remove AbstractUtil since Polymod now supports FlxSignal proper 2026-03-10 04:37:00 -05:00
AbnormalPoof aa24c94782 Remove import aliases for abstracts 2026-03-10 04:36:58 -05:00
ComedyLostandAbnormalPoof 7075c8af4b Fix a crash for inst only songs 2026-03-10 04:33:14 -05:00
AbnormalPoof efc33403b6 fix: Fix REDIRECT_ASSETS_FOLDER not working on HashLink on macOS 2026-03-10 04:33:07 -05:00
Hundrec 25a42b8182 Reword Stage Editor unsaved work prompt 2026-03-09 20:16:07 -06:00
KoloandHundrec 0389af2202 fix moving globally offset characters not working 2026-03-09 20:16:07 -06:00
Hyper_andHundrec b694ec08d6 fix: Improve Preloader time on HashLink 2026-03-09 20:16:07 -06:00
PurSnakeandHundrec 423ccfab98 Implement ScriptedBaseFreeplayDJ usage 2026-03-09 09:38:58 -06:00
AbnormalPoofandHundrec edc1f7113b Update polymod to the latest commits 2026-03-09 09:38:58 -06:00
ImVeryBadandHundrec f0b50de9fa Add support for the new Polymod mod ID system. 2026-03-09 09:38:58 -06:00
LasercarandHundrec 0ad2d507ef Random cap difficulty & BPM value visible fix 2026-03-09 09:16:39 -06:00
LasercarandHundrec 6c13444211 Hide character select keybinds until unlock 2026-03-09 09:06:58 -06:00
MightyTheArmiddiloandHundrec 5a0b4310a2 Add onPause dispatching for cutscenes and conversations 2026-03-09 09:06:58 -06:00
LasercarandHundrec 6b1fc0372b Disable edit buttons if no selection 2026-03-09 08:41:21 -06:00
ImVeryBadandHundrec cf69125d25 Clean up Cursor.hx code 2026-03-09 08:34:15 -06:00
Redar13andHundrec 84b2d5b48d Fix GF bopping when switching levels in the story menu. 2026-03-09 08:28:18 -06:00
RudyrueandHundrec dcb5b3a935 fix timing windows being 1 ms tighter 2026-03-09 08:11:45 -06:00
TrofemandHundrec 011f1541b1 control + character icon combination for character preview 2026-03-09 07:50:49 -06:00
sector-aandHundrec 13c1bf8ac0 Fix null object reference when using collapsible 2026-03-09 07:50:49 -06:00
1893f2b2f6 Implement SetTargetBopSpeed Event
Co-Authored-By: Eric <4635334+EliteMasterEric@users.noreply.github.com>
2026-03-09 07:25:40 -06:00
VirtuGuyandHundrec a0caa41edc Fix phillyStreets rain not fading out 2026-03-09 06:55:23 -06:00
FuroandHundrec 456b2ff6c4 Prevent Importing non osu!mania beatmaps 2026-03-09 03:32:32 -06:00
AbnormalPoofandHundrec a1d1b1b2d1 Fix garbage collection being mostly broken on HashLink 2026-03-09 03:32:32 -06:00
Hyper_andHundrec 0db4ce11b7 fix: Make types explicit to fix crash on HashLink 2026-03-09 02:51:06 -06:00
340fd5dcf1 Add proper HashLink support
Co-authored-by: Sinco <113909588+sphis-Sinco@users.noreply.github.com>
2026-03-09 02:51:06 -06:00
EliteMasterEricandHundrec d569690a51 I think I was tired when I made that last commit lmao... 2026-03-09 02:51:06 -06:00
EliteMasterEricandHundrec 4a5afa2fc7 Oops there was a compile error 2026-03-09 02:51:06 -06:00
EliteMasterEricandHundrec 59c593b812 Adjust scroll speed tween duration based on playback rate 2026-03-09 02:51:06 -06:00
EliteMasterEricandHundrec 6ba9e00a9f Adjust camera zoom tween duration based on playback rate 2026-03-09 02:51:06 -06:00
EliteMasterEricandHundrec ec7bdd32e2 Adjust camera follow tween duration based on playback rate 2026-03-09 02:51:06 -06:00
AnimatingLegendandHundrec 939528a9bd refactor: remove discord_rpc from background process
DiscordRPC is being handled somewhere else. having these managers running twice, both for the same reasons its kind of pointless.
2026-03-09 02:51:06 -06:00
LasercarandHundrec 08b3af959d Chart editor - select above/below playhead 2026-03-06 05:17:14 -07:00
FuroandHundrec cea54e394c Legacy Voices System 2026-03-06 03:45:04 -07:00
Honton129andHundrec e710198afe Edit Note option in Context Menu
Shortcut to the  ``Notes`` toolbox by right-clicking a note and selecting ``Edit Note``.
2026-03-06 03:31:27 -07:00
Hyper_andHundrec bf3601ea8d fix: Properly trace Ansi code for exit trace 2026-03-06 03:31:24 -07:00
Hundrec c5566c8644 Exclude Week 7 bricks from ASTC 2026-03-04 23:21:51 -07:00
MAJigsaw77andHundrec 5944f5b55d Add Pangle mediation for Admob 2026-03-04 23:10:39 -07:00
RaltyandHundrec 077fbf6978 Fix sound tray playing multiple sounds at once, not appearing in lags 2026-03-04 23:10:39 -07:00
Hundrec f02bdc4225 Bump assets 2026-03-04 22:39:17 -07:00
EliteMasterEricandHundrec 8da9ed4ea0 Make sure only one stretchy sound plays at a time. 2026-03-04 22:39:17 -07:00
EliteMasterEricandHundrec 5ed4a2ddd0 Flag instrumental and vocal tracks as important to prevent them getting overriden by other sounds. 2026-03-04 22:39:17 -07:00
EliteMasterEricandHundrec 6293e2808b Reuse the sound objects for the stretchy sounds, to prevent too many of them playing at once. 2026-03-04 22:39:15 -07:00
Hundrec c6dc562769 Adjust some wording in the Backup window 2026-03-04 20:45:54 -07:00
marcoandHundrec a607396d04 Rename button text from 'Take Me There' to 'Open In Folder'
makes it clearer about what it does
2026-03-04 20:45:51 -07:00
ImVeryBadandHundrec 365f8dcfea Filter out unavailable difficulties from Story Mode levels. 2026-03-04 20:45:51 -07:00
FuroandHundrec b3eb709f4e Pixel Icon now changes the character value only if its valid 2026-03-04 15:25:30 -07:00
FuroandHundrec fcbce0a66b Fix Rank Slamming Animation 2026-03-04 15:25:21 -07:00
ComedyLostandHundrec 05032e3126 Play danceLeft anim for alternating characters 2026-03-04 15:25:16 -07:00
Hundrec b8a7189e24 Don't do Sys.exit force-kill on Mobile 2026-03-04 02:43:32 -07:00
AnimatingLegendandHundrec 881aba3b03 fix: prevent background processing upon game exit 2026-03-04 01:38:52 -07:00
Hundrec 5480774afe Fix Polymod for Mobile and HTML5 compiling 2026-03-03 17:21:59 -07:00
VirtuGuyandHundrec d62c8af20c Fix hold note length when hitting too early 2026-03-03 16:40:54 -07:00
MoonDroidandHundrec 7d0644f3c8 Add missing feature flag 2026-03-03 15:03:11 -07:00
Hyper_andHundrec fe21c0addd docs: Debug Hotkeys - Remove duplicate entry, fix error and add Mirrored Notes debug key 2026-03-02 20:16:03 -07:00
Hyper_andHundrec 219143c02d fix non existant paths not being sanitized properly on Linux 2026-03-02 20:16:03 -07:00
MightyTheArmiddiloandHundrec 03930a29c3 Remove duplicate blacklisting of the funkin.api.newgrounds package 2026-03-02 20:16:03 -07:00
ImVeryBadandHundrec 5d378cd9f2 Remove more traces from classes. 2026-03-02 20:16:03 -07:00
HundrecandKade e5db402025 Bump Polymod and adjust outdated mod error message
Co-Authored-By: Kade <26305836+Kade-github@users.noreply.github.com>
2026-03-02 20:16:03 -07:00
ImVeryBadandHundrec d348ef3127 Optional dependencies no longer throw window errors and improve log output messages. 2026-03-02 20:16:03 -07:00
Hundrec 9301c0c7dd Remove Song Preview 0 end times 2026-03-02 18:46:33 -07:00
ADA-FunniandHundrec 02ee8e64c8 Fix an issue where metadata stuff was acting weird. 2026-03-02 18:45:28 -07:00
ADA-FunniandHundrec 40eab2e461 Add customisable Freeplay song previews.
Any preview values over 15,000 get turned into 0 (start) and 0.2 (end).
2026-03-02 18:45:28 -07:00
AbnormalPoofandHundrec d6a65ca681 Tweak some animation lengths for Boyfriend DJ 2026-03-02 18:45:15 -07:00
EliteMasterEricandHundrec f8841bab35 Use a float internally to hold the Score, ensuring hold notes get scored correctly relative to the current framerate. 2026-03-02 01:38:30 -07:00
EliteMasterEricandAbnormalPoof dc23a116dd Update the PolymodErrorHandler to display an error message for API version or dependency issues. 2026-03-02 01:50:09 -06:00
AbnormalPoofandHundrec 024994e85a Re-export Boyfriend DJ using the latest BTA 2026-03-01 22:30:40 -07:00
MAJigsaw77andHundrec 9be1633320 Update extension-admob. 2026-03-01 04:21:54 -07:00
AnimatingLegendandHundrec 3b15873fc7 fix: chart editor playback-speed rounding upon reload 2026-02-28 00:05:34 -07:00
ComedyLostandHundrec 786f19c57d Stop playtest results with botplay 2026-02-28 00:05:34 -07:00
ComedyLostandHundrec ccb874e97a Stop the playbar head dragging when in song 2026-02-28 00:05:34 -07:00
VirtuGuyandHundrec f7fd7a57c3 Play SFX When Undoing Add Event 2026-02-28 00:05:33 -07:00
Hundrec 23f79aef58 Update assets submodule 2026-02-27 21:28:49 -07:00
EliteMasterEricandHundrec 2c394cc636 Fix an issue where displaying Tooltips would mess up HaxeUI field focus. 2026-02-27 21:26:11 -07:00
Hundrec d7a0139e4f Adjust focus lost volume level to 25%
Reducing to 50% wasn't noticeable enough, but 25% should be a clean reduction.
2026-02-27 21:25:57 -07:00
Karim AkraandHundrec 562d23005d Properly center the sound tray when the resolution is changed 2026-02-27 21:25:57 -07:00
EliteMasterEricandHundrec 671c152463 Fix a bug when the HUD camera zoom would be disabled when the MAIN camera zoom (different camera!) was above 1.35x. 2026-02-26 20:21:16 -07:00
EliteMasterEricandHundrec 3ce7c7939f Updated tooltips to use the note kind description 2026-02-25 00:52:47 -07:00
EliteMasterEricandHundrec 28450ccfc6 Build the list of note kinds from the NoteKindManager instead of hardcoding it 2026-02-25 00:52:45 -07:00
472 changed files with 24539 additions and 7865 deletions
+4 -4
View File
@@ -14,7 +14,7 @@ body:
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
- label: I have checked the Issues/Discussions pages to see if my issue has already been reported
- label: I have properly titled my issue
- label: I did not have any mods installed when I encountered this issue
- label: I did not have any mods installed when I encountered this issue, or the issue is related to mods
- type: dropdown
attributes:
@@ -48,19 +48,19 @@ body:
attributes:
label: Mobile Device Model
description: (Mobile users only) What mobile device are you playing on?
placeholder: ex. iPhone 17, Galaxy S25, iPad 11th Gen
placeholder: ex. iPhone 17, Galaxy S26, iPad 11th Gen
- type: input
attributes:
label: Mobile OS Version
description: (Mobile users only) What version is your Operating System?
placeholder: ex. iOS 26.3, Android 16, iPadOS 26.3
placeholder: ex. iOS 26.4, Android 16, iPadOS 26.4
- type: input
attributes:
label: Version
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
placeholder: ex. 0.8.3
placeholder: ex. 0.8.6 or 0.9 Feature Preview 3
validations:
required: true
+2 -2
View File
@@ -36,7 +36,7 @@ body:
attributes:
label: Version
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
placeholder: ex. 0.8.3
placeholder: ex. 0.8.6 or 0.9 Feature Preview 3
validations:
required: true
@@ -52,7 +52,7 @@ body:
attributes:
label: Location
description: Where did you find the issue(s)? Include the name of the song, the variation, the difficulty, the time/section of the song, and any images or videos.
placeholder: ex. Cocoa Erect on Erect/Nightmare difficulties at Section 30
placeholder: ex. Cocoa Erect [Nightmare] at Section 30, step 5
validations:
required: true
+1 -1
View File
@@ -36,7 +36,7 @@ body:
attributes:
label: Version
description: Which version are you compiling? The game version is in the bottom left corner of the main menu or in the project.hxp file.
placeholder: ex. 0.8.3
placeholder: ex. 0.8.6 or `preview/public-playtest`
validations:
required: true
+4 -4
View File
@@ -15,7 +15,7 @@ body:
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
- label: I have checked the Issues/Discussions pages to see if my issue has already been reported
- label: I have properly titled my issue
- label: I did not have any mods installed when I encountered this issue
- label: I did not have any mods installed when I encountered this issue, or the issue is related to mods
- type: dropdown
attributes:
@@ -49,19 +49,19 @@ body:
attributes:
label: Mobile Device Model
description: (Mobile users only) What mobile device are you playing on?
placeholder: ex. iPhone 17, Galaxy S25, iPad 11th Gen
placeholder: ex. iPhone 17, Galaxy S26, iPad 11th Gen
- type: input
attributes:
label: Mobile OS Version
description: (Mobile users only) What version is your Operating System?
placeholder: ex. iOS 26.3, Android 16, iPadOS 26.3
placeholder: ex. iOS 26.4, Android 16, iPadOS 26.4
- type: input
attributes:
label: Version
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
placeholder: ex. 0.8.3
placeholder: ex. 0.8.6 or 0.9 Feature Preview 3
validations:
required: true
+4 -4
View File
@@ -5,7 +5,7 @@ inputs:
haxe:
description: 'Version of haxe to install'
required: true
default: '4.3.6'
default: '4.3.7'
hxcpp-cache:
description: 'Whether to use a shared hxcpp compile cache'
required: true
@@ -71,7 +71,7 @@ runs:
- name: Restore cached dependencies
id: cache-hmm
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: .haxelib
key: haxe-hmm-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
@@ -98,7 +98,7 @@ runs:
# by default use a shared hxcpp cache
- if: ${{ inputs.hxcpp-cache == 'true' }}
name: Restore hxcpp cache
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ${{ inputs.hxcpp-cache-path }}
key: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
@@ -114,7 +114,7 @@ runs:
# if it's explicitly disabled, still cache export/ since that then contains the builds
- if: ${{ inputs.hxcpp-cache != 'true' }}
name: Restore export cache
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ${{ inputs.hxcpp-cache-path }}
key: haxe-export-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
+3 -3
View File
@@ -61,7 +61,7 @@ runs:
- name: Get latest butler version
shell: bash
run: |
LATEST=$(curl -sfL https://broth.itch.ovh/butler/$OS_AND_ARCH/LATEST)
LATEST=$(curl -sfL https://broth.itch.zone/butler/$OS_AND_ARCH/LATEST)
echo BUTLER_LATEST=$LATEST >> "$GITHUB_ENV"
command -v butler \
@@ -70,7 +70,7 @@ runs:
- name: Try to get butler from cache
id: cache-butler
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ${{ env.BUTLER_INSTALL_PATH }}
key: butler-${{ runner.os }}-${{ env.BUTLER_LATEST }}
@@ -88,7 +88,7 @@ runs:
mkdir -p $BUTLER_INSTALL_PATH
cd $BUTLER_INSTALL_PATH
curl -L -o butler.zip https://broth.itch.ovh/butler/$OS_AND_ARCH/LATEST/archive/default
curl -L -o butler.zip https://broth.itch.zone/butler/$OS_AND_ARCH/LATEST/archive/default
unzip butler.zip
chmod +x butler
+38 -15
View File
@@ -24,10 +24,10 @@ jobs:
trigger-build: ${{ steps.should-trigger.outputs.result }}
steps:
- name: Checkout repo
uses: funkincrew/ci-checkout@v7.3.3
uses: funkincrew/ci-checkout@v7.4
with:
submodules: false
- uses: dorny/paths-filter@v3
- uses: dorny/paths-filter@v4
id: filter
with:
base: ${{ github.ref }}
@@ -59,7 +59,7 @@ jobs:
list: ${{ steps.build-tags.outputs.list }}
steps:
- name: Gather build tags
uses: actions/github-script@v7
uses: actions/github-script@v8
id: build-tags
with:
script: |
@@ -96,17 +96,20 @@ jobs:
packages: write
steps:
- name: Checkout repo
uses: funkincrew/ci-checkout@v7.3.3
uses: funkincrew/ci-checkout@v7.4
with:
submodules: false
- name: Log into GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
with:
context: ./build
push: true
@@ -143,14 +146,14 @@ jobs:
run: |
git config --global --replace-all safe.directory $GITHUB_WORKSPACE
- name: Get checkout token
uses: actions/create-github-app-token@v1
uses: actions/create-github-app-token@v3
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v7.3.3
uses: funkincrew/ci-checkout@v7.4
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
@@ -184,7 +187,7 @@ jobs:
timeout-minutes: 120
- name: Save build artifact to Github Actions
if: ${{ github.event.inputs.save-artifact }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: build-${{ matrix.target }}
path: export/release/${{matrix.target}}/bin/
@@ -212,14 +215,14 @@ jobs:
BUILD_DEFINES: ${{ github.event.inputs.build-defines || '-DGITHUB_BUILD' }}
steps:
- name: Get checkout token
uses: actions/create-github-app-token@v1
uses: actions/create-github-app-token@v3
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v7.3.3
uses: funkincrew/ci-checkout@v7.4
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
@@ -233,7 +236,7 @@ jobs:
echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV"
- name: Restore cached dependencies
id: cache-hmm
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: .haxelib
key: haxe-hmm-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
@@ -242,15 +245,35 @@ jobs:
run: |
git config --global 'url.https://x-access-token:${{ steps.app_token.outputs.token }}@github.com/.insteadOf' https://github.com/
git config --global advice.detachedHead false
haxelib --global git haxelib https://github.com/FunkinCrew/haxelib.git
haxelib --global git hmm https://github.com/FunkinCrew/hmm.git
haxelib --global run hmm install -q
cd .haxelib/hxcpp/git/tools/hxcpp && haxe compile.hxml
haxelib --global fixrepo
haxelib --global list
pushd .haxelib/hxcpp/git/tools/hxcpp && haxe compile.hxml && popd
- if: ${{ matrix.target != 'html5' }}
name: Restore hxcpp cache
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: /usr/share/hxcpp
key: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}
- name: Restore lime rebuild cache
id: cache-lime
uses: actions/cache@v5
with:
path: .haxelib/lime/git/ndll/Linux64
key: haxe-lime-linux64-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}-${{ github.sha }}
restore-keys: haxe-lime-linux64-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
- name: Setup lime
run: |
haxelib --always run lime setup
haxelib run lime rebuild hxcpp
- if: ${{ steps.cache-lime.outputs.cache-hit != 'true' }}
name: Rebuild lime
run: |
haxelib run lime rebuild cpp -64
git -C .haxelib/lime/git status || true
- name: Populate .env
run: |
touch .env
@@ -262,7 +285,7 @@ jobs:
timeout-minutes: 120
- name: Save build artifact to Github Actions
if: ${{ github.event.inputs.save-artifact }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: build-${{ matrix.target }}
path: export/release/${{matrix.target}}/bin/
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
steps:
- name: Cancel queued workflows for ${{ github.event.pull_request.head.ref }}
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
result-encoding: string
retries: 3
+1 -1
View File
@@ -27,4 +27,4 @@ jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/label-actions@v4
- uses: dessant/label-actions@v5
@@ -7,6 +7,11 @@ on:
types:
- opened
# Ensure only one task can execute for a given PR at a time.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
queue: max
jobs:
# Apply `status: pending triage` to newly created pull requests
+5 -1
View File
@@ -13,6 +13,10 @@ name: "Pull Request Labeler"
on:
- pull_request_target
# Ensure only one task can execute for a given PR at a time.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
queue: max
jobs:
# Apply labels to pull requests based on which files were edited
@@ -23,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set basic labels
uses: actions/labeler@v5
uses: actions/labeler@v6
with:
sync-labels: true
# Apply labels to pull requests based on how many lines were edited
+8
View File
@@ -17,6 +17,14 @@ NewgroundsCredentials.hx
.idea/
*.iml
# Dox output and types
docs/dox/output
docs/dox/Windows.xml
docs/dox/Mac.xml
docs/dox/iOS.xml
docs/dox/Linux.xml
docs/dox/Android.xml
# Mobile signing stuff
.apple/
.env
+7 -2
View File
@@ -80,13 +80,13 @@
{ "name": "html5", "enabled": true, "label": "HTML5" },
{ "name": "android", "enabled": true, "label": "Android" },
{ "name": "ios", "enabled": true, "label": "iOS" },
// Disabled targets
{ "name": "hl", "enabled": false, "label": "HashLink" },
{ "name": "air", "enabled": false },
{ "name": "electron", "enabled": false },
{ "name": "flash", "enabled": false },
{ "name": "neko", "enabled": false },
{ "name": "tvos", "enabled": false }
{ "name": "hl", "enabled": false }
],
"lime.defaultTargetConfiguration": "Windows / Debug",
"lime.targetConfigurations": [
@@ -144,6 +144,11 @@
"target": "windows",
"args": ["-debug", "-DLATENCY", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Windows / Debug (No Asset Redirect)",
"target": "windows",
"args": ["-debug", "-DNO_REDIRECT_ASSETS_FOLDER"]
},
{
"label": "Windows / Debug (Waveform Test)",
"target": "windows",
+270 -32
View File
@@ -4,6 +4,243 @@ All notable changes will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.8.7] - 2026-08-23
### Fixed
- [ANDROID] Fixed a crash when opening an FNFC chart file.
- [ANDROID] Fixed errors and crashes related to the lime backend.
- [ANDROID] Fixed a shader not displaying correctly in some places.
## [0.8.6] - 2026-08-12
### Added
- Added the ability to toggle Discord RPC statuses and hide song info.
- [LINUX] Added support for Wayland, which the game now defaults to. (Thanks Starexify!)
- Added the game version as a compilation flag for modders to access. ([e51ae10](https://github.com/FunkinCrew/Funkin/commit/e51ae1098a9392c7ec3a903543f3aa4fc4220da1)) - by @zxcksharks in [#7659](https://github.com/FunkinCrew/Funkin/pull/7659)
- Added a shouldBop property to HealthIconData to allow animated icons to bop. ([cc91faa](https://github.com/FunkinCrew/Funkin/commit/cc91faaccc63d2050270723bd49477f8b518ab6f)) - by @Starexify in [#6901](https://github.com/FunkinCrew/Funkin/pull/6901)
- Added album and sticker pack fields to the Chart Editor Metadata window. ([790e3fb](https://github.com/FunkinCrew/Funkin/commit/790e3fb097b7054e7cf4010d6b588264414d283a)) - by @Starexify in [#6266](https://github.com/FunkinCrew/Funkin/pull/6266)
### Changed
- [HTML5] The “Touch To Play” sprite now smoothly scales when hovered.
- Made some improvements to width/height and cliprect functionality for FunkinGroup.
- The Chart Editor now consistently exports chart data in the same order. (Thanks TechnikTil!)
- Discord RPC images can now be configured in the album and song data files.
- Discord RPC now pulls icons based on character icon data. ([bd23b5c](https://github.com/FunkinCrew/Funkin/commit/bd23b5c12f734eae529a8d2d2593fd1d6eb9a27b)) - by @7oltan in [#7643](https://github.com/FunkinCrew/Funkin/pull/7643)
- Forced animations for the player character now unmute the player's vocals. ([e0a6253](https://github.com/FunkinCrew/Funkin/commit/e0a625331010a2dddde639a24953dd88f25010b1)) - by @Lasercar in [#4314](https://github.com/FunkinCrew/Funkin/pull/4314)
- The Animation Editor now plays the Chart Editor theme music and click sounds. ([f42dcec](https://github.com/FunkinCrew/Funkin/commit/f42dcecab6966f77162308a0564af558616ea81b)) - by @JVNpixels in [#7556](https://github.com/FunkinCrew/Funkin/pull/7556)
### Fixed
- Made some niche fixes to Polymod.
- Argument count validation no longer crashes the game entirely in some instances. (Thanks Starexify!)
- The `cast` keyword no longer throws a parsing error. (Thanks gamerbross!)
- Every non-Windows platform is now case-insensitive. (Thanks TechnikTil!)
- Preprocessors that span the entire file no longer throw an error. (Thanks KoloInDaCrib!)
- Scripted class extending no longer breaks with multiple scripted layers. (Thanks TechnikTil!)
- Imports with module names (ex. `funkin.play.character.BaseCharacter.CharacterType​​`) no longer throw an import error. (Thanks NotHyper-474!)
- [iOS] Connecting a keyboard no longer freezes the game.
- The Darken blend mode no longer renders with black boxes, fixing the Boyfriend Freeplay DJ Dad animation.
- The Open File dialog now opens from the latest directory, not the root directory.
- The Chart Editor now exports charts with correct suffixes for vocal tracks.
- Clicking the Save Chart button now displays a notification in the Chart Editor.
- Disconnecting a controller while in the gamepad controls menu no longer crashes the game. ([6fe2089](https://github.com/FunkinCrew/Funkin/commit/6fe2089beac639124d3561d4c2c1af1ffb7dfe11)) - by @MrMadera in [#7214](https://github.com/FunkinCrew/Funkin/pull/7214)
- Hot-reloading and re-entering the Lag Adjustment menu no longer crashes the game. ([adbe5ba](https://github.com/FunkinCrew/Funkin/commit/adbe5ba7cb53f67363ec205c5e555744e69215de)) - by @AnimatingLegend in [#7304](https://github.com/FunkinCrew/Funkin/pull/7304)
- `onExit` is now properly called when exiting the game. ([90712bf](https://github.com/FunkinCrew/Funkin/commit/90712bf1e62a20d1201c3da15b4554720e9fff46)) - by @AnimatingLegend in [#7321](https://github.com/FunkinCrew/Funkin/pull/7321)
- Focusing into the game with 0 volume and Pause on Unfocus disabled no longer increases the volume. ([18f5e25](https://github.com/FunkinCrew/Funkin/commit/18f5e25496d2cb74fff24e490a95db29a1fb59e3)) - by @ahmed7p in [#7750](https://github.com/FunkinCrew/Funkin/pull/7750)
- Save Data prompts no longer allow scrolling the Options menu behind them. ([83bfccc](https://github.com/FunkinCrew/Funkin/commit/83bfccc10115b089f6b8d747c366c2be64c4335c)) - by @Starexify in [#7213](https://github.com/FunkinCrew/Funkin/pull/7213)
- Adjusted the Lag Adjustment overlay to fit the whole screen. ([27fd960](https://github.com/FunkinCrew/Funkin/commit/27fd960fb369b2baf3c3377fa317732bf80a5230)) - by @JVNpixels in [#7358](https://github.com/FunkinCrew/Funkin/pull/7358)
- Input latency is now calculated correctly when hitting a note late in the Lag Adjustment menu. ([de36ca8](https://github.com/FunkinCrew/Funkin/commit/de36ca87e8b95d8fe4d40d458c355baf52e4d94a)) - by @nykwono in [#7792](https://github.com/FunkinCrew/Funkin/pull/7792)
- Weeks with non-default variation songs no longer use default variation scripts. ([2a49681](https://github.com/FunkinCrew/Funkin/commit/2a4968115f0ed5e81d4209bedba3f8bf153aab6a)) - by @requazar in [#7586](https://github.com/FunkinCrew/Funkin/pull/7586)
- Scrolling Freeplay after the rank slam animation now properly updates the song preview. ([347f7cf](https://github.com/FunkinCrew/Funkin/commit/347f7cfecbe91fc06e71a502ee58a5d7859be5fc)) - by @AnimatingLegend in [#7230](https://github.com/FunkinCrew/Funkin/pull/7230)
- Earning a new rank no longer causes the song title to clip incorrectly. ([0b6198f](https://github.com/FunkinCrew/Funkin/commit/0b6198f23ad7a957d40eaaf6d4af9b976e6e1a36)) - by @KoloInDaCrib in [#7350](https://github.com/FunkinCrew/Funkin/pull/7350)
- Selecting a Freeplay song capsule no longer occasionally squashes the text. ([bdf51dc](https://github.com/FunkinCrew/Funkin/commit/bdf51dcd4392a7d99c9837bd3b56b4e6497cf207)) - by @Lasercar in [#6038](https://github.com/FunkinCrew/Funkin/pull/6038)
- The Freeplay backing image now respects modified alpha values. ([840c043](https://github.com/FunkinCrew/Funkin/commit/840c0431ecaf3004901bd09a346c126eb8e2f484)) - by @Luscious77 in [#7576](https://github.com/FunkinCrew/Funkin/pull/7576)
- Removed clipping from the OST Vol 1 album title sprite. ([90282d7](https://github.com/FunkinCrew/funkin.assets/commit/90282d78c6a326f1c1e05bec3f3638d3f0cd66a9)) - by @LeGooeyy in [funkin.assets#410](https://github.com/FunkinCrew/funkin.assets/pull/410)
- The Freeplay change character hint now updates consistently when a gamepad is connected. ([e0af5e2](https://github.com/FunkinCrew/Funkin/commit/e0af5e282e6cf2ad0a63dbf633eb325204fbd649)) - by @MrMadera in [#7409](https://github.com/FunkinCrew/Funkin/pull/7409)
- Character Select nametags no longer become stuck pixelated when switching between characters. ([a62e1c0](https://github.com/FunkinCrew/Funkin/commit/a62e1c08ab4a8cbe1f0bc790e4c228b5b64f0071)) - by @NotHyper-474 in [#7217](https://github.com/FunkinCrew/Funkin/pull/7217)
- Pressing a note with two different keybinds now properly penalizes health. ([d60fe07](https://github.com/FunkinCrew/Funkin/commit/d60fe0726f1cab3999a35ff497ba32e82afbd1b8)) - by @realvirtu in [#7744](https://github.com/FunkinCrew/Funkin/pull/7744)
- Input latency is now calculated correctly when hitting a note late. ([b97012a](https://github.com/FunkinCrew/Funkin/commit/b97012a10d54e222a3f370956d0e42f8d8eaab47)) - by @Lasercar in [#7367](https://github.com/FunkinCrew/Funkin/pull/7367)
- Conductor events are no longer dispatched when a substate is active. ([19610c4](https://github.com/FunkinCrew/Funkin/commit/19610c43099dfaf4a8b9ae70dc7f4b1833f420a9)) - by @KoloInDaCrib in [#6886](https://github.com/FunkinCrew/Funkin/pull/6886)
- Health icon angles now lerp at the proper rate. ([2bb5397](https://github.com/FunkinCrew/Funkin/commit/2bb5397c2b9e7fcc9d62670c6a86ebce64737f46)) - by @Starexify in [#7222](https://github.com/FunkinCrew/Funkin/pull/7222)
- Hold note covers no longer disappear when too many are on screen at once. ([f0a5188](https://github.com/FunkinCrew/Funkin/commit/f0a5188cb11cde3f6646254a39953e7b064dd7e9)) - by @realvirtu in [#7593](https://github.com/FunkinCrew/Funkin/pull/7593)
- The notestyle now properly falls back to the default notestyle in PlayState. ([ac10239](https://github.com/FunkinCrew/Funkin/commit/ac102396d71609b61f8864c2dad72b8d4b647dd1)) - by @NotHyper-474 in [#7721](https://github.com/FunkinCrew/Funkin/pull/7721)
- Using characters outside of PlayState no longer tries to create health icons. ([da1e8e4](https://github.com/FunkinCrew/Funkin/commit/da1e8e4664dfdd098794aa7187e15c85d020508c)) - by @zxcksharks in [#7646](https://github.com/FunkinCrew/Funkin/pull/7646)
- Pausing the game on the same frame a camera event is triggered no longer cancels the event. ([0e967eb](https://github.com/FunkinCrew/Funkin/commit/0e967ebefb61cb007cc84fc2032dc4a1d7c399a5)) - by @realvirtu in [#7472](https://github.com/FunkinCrew/Funkin/pull/7472)
- Pausing while a dialogue conversation is fading out now pauses the fade tween. ([c0a483f](https://github.com/FunkinCrew/Funkin/commit/c0a483f003ca901679e7a4a3fe5a9dfacd86ea15)) - by @ahmed7p in [#7359](https://github.com/FunkinCrew/Funkin/pull/7359)
- A-Bot's eyes now consistently follow the Focus Camera event. ([0de4f94](https://github.com/FunkinCrew/funkin.assets/commit/0de4f94e10f09f637dca2dedf2538d5ae45dcd97)) - by @ahmed7p in [funkin.assets#408](https://github.com/FunkinCrew/funkin.assets/pull/408)
- Doppelganger Pico's vocals are now fully muted after encountering an easter egg. ([09e3b50](https://github.com/FunkinCrew/funkin.assets/commit/09e3b5025268e53c5c9415e9d2c40122c5ec4493)) - by @trayfellow in [funkin.assets#401](https://github.com/FunkinCrew/funkin.assets/pull/401)
- The passing car in Week 4 stages no longer floats when the camera is zoomed out. ([baacbaa](https://github.com/FunkinCrew/funkin.assets/commit/baacbaa45469a5497e0ac4e35dc772214beef763)) - by @realvirtu in [funkin.assets#415](https://github.com/FunkinCrew/funkin.assets/pull/415)
- Spirit's icon no longer renders behind the health bar in some cases. ([4f96d2c](https://github.com/FunkinCrew/Funkin/commit/4f96d2c070c2768327c6fcd5983dd6a4458f61b3)) - by @NotHyper-474 in [#7676](https://github.com/FunkinCrew/Funkin/pull/7676)
- The Stress background tankmen now pause their flickering when the game is paused. ([25c7810](https://github.com/FunkinCrew/funkin.assets/commit/25c781024d4299c15c42a23d2ed788c9e34785fa)) - by @ahmed7p in [funkin.assets#405](https://github.com/FunkinCrew/funkin.assets/pull/405)
- Optimized the rimlight shader to improve performance in the Week 7 Erect stage. ([0e82016](https://github.com/FunkinCrew/Funkin/commit/0e8201623240ed189ce8517431e73eb6a0d8b50c)) - by @iLauncherDev in [#7517](https://github.com/FunkinCrew/Funkin/pull/7517)
- Selecting between events of different types while searching in the Events window no longer crashes the Chart Editor. ([05c81bc](https://github.com/FunkinCrew/Funkin/commit/05c81bc622fbe8eeaefbc685389c18d8944243b2)) - by @Infinite-SUDO67 in [#7767](https://github.com/FunkinCrew/Funkin/pull/7767)
- Selecting between notes with different notekinds while searching in the Notes window no longer crashes the Chart Editor. ([b42cd4b](https://github.com/FunkinCrew/Funkin/commit/b42cd4b6e17ac9bbff9934a69b10c7fbb2e6f5e6)) - by @kiryvajiravuth in [#7761](https://github.com/FunkinCrew/Funkin/pull/7761)
- Chart Editor dropdowns no longer lock focus onto them after selecting an item. ([86f2f44](https://github.com/FunkinCrew/Funkin/commit/86f2f44b468a25c060240911765a8b210867418b)) - by @VICK-sys in [#7528](https://github.com/FunkinCrew/Funkin/pull/7528)
- Health icons now consistently appear in the Chart Editor. ([1fce75f](https://github.com/FunkinCrew/Funkin/commit/1fce75feb99988a4757f620968f4ab53d68111c7)) - by @Starexify in [#7193](https://github.com/FunkinCrew/Funkin/pull/7193)
- Chart Editor Results Screen music no longer persists into gameplay when hot-reloading with F5. ([0b08668](https://github.com/FunkinCrew/Funkin/commit/0b086689e82c6fd6cac0d96b4cdca7b18543659d)) - by @AnimatingLegend in [#7126](https://github.com/FunkinCrew/Funkin/pull/7126)
- Chart Editor playtests now only carry over custom playback rates when "Use Editor Audio Settings" is enabled. ([7f8a1ab](https://github.com/FunkinCrew/Funkin/commit/7f8a1ab6d067db0b2cd7d16f75d08cc2bce6731d)) - by @NotHyper-474 in [#7483](https://github.com/FunkinCrew/Funkin/pull/7483)
- Packaged song scripts no longer create errors during Chart Editor playtests. ([b75add7](https://github.com/FunkinCrew/Funkin/commit/b75add7c59d338606b7004f5814e976aaa074a8f)) - by @ahmed7p in [#7470](https://github.com/FunkinCrew/Funkin/pull/7470)
- Saving a chart or metadata file through the Difficulty toolbox now saves with the correct file name. ([6aa8bc3](https://github.com/FunkinCrew/Funkin/commit/6aa8bc3ce93affbe69bf7b39300c62f60e912cce)) - by @NebulaStellaNova in [#7571](https://github.com/FunkinCrew/Funkin/pull/7571)
- The Chart Editor background now scales properly on widescreen resolutions. ([2e4115a](https://github.com/FunkinCrew/Funkin/commit/2e4115a33cee591f28433b92da4ead2e64da90fa)) - by @JVNpixels in [#7741](https://github.com/FunkinCrew/Funkin/pull/7741)
- The Stage Editor no longer crashes when loading in Texture Atlas props. ([e8d91e0](https://github.com/FunkinCrew/Funkin/commit/e8d91e0f1f6aff6a62b4946868f5dfe6d6b2d461)) - by @KoloInDaCrib in [#7674](https://github.com/FunkinCrew/Funkin/pull/7674)
- Folders in the mod folder without Polymod metadata no longer display an error. ([6ab6bc6](https://github.com/FunkinCrew/Funkin/commit/6ab6bc62e7bd81e218747ed4446089f04a938811)) - by @Starexify in [#7282](https://github.com/FunkinCrew/Funkin/pull/7282)
- Enforced the Polymod blacklist in ReflectUtil. ([66d191d](https://github.com/FunkinCrew/Funkin/commit/66d191d43102f75f672478bd2efd9c7e820c1c05)) - by @FuroYT in [#7005](https://github.com/FunkinCrew/Funkin/pull/7005)
- Blacklisted a class for security. ([3752232](https://github.com/FunkinCrew/Funkin/commit/3752232e3ab6ed0cb41445cb50729e74f338fa44)) - by @charlesisfeline in [#7512](https://github.com/FunkinCrew/Funkin/pull/7512)
## New Contributors for 0.8.6
* @moxie-coder made their first contribution in [#7187](https://github.com/FunkinCrew/Funkin/pull/7187)
* @ahmed7p made their first contribution in [#7470](https://github.com/FunkinCrew/Funkin/pull/7470)
* @iLauncherDev made their first contribution in [#7517](https://github.com/FunkinCrew/Funkin/pull/7517)
* @Luscious77 made their first contribution in [#7576](https://github.com/FunkinCrew/Funkin/pull/7576)
* @VICK-sys made their first contribution in [#7528](https://github.com/FunkinCrew/Funkin/pull/7528)
* @MRK2009 made their first contribution in [#7686](https://github.com/FunkinCrew/Funkin/pull/7686)
* @kiryvajiravuth made their first contribution in [#7761](https://github.com/FunkinCrew/Funkin/pull/7761)
* @Infinite-SUDO67 made their first contribution in [#7767](https://github.com/FunkinCrew/Funkin/pull/7767)
* @nykwono made their first contribution in [#7792](https://github.com/FunkinCrew/Funkin/pull/7792)
* @WizardMantis441 made their first contribution in [funkin.assets#413](https://github.com/FunkinCrew/funkin.assets/pull/413)
## [0.8.5] - 2026-04-06
### Fixed
- [ANDROID] Fixed various issues with visuals, controls, and gamepad functionality.
## [0.8.4] - 2026-03-26
### Added
- Added several new features to Polymod:
- Added FULL support for abstracts! (Previously, only `FlxColor` was supported)
- Added support for getting the code of a single character string (i.e `’h’.code`) (Thanks NotHyper-474!)
- Added support for import defaults (`import.hx`/`import.hxc`), allowing scripted classes with the same package to share imports. (Thanks KoloInDaCrib!)
- Added `scriptInit` and `listScriptClasses` functions to scripted classes. (Thanks KoloInDaCrib!)
- `.hx` files can now be parsed. (Thanks Starexify!)
- Added support for preprocessing (`#if`/`#else` syntax), allowing for platform-specific code to be implemented in an easier way. (Thanks KoloInDaCrib!)
- Added support for mod IDs. (Thanks Starexify!)
- Implemented `_merge` support for scripts. (Thanks KoloInDaCrib!)
- Please refer to the Cookbook to learn how to use this.
- Added widescreen scale properties to the Zoom Camera event in the Chart Editor to account for widescreen resolutions.
- Added a flipY field for Story Mode level props. ([48ed659](https://github.com/FunkinCrew/Funkin/commit/48ed65980005366371fda7a66c04f73bb5b86200)) - by @ExtraCode75 in [#6340](https://github.com/FunkinCrew/Funkin/pull/6340)
- Implemented working start and end times for Freeplay song previews. ([40eab2e](https://github.com/FunkinCrew/Funkin/commit/40eab2e4618ebb6dc67a06ef67df817920773c56)) - by @ADA-Funni in [#6725](https://github.com/FunkinCrew/Funkin/pull/6725)
- Added a new albumOSTName property to Freeplay album data to make the "OFFICIAL OST" text moddable. ([67d2a98](https://github.com/FunkinCrew/Funkin/commit/67d2a9811b5c92409bdc76e287c984d5777d8621)) - by @NotHyper-474 in [#6578](https://github.com/FunkinCrew/Funkin/pull/6578)
- Added an optional 'capsule' field to level data to display any week label on Freeplay capsules. ([528e9e4](https://github.com/FunkinCrew/Funkin/commit/528e9e4f03c40e59f3932d8b4c522b6eeb66783b)) - by @Trayfellow in [#7149](https://github.com/FunkinCrew/Funkin/pull/7149)
- Implemented ScriptedBaseFreeplayDJ, allowing modders to customize how custom Freeplay DJs are rendered. ([423ccfa](https://github.com/FunkinCrew/Funkin/commit/423ccfab98a29646e4998dacedaf403319d956ff)) - by @PurSnake in [#6806](https://github.com/FunkinCrew/Funkin/pull/6806)
- Added a new FunkinGroup class to make groups of sprites easier to modify. ([4f31600](https://github.com/FunkinCrew/Funkin/commit/4f316003af9a6ca46c77bf4971059e20543cbd7b)) - by @MightyTheArmiddilo in [#6758](https://github.com/FunkinCrew/Funkin/pull/6758)
- Added `Reflect.makeVarArgs` to allow modders to create functions with a variable number of arguments. ([3633df3](https://github.com/FunkinCrew/Funkin/commit/3633df3fdc6dc0af4f9886fcb1e1d4a8d2b8d5aa)) - by @Starexify in [#6738](https://github.com/FunkinCrew/Funkin/pull/6738)
- Added script event support for song events. ([15bef89](https://github.com/FunkinCrew/Funkin/commit/15bef89d71982c5685f4ce6f6d7e6e4d8321508c)) - by @KoloInDaCrib in [#4130](https://github.com/FunkinCrew/Funkin/pull/4130)
- Added a new Chart Editor event type: Set Target Bop Speed. ([1893f2b](https://github.com/FunkinCrew/Funkin/commit/1893f2b2f679d8a4d262052793dde24e94719ee6)) - by @roma-perec-bp in [#6769](https://github.com/FunkinCrew/Funkin/pull/6769)
- Added shortcuts to select all notes above or below the playhead in the Chart Editor. ([08b3af9](https://github.com/FunkinCrew/Funkin/commit/08b3af959d6657511bfe8418da545731050cb24a)) - by @Lasercar in [#4306](https://github.com/FunkinCrew/Funkin/pull/4306)
- Added the ability to view and edit the timing of a note or event through the Chart Editor context menu. ([a782b3f](https://github.com/FunkinCrew/Funkin/commit/a782b3f9e8498634babb864341fd1437bb2c01f6)) - by @Lasercar in [#4200](https://github.com/FunkinCrew/Funkin/pull/4200)
- Added an "Edit Note" option to the Chart Editor context menu that opens the Notes window. ([e710198](https://github.com/FunkinCrew/Funkin/commit/e710198afec9a0fe19effe4cd196ab3a247f4784)) - by @Honton129 in [#7010](https://github.com/FunkinCrew/Funkin/pull/7010)
- Added the ability to Ctrl-click on health icons in the Chart Editor to open character previews. ([011f154](https://github.com/FunkinCrew/Funkin/commit/011f1541b197fd4f962ab8a910cbd417f78c2d09)) - by @Trofem in [#7089](https://github.com/FunkinCrew/Funkin/pull/7089)
### Changed
- Upgraded the input handling system from SDL2 to SDL3!
- Added an “Unlocked Framerate” preference to Desktop platforms.
- The input system is now much more responsive and accurate down to the nanosecond.
- The game now properly supports more controllers and input devices.
- The game now shows popups when installed mods have issues, such as when the API version is incorrect.
- Unfocusing the game now reduces the game’s volume to 25% (down from 50%).
- The notekinds dropdown are no longer hardcoded in the Chart Editor.
- The Character Select key is now hidden in the Controls menu until a new character is unlocked. ([6c13444](https://github.com/FunkinCrew/Funkin/commit/6c134442118d3f5f61b9e3faa631512d210422fb)) - by @Lasercar in [#4882](https://github.com/FunkinCrew/Funkin/pull/4882)
- The Story Mode level score now displays with commas. ([04fffe8](https://github.com/FunkinCrew/Funkin/commit/04fffe8ade4c4b236d59a236f08534e8eede179f)) - by @JVNpixels in [#4965](https://github.com/FunkinCrew/Funkin/pull/4965)
- Freeplay capsule week labels are now softcoded and rendered using a font. ([48752e4](https://github.com/FunkinCrew/Funkin/commit/48752e444cc5f1b8cd0a3b579f843e9ab6580c46)) - by @KoloInDaCrib in [#5249](https://github.com/FunkinCrew/Funkin/pull/5249)
- The Freeplay change character hint now changes when a gamepad is connected. ([0f7859b](https://github.com/FunkinCrew/Funkin/commit/0f7859bfb6b829290804efab9d5c67fbdbec0903)) - by @MrMadera in [#6609](https://github.com/FunkinCrew/Funkin/pull/6609)
- Moved the Winter Horrorland intro cutscene logic into a script. ([9bbe73b](https://github.com/FunkinCrew/funkin.assets/commit/9bbe73b21ccbea29a5d5187709f91b4822bf7e31)) - by @mario64thane in [funkin.assets#63](https://github.com/FunkinCrew/funkin.assets/pull/63)
- Merged FlxFilteredSprite functionality into FunkinSprite. ([22736b2](https://github.com/FunkinCrew/Funkin/commit/22736b27da7d8de8b11ab6cc6c2a622e5579dccd)) - by @TechnikTil in [#7114](https://github.com/FunkinCrew/Funkin/pull/7114)
- Adjusted some wording in the Chart/Stage Editor backup window to be clearer. ([a607396](https://github.com/FunkinCrew/Funkin/commit/a607396d04f24388691ee23bd04022681ca54756)) - by @Marcosayfi in [#7071](https://github.com/FunkinCrew/Funkin/pull/7071)
### Fixed
- Conjoined string interpolation `$a$b` now parses properly in Polymod.
- Video cutscenes are no longer muted at volumes of 3 or lower.
- Video cutscenes no longer occasionally show glitches at the beginning.
- [MOBILE] Loading a cloud save from Newgrounds no longer carries over the volume level from Desktop.
- [HTML5] Scrolling the game out of view now pauses the game instead of allowing gameplay to continue processing.
- The Boyfriend Freeplay DJ new rank animation now transitions smoothly back to its idle animation.
- Hold notes now score much more consistently across different framerate values.
- The bricks in Week 7 stages are now better quality.
- Trimmed out the silent beat at the beginning of Ugh Erect.
- Camera bopping no longer stops at zoom values of 1.35x or higher.
- Charting many hold notes in a row no longer breaks audio handling.
- Adding collapsible frames in event schemas no longer crashes the game.
- Some event properties have been grouped under Advanced frames.
- Chart Editor dropdowns no longer refocus when a tooltip appears.
- Focus and Zoom Camera event durations now account for playback speed.
- [WINDOWS] Exiting the game no longer leaves it running as a background process. ([881aba3](https://github.com/FunkinCrew/Funkin/commit/881aba3b03a26764374441cab244cd2d360a30b9)) - by @AnimatingLegend in [#6885](https://github.com/FunkinCrew/Funkin/pull/6885)
- Story Mode now only shows difficulties that all of a level's songs have. ([365f8dc](https://github.com/FunkinCrew/Funkin/commit/365f8dcfea9569f2edba1ebfceb3d49819ad2b57)) - by @Starexify in [#7046](https://github.com/FunkinCrew/Funkin/pull/7046)
- The Girlfriend Story Mode prop now bops continuously when scrolling through levels. ([84b2d5b](https://github.com/FunkinCrew/Funkin/commit/84b2d5b48d9eb76c918fdba6987ccc1f5da76133)) - by @Redar13 in [#6830](https://github.com/FunkinCrew/Funkin/pull/6830)
- The Freeplay new rank slam animation now properly plays its glow effect. ([fcbce0a](https://github.com/FunkinCrew/Funkin/commit/fcbce0a66b75b0c1224c6a0e2907c170b71998ad)) - by @FuroYT in [#7015](https://github.com/FunkinCrew/Funkin/pull/7015)
- The Freeplay Random capsule no longer displays BPM and difficulty numbers. ([0ad2d50](https://github.com/FunkinCrew/Funkin/commit/0ad2d507efa9dcb577184e28bfd04091b3424bfb)) - by @Lasercar in [#4927](https://github.com/FunkinCrew/Funkin/pull/4927)
- Favoriting a song in Freeplay no longer breaks capsule text cycling. ([ce493a0](https://github.com/FunkinCrew/Funkin/commit/ce493a03c9ffb4c43c2c27885ed0fab0c1c3531d)) - by @realvirtu in [#7134](https://github.com/FunkinCrew/Funkin/pull/7134)
- Freeplay songs with invalid pixel icons no longer duplicate the icon from the previous song in the list. ([b3eb709](https://github.com/FunkinCrew/Funkin/commit/b3eb709f4ed535ed2544f3bb530ff3724e07be3f)) - by @FuroYT in [#7006](https://github.com/FunkinCrew/Funkin/pull/7006)
- A Freeplay clear percent of 100% now properly exits to the right when returning to the Main Menu. ([5974c1a](https://github.com/FunkinCrew/Funkin/commit/5974c1a48293f3185c5f249acb9130ebd6b35ae4)) - by @Trayfellow in [#7183](https://github.com/FunkinCrew/Funkin/pull/7183)
- Nudged the Freeplay backing image down by one pixel to align with the bottom of the screen. ([b8c2854](https://github.com/FunkinCrew/Funkin/commit/b8c2854007f36ac7a2b6897eead3f979e11f0ad7)) - by @SuperEric1 in [#6893](https://github.com/FunkinCrew/Funkin/pull/6893)
- Improved performance for songs that use a lot of events. ([3b27ec5](https://github.com/FunkinCrew/Funkin/commit/3b27ec5b66b2fa00d59a77f6ec07aff68e440860)) - by @KoloInDaCrib in [#7171](https://github.com/FunkinCrew/Funkin/pull/7171)
- Adjusted hit window logic to accurately reflect threshold values for all judgments. ([dcb5b3a](https://github.com/FunkinCrew/Funkin/commit/dcb5b3a9358a9bb126153b57aa2d38dc0684c39d)) - by @Rudyrue in [#7104](https://github.com/FunkinCrew/Funkin/pull/7104)
- Adjusted offsets for all health icons to be more consistent. ([83d8134](https://github.com/FunkinCrew/funkin.assets/commit/83d8134f9d0b3cf3b59e9e1d972fa1e200a98ba1)) - by @LeGooeyy in [funkin.assets#278](https://github.com/FunkinCrew/funkin.assets/pull/278)
- Hold notes no longer shift upward when hit early. ([d62c8af](https://github.com/FunkinCrew/Funkin/commit/d62c8af20c90ec3d6e4274aba8ddbfb378ab0256)) - by @realvirtu in [#7060](https://github.com/FunkinCrew/Funkin/pull/7060)
- The opponent no longer stops singing upon missing if Boyfriend has no vocals file. ([cea54e3](https://github.com/FunkinCrew/Funkin/commit/cea54e394c78544dd0ec0339721faaac140caa65)) - by @FuroYT in [#7007](https://github.com/FunkinCrew/Funkin/pull/7007)
- onPause script functions now properly trigger when pausing during a cutscene or dialogue. ([5a0b431](https://github.com/FunkinCrew/Funkin/commit/5a0b4310a2c39b033989e0e36b8f456bdac65a5b)) - by @MightyTheArmiddilo in [#6804](https://github.com/FunkinCrew/Funkin/pull/6804)
- Camera events now consistently pause when the Pause Menu is opened. ([e623439](https://github.com/FunkinCrew/Funkin/commit/e6234397f57d2af37035a0ff2504b8241e23949d)) - by @realvirtu in [#7145](https://github.com/FunkinCrew/Funkin/pull/7145)
- The Pause Menu global offset value now adjusts at the same rate across all framerates. ([348647f](https://github.com/FunkinCrew/Funkin/commit/348647f48629a24ee3bd2b759bbfc1bff168fb81)) - by @KolzeYT in [#7147](https://github.com/FunkinCrew/Funkin/pull/7147)
- Spirit's trail effect now renders consistently across all framerates. ([75506f7](https://github.com/FunkinCrew/Funkin/commit/75506f71a97d468f516a0232c8be5560afb0682e)) - by @KolzeYT in [#7179](https://github.com/FunkinCrew/Funkin/pull/7179)
- The sound tray now appears consistently and plays sound effects at the right volume. ([2b9906d](https://github.com/FunkinCrew/Funkin/commit/2b9906df29660057410d3054e897012896896d6a)) - by @Raltyro in [#7068](https://github.com/FunkinCrew/Funkin/pull/7068)
- The sticker transition now properly pauses when losing focus with Pause on Unfocus enabled. ([8a1d74b](https://github.com/FunkinCrew/Funkin/commit/8a1d74b82cceab97e777dc49e7a2117b8d27e59b)) - by @ComedyLost in [#7129](https://github.com/FunkinCrew/Funkin/pull/7129)
- [HTML5] Rimlight alt masks now render properly. ([0613e9d](https://github.com/FunkinCrew/Funkin/commit/0613e9d295179e66d30db3d2f6805870eac847d6)) - by @realvirtu in [#6900](https://github.com/FunkinCrew/Funkin/pull/6900)
- The Week 2 Erect stage lightning strike fade now pauses and cancels appropriately. ([cd05267](https://github.com/FunkinCrew/funkin.assets/commit/cd05267023859d04cc8920c787b8280682e5f0f5)) - by @ComedyLost in [funkin.assets#390](https://github.com/FunkinCrew/funkin.assets/pull/390)
- A-Bot (Dark)'s frame no longer renders as completely dark in Week 2 Erect. ([a142530](https://github.com/FunkinCrew/funkin.assets/commit/a142530cae6198ca17b560ff73e36d50f1582768)) - by @ComedyLost in [funkin.assets#368](https://github.com/FunkinCrew/funkin.assets/pull/368)
- Dying on the same frame as a lightning strike in Week 2 Erect no longer throws a script error. ([ef89bde](https://github.com/FunkinCrew/funkin.assets/commit/ef89bde19c397f15a53b0fda2f64ba93ff96f56f)) - by @KoloInDaCrib in [funkin.assets#363](https://github.com/FunkinCrew/funkin.assets/pull/363)
- Pico (Dark) and Nene (Dark) no longer throw script errors in debug editors. ([b16ce44](https://github.com/FunkinCrew/funkin.assets/commit/b16ce44beb43d4511c61418c824929fb4dfabb63)) - by @ComedyLost in [funkin.assets#367](https://github.com/FunkinCrew/funkin.assets/pull/367)
- Girlfriend's hair no longer falls when restarting the song in a Week 3 stage. ([ade80ab](https://github.com/FunkinCrew/funkin.assets/commit/ade80ab72915ddd47724c380bb41d6df4c1b79bd)) - by @AnimatingLegend in [funkin.assets#370](https://github.com/FunkinCrew/funkin.assets/pull/370)
- The camera transition to Results no longer reveals the edges of stage art in the Week 6 Erect stage. ([ecf4c54](https://github.com/FunkinCrew/funkin.assets/commit/ecf4c5458a2e1fadba7db31c3272cea485d22b2f)) - by @ComedyLost in [funkin.assets#383](https://github.com/FunkinCrew/funkin.assets/pull/383)
- Fine-tuned offsets for pixel characters. ([8b3c268](https://github.com/FunkinCrew/funkin.assets/commit/8b3c2680a6a966e81b62598e783c60f46355c759)) - by @CEliuxJV in [funkin.assets#376](https://github.com/FunkinCrew/funkin.assets/pull/376)
- Tankman's game over lines now properly play during game overs in Ugh (Pico Mix) and Guns (Pico Mix). ([b900208](https://github.com/FunkinCrew/funkin.assets/commit/b900208143f980adee25d70db247e0b176dd659c)) - by @hucks5 in [funkin.assets#373](https://github.com/FunkinCrew/funkin.assets/pull/373)
- Restarting during the mid-song animation in Stress (Pico Mix) now properly resets the characters' animations. ([2ca92de](https://github.com/FunkinCrew/funkin.assets/commit/2ca92de46eced3f53d305579704fcb7e8c051f3a)) - by @requazar in [funkin.assets#364](https://github.com/FunkinCrew/funkin.assets/pull/364)
- The rain shader now properly fades out with the transition to the Results Screen. ([a0caa41](https://github.com/FunkinCrew/Funkin/commit/a0caa41edcb26298e4f8c243a5eed0b4fe93fcf7)) - by @realvirtu in [#6776](https://github.com/FunkinCrew/Funkin/pull/6776)
- Exiting a Chart Editor playtest while using the pixel notestyle no longer crashes the game. ([6c1f380](https://github.com/FunkinCrew/Funkin/commit/6c1f3800dbc9b13fb4b409abce53c1dafc9bbe8f)) - by @Starexify and @KoloInDaCrib in [#7108](https://github.com/FunkinCrew/Funkin/pull/7108)
- Chart Editor Edit buttons are now appropriately disabled when nothing is selected. ([6b1fc03](https://github.com/FunkinCrew/Funkin/commit/6b1fc0372bca202d80f4ccf316580b13a5a80879)) - by @Lasercar in [#4386](https://github.com/FunkinCrew/Funkin/pull/4386)
- Undoing a Chart Editor event now plays the undo sound. ([f7fd7a5](https://github.com/FunkinCrew/Funkin/commit/f7fd7a57c36f0461f56c2ab627a17d752cb82320)) - by @realvirtu in [#6963](https://github.com/FunkinCrew/Funkin/pull/6963)
- The playback speed audio setting no longer rounds incorrectly upon reopening the Chart Editor. ([3b15873](https://github.com/FunkinCrew/Funkin/commit/3b15873fc7d0c20840c313f1d2cfed91014c664f)) - by @AnimatingLegend in [#7023](https://github.com/FunkinCrew/Funkin/pull/7023)
- The Chart Editor easing preview graph now properly displays tweens that exceed start/end values. ([7626700](https://github.com/FunkinCrew/Funkin/commit/7626700495743862caddbf50a7dafef51529a2a6)) - by @echolotl in [#7152](https://github.com/FunkinCrew/Funkin/pull/7152)
- The Chart Editor playbar head is no longer draggable during a playtest. ([ccb874e](https://github.com/FunkinCrew/Funkin/commit/ccb874e97a121859c26a8a71b394743d27f6ed37)) - by @ComedyLost in [#6987](https://github.com/FunkinCrew/Funkin/pull/6987)
- The Results Screen no longer shows up after a Chart Editor playtest with Bot Play enabled. ([786f19c](https://github.com/FunkinCrew/Funkin/commit/786f19c57d999dba9309cae28d912b080968670d)) - by @ComedyLost in [#7022](https://github.com/FunkinCrew/Funkin/pull/7022)
- The Osu!Mania Chart Editor importer no longer accepts non-Osu!Mania beatmaps. ([456b2ff](https://github.com/FunkinCrew/Funkin/commit/456b2ff6c4a127733120cef3d03d6102bdd7522f)) - by @FuroYT in [#6624](https://github.com/FunkinCrew/Funkin/pull/6624)
- Characters in the Stage Editor no longer fly away when clicking and dragging them. ([0389af2](https://github.com/FunkinCrew/Funkin/commit/0389af2202aa4dc6a21ce9b7eea95944bfaa6946)) - by @KoloInDaCrib in [#7002](https://github.com/FunkinCrew/Funkin/pull/7002)
- Characters with alternating idle animations now properly play danceLeft when pressing Space in the Animation Editor. ([05032e3](https://github.com/FunkinCrew/Funkin/commit/05032e3126eda78a2bbf70e8c975bcb04eed201b)) - by @ComedyLost in [#7056](https://github.com/FunkinCrew/Funkin/pull/7056)
- [LINUX] Paths are now properly sanitized as they are on other platforms. ([219143c](https://github.com/FunkinCrew/Funkin/commit/219143c02dcf65e68aec80701a82023ca0d70db6)) - by @NotHyper-474 in [#6395](https://github.com/FunkinCrew/Funkin/pull/6395)
- OpenFL and some Lime classes are now accessible to modders. ([56a56db](https://github.com/FunkinCrew/Funkin/commit/56a56dbfaa3f62a3f684df49c682f69a496e45f4)) - by @FuroYT in [#7115](https://github.com/FunkinCrew/Funkin/pull/7115)
- Sandboxed API classes can now be accessed by mods. ([03930a2](https://github.com/FunkinCrew/Funkin/commit/03930a29c3d8aa6a310147a7131c6b7cddefd475)) - by @MightyTheArmiddilo in [#6952](https://github.com/FunkinCrew/Funkin/pull/6952)
- Blacklisted some more classes for security.
- And even more fixes!
## New Contributors for 0.8.4
* @roma-perec-bp made their first contribution in [#6769](https://github.com/FunkinCrew/Funkin/pull/6769)
* @Redar13 made their first contribution in [#6830](https://github.com/FunkinCrew/Funkin/pull/6830)
* @SuperEric1 made their first contribution in [#6893](https://github.com/FunkinCrew/Funkin/pull/6893)
* @AnimatingLegend made their first contribution in [#7023](https://github.com/FunkinCrew/Funkin/pull/7023)
* @Marcosayfi made their first contribution in [#7071](https://github.com/FunkinCrew/Funkin/pull/7071)
* @Rudyrue made their first contribution in [#7104](https://github.com/FunkinCrew/Funkin/pull/7104)
* @KolzeYT made their first contribution in [#7147](https://github.com/FunkinCrew/Funkin/pull/7147)
* @echolotl made their first contribution in [#7152](https://github.com/FunkinCrew/Funkin/pull/7152)
* @mario64thane made their first contribution in [funkin.assets#63](https://github.com/FunkinCrew/funkin.assets/pull/63)
* @LeGooeyy made their first contribution in [funkin.assets#278](https://github.com/FunkinCrew/funkin.assets/pull/278)
* @requazar made their first contribution in [funkin.assets#364](https://github.com/FunkinCrew/funkin.assets/pull/364)
## [0.8.3] - 2026-02-23
### Fixed
@@ -102,21 +339,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Scrolling really quickly in Freeplay no longer crashes the game. ([76699b2](https://github.com/FunkinCrew/Funkin/commit/76699b235cd5b359bc34e6950cd05bbbb13918f8)) - by @ComedyLost in [#6962](https://github.com/FunkinCrew/Funkin/pull/6962)
- Fixed a memory leak in the Freeplay menu. ([910ba65](https://github.com/FunkinCrew/Funkin/commit/910ba650b0c1011802b151b85f4a9d8177ae95c7)) - by @KoloInDaCrib in [#6615](https://github.com/FunkinCrew/Funkin/pull/6615)
- Modded difficulty dots and graphics now render correctly in Freeplay. ([90b856d](https://github.com/FunkinCrew/Funkin/commit/90b856d88635ac4e5517e934298e3820b2e5f45c)) - by @ComedyLost in [#6205](https://github.com/FunkinCrew/Funkin/pull/6205)
- Freeplay capsules with long song names no longer display too far to the left during the new rank animation. ([17a914c](https://github.com/FunkinCrew/Funkin/commit/17a914c933592cb3ba79881ca6a8d900b8513cbc)) - by @VirtuGuy in [#6690](https://github.com/FunkinCrew/Funkin/pull/6690)
- Freeplay capsule BPM values ending in 1 now display with proper spacing. ([e5b4351](https://github.com/FunkinCrew/Funkin/commit/e5b43510dd810a74a7d06f7f02c52892d11d6f8b)) - by @VirtuGuy in [#6696](https://github.com/FunkinCrew/Funkin/pull/6696)
- The Freeplay pixel icon now properly plays its confirm animation when mashing the capsule. ([a56bc44](https://github.com/FunkinCrew/Funkin/commit/a56bc4462d1c49e8ec71462b9bd7ff338b743c93)) - by @VirtuGuy in [#6723](https://github.com/FunkinCrew/Funkin/pull/6723)
- [HTML5] Scrolling with the mouse now works properly in Story Mode and Freeplay. ([506d80b](https://github.com/FunkinCrew/Funkin/commit/506d80b287b969121dc3601714c2459cc71f7e55)) - by @VirtuGuy in [#6621](https://github.com/FunkinCrew/Funkin/pull/6621)
- Freeplay capsules with long song names no longer display too far to the left during the new rank animation. ([17a914c](https://github.com/FunkinCrew/Funkin/commit/17a914c933592cb3ba79881ca6a8d900b8513cbc)) - by @realvirtu in [#6690](https://github.com/FunkinCrew/Funkin/pull/6690)
- Freeplay capsule BPM values ending in 1 now display with proper spacing. ([e5b4351](https://github.com/FunkinCrew/Funkin/commit/e5b43510dd810a74a7d06f7f02c52892d11d6f8b)) - by @realvirtu in [#6696](https://github.com/FunkinCrew/Funkin/pull/6696)
- The Freeplay pixel icon now properly plays its confirm animation when mashing the capsule. ([a56bc44](https://github.com/FunkinCrew/Funkin/commit/a56bc4462d1c49e8ec71462b9bd7ff338b743c93)) - by @realvirtu in [#6723](https://github.com/FunkinCrew/Funkin/pull/6723)
- [HTML5] Scrolling with the mouse now works properly in Story Mode and Freeplay. ([506d80b](https://github.com/FunkinCrew/Funkin/commit/506d80b287b969121dc3601714c2459cc71f7e55)) - by @realvirtu in [#6621](https://github.com/FunkinCrew/Funkin/pull/6621)
- Optimized rendering in the Character Select menu. ([2ecebf7](https://github.com/FunkinCrew/Funkin/commit/2ecebf79205a66b64148d64bbb3162c9fc073d85)) - by @MaybeMaru in [#6789](https://github.com/FunkinCrew/Funkin/pull/6789)
- [MOBILE] Tapping on a lock in Character Select now plays its reject animation. ([05148f0](https://github.com/FunkinCrew/Funkin/commit/05148f0e5dad4d60089e6074e616b583ba29a5e6)) - by @VirtuGuy in [#6779](https://github.com/FunkinCrew/Funkin/pull/6779)
- [MOBILE] Tapping on a lock in Character Select now plays its reject animation. ([05148f0](https://github.com/FunkinCrew/Funkin/commit/05148f0e5dad4d60089e6074e616b583ba29a5e6)) - by @realvirtu in [#6779](https://github.com/FunkinCrew/Funkin/pull/6779)
- Hold note covers now follow when the strumline position is modified. ([77c6651](https://github.com/FunkinCrew/Funkin/commit/77c6651e245ea276b1bdf33e5d6732073dcb6037)) - by @MightyTheArmiddilo in [#6746](https://github.com/FunkinCrew/Funkin/pull/6746)
- The pause and game over screens no longer sometimes play the wrong character's themes. ([878644a](https://github.com/FunkinCrew/Funkin/commit/878644aee7ba425e482707b94b9f887ec23f6306)) - by @KoloInDaCrib in [#6812](https://github.com/FunkinCrew/Funkin/pull/6812)
- The game over camera focus point is now consistent, regardless of which animation was previously playing. ([18cceb4](https://github.com/FunkinCrew/Funkin/commit/18cceb4946a51fda0009d77baae1115437694415)) - by @KoloInDaCrib in [#6705](https://github.com/FunkinCrew/Funkin/pull/6705)
- Pico (Pixel) and other pixel characters now use RetroCameraFade as Boyfriend (Pixel) does. ([d1382aa](https://github.com/FunkinCrew/Funkin/commit/d1382aa985f97e3b40b0b629cb3d04301ebfb55e)) - by @afreetoplaynoob in [#6526](https://github.com/FunkinCrew/Funkin/pull/6526)
- [MOBILE] The back button can no longer exit during the Boyfriend fakeout death animation. ([9d06018](https://github.com/FunkinCrew/Funkin/commit/9d0601813e912de9e25a851ad9204a654316625a)) - by @ActualMandM in [#6917](https://github.com/FunkinCrew/Funkin/pull/6917)
- The song name text is now properly hidden at the beginning of the Results Screen animation. ([a5b15b9](https://github.com/FunkinCrew/Funkin/commit/a5b15b9424f16d8eadc7a92f1c355da647990c3a)) - by @NotHyper-474 and @Trayfellow in [#6931](https://github.com/FunkinCrew/Funkin/pull/6931)
- The sticker transition no longer covers the volume soundtray. ([616546d](https://github.com/FunkinCrew/Funkin/commit/616546d298a06c4135a32ffad41483be208552f1)) - by @VirtuGuy in [#6727](https://github.com/FunkinCrew/Funkin/pull/6727)
- The sticker transition no longer covers the volume soundtray. ([616546d](https://github.com/FunkinCrew/Funkin/commit/616546d298a06c4135a32ffad41483be208552f1)) - by @realvirtu in [#6727](https://github.com/FunkinCrew/Funkin/pull/6727)
- Lightning now appears more regularly during South Erect and South (Pico Mix). ([9ca2092](https://github.com/FunkinCrew/funkin.assets/commit/9ca20929bc3dde6b07d74100c45fb45e48769c35)) - by @JackXson-Real in [funkin.assets#345](https://github.com/FunkinCrew/funkin.assets/pull/345)
- [HTML5] The city lights in the Week 3 stages now show up. ([603684f](https://github.com/FunkinCrew/funkin.assets/commit/603684ffb327f03d8216aaeaba143ca5f9cd77f0)) - by @VirtuGuy in [funkin.assets#342](https://github.com/FunkinCrew/funkin.assets/pull/342)
- [HTML5] The city lights in the Week 3 stages now show up. ([603684f](https://github.com/FunkinCrew/funkin.assets/commit/603684ffb327f03d8216aaeaba143ca5f9cd77f0)) - by @realvirtu in [funkin.assets#342](https://github.com/FunkinCrew/funkin.assets/pull/342)
- The Week 3 Pico doppelganger cutscene background music no longer cuts off at the end. ([8ef58aa](https://github.com/FunkinCrew/funkin.assets/commit/8ef58aabdba8287d4c88808e2f0ecc0ac385b383)) - by @Trayfellow in [funkin.assets#349](https://github.com/FunkinCrew/funkin.assets/pull/349)
- The Story Mode cutscene before Stress now properly plays when viewed more than once. ([6ec45ec](https://github.com/FunkinCrew/funkin.assets/commit/6ec45ec82ca77188b1b2b9c58ada172f5c357103)) - by @NotHyper-474 in [funkin.assets#341](https://github.com/FunkinCrew/funkin.assets/pull/341)
- Darnell's can sound effects in 2hot no longer play twice with high offsets or when lagging. ([6315e25](https://github.com/FunkinCrew/funkin.assets/commit/6315e25eaaa8be4ca85e9b607f547595c699997a)) - by @JackXson-Real in [funkin.assets#354](https://github.com/FunkinCrew/funkin.assets/pull/354)
@@ -129,8 +366,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The Chart Editor vocal waveforms now display in the proper position regardless of the game's aspect ratio. ([1fb9040](https://github.com/FunkinCrew/Funkin/commit/1fb9040470432528a0441d7938d217e424ce27fd)) - by @Starexify in [#6193](https://github.com/FunkinCrew/Funkin/pull/6193)
- The second section number and divider now renders consistently in the Chart Editor. ([ac539bd](https://github.com/FunkinCrew/Funkin/commit/ac539bdf26ee7b5ecdcc52665c7c95287ef491c0)) - by @NotHyper-474 in [#6765](https://github.com/FunkinCrew/Funkin/pull/6765)
- The Chart Editor now saves the Show Results Screen setting. ([c893a73](https://github.com/FunkinCrew/Funkin/commit/c893a7320d72abd3743bc5c1ddeaecf073035eb1)) - by @MightyTheArmiddilo in [#6854](https://github.com/FunkinCrew/Funkin/pull/6854)
- Closing the game while in the Stage Editor no longer crashes the game. ([99cd4e2](https://github.com/FunkinCrew/Funkin/commit/99cd4e2cbd7fba87249b02b072a1e60f07c2c907)) - by @VirtuGuy in [#6775](https://github.com/FunkinCrew/Funkin/pull/6775)
- The onion skin now properly renders as transparent after changing characters in the Animation Editor. ([5c444f1](https://github.com/FunkinCrew/Funkin/commit/5c444f1109e5af04735a4383e577c69682b3713f)) - by @VirtuGuy in [#6545](https://github.com/FunkinCrew/Funkin/pull/6545)
- Closing the game while in the Stage Editor no longer crashes the game. ([99cd4e2](https://github.com/FunkinCrew/Funkin/commit/99cd4e2cbd7fba87249b02b072a1e60f07c2c907)) - by @realvirtu in [#6775](https://github.com/FunkinCrew/Funkin/pull/6775)
- The onion skin now properly renders as transparent after changing characters in the Animation Editor. ([5c444f1](https://github.com/FunkinCrew/Funkin/commit/5c444f1109e5af04735a4383e577c69682b3713f)) - by @realvirtu in [#6545](https://github.com/FunkinCrew/Funkin/pull/6545)
- Blacklisted a class for security. ([3a113c2](https://github.com/FunkinCrew/Funkin/commit/3a113c270f92a6b14dfcda221124742437e1670a)) - by @charlesisfeline in [#6573](https://github.com/FunkinCrew/Funkin/pull/6573)
- Even more tiny fixes!
@@ -215,7 +452,7 @@ The LE SSERAFIM collab update!
- Freeplay song previews now fade out before restarting. ([aaf5084](https://github.com/FunkinCrew/Funkin/commit/aaf5084fd9e9c2d3b7e823767a93db82ce908d86)) - by @JVNpixels in [#6094](https://github.com/FunkinCrew/Funkin/pull/6094)
- The game's volume is now reduced when unfocused without pausing. ([3040692](https://github.com/FunkinCrew/Funkin/commit/30406928522f88762eab4bbf571fedf1424f7569)) - by @PurSnake in [#6250](https://github.com/FunkinCrew/Funkin/pull/6250)
- Optimized the way the windows in Week 3 are handled. ([70d433d](https://github.com/FunkinCrew/funkin.assets/commit/70d433de3027badb39027d295d1b18d20a130741)) - by @CrusherNotDrip in [funkin.assets#291](https://github.com/FunkinCrew/funkin.assets/pull/291)
- Script create events now also run after hot-reloading with F5, rather than only during initialization. ([2f865a5](https://github.com/FunkinCrew/Funkin/commit/2f865a5c7f4d8712f1b1e0bc70cb910f4fed08dc)) - by @VirtuGuy in [#6084](https://github.com/FunkinCrew/Funkin/pull/6084)
- Script create events now also run after hot-reloading with F5, rather than only during initialization. ([2f865a5](https://github.com/FunkinCrew/Funkin/commit/2f865a5c7f4d8712f1b1e0bc70cb910f4fed08dc)) - by @realvirtu in [#6084](https://github.com/FunkinCrew/Funkin/pull/6084)
- Hot-reloading with F5 during a Chart Editor playtest no longer returns to the Chart Editor. ([c1988f1](https://github.com/FunkinCrew/Funkin/commit/c1988f1858344a78a82bf335774d986703cac942)) - by @KoloInDaCrib in [#6275](https://github.com/FunkinCrew/Funkin/pull/6275)
- Opening the Chart Editor during a song now places the playhead at the current song position. ([71b4a58](https://github.com/FunkinCrew/Funkin/commit/71b4a58cab821c3b5a530e3a2be6d73966faa2a6)) - by @KoloInDaCrib in [#6210](https://github.com/FunkinCrew/Funkin/pull/6210)
- The Easing property for Chart Editor events is now split into two separate dropdowns: type and direction. ([d1d77dd](https://github.com/FunkinCrew/Funkin/commit/d1d77dd85c3daed22ee954353fa41e81279ced3c)) - by @PurSnake in [#5612](https://github.com/FunkinCrew/Funkin/pull/5612)
@@ -275,7 +512,7 @@ The LE SSERAFIM collab update!
- Pause on Unfocus now properly applies to Chart Editor playtests.
- Unfocusing while the Chart Editor is playing audio now pauses the playback.
- Fixed a memory leak with the Freeplay backing card scrolling text. ([67846d6](https://github.com/FunkinCrew/Funkin/commit/67846d6c4bfd2f42e002fa129a51772f0717329d)) - by @FuroYT in [#5963](https://github.com/FunkinCrew/Funkin/pull/5963)
- Using a static pixel icon in Character Select no longer crashes the game. ([96f8ee8](https://github.com/FunkinCrew/Funkin/commit/96f8ee85e0c2281834b7334b87d1862003e5fa05)) - by @VirtuGuy in [#6171](https://github.com/FunkinCrew/Funkin/pull/6171)
- Using a static pixel icon in Character Select no longer crashes the game. ([96f8ee8](https://github.com/FunkinCrew/Funkin/commit/96f8ee85e0c2281834b7334b87d1862003e5fa05)) - by @realvirtu in [#6171](https://github.com/FunkinCrew/Funkin/pull/6171)
- A-Bot's visualizer no longer causes a memory leak during gameplay or in Character Select. ([6607645](https://github.com/FunkinCrew/Funkin/commit/6607645786ed8611436fa5f92a35027c2a64f1d0)) - by @FuroYT in [#5908](https://github.com/FunkinCrew/Funkin/pull/5908)
- The Credits menu no longer crashes when not using hardcoded credits. ([4366fbe](https://github.com/FunkinCrew/Funkin/commit/4366fbe51274438ad2bc190afcca42e37987386d)) - by @sphis-sinco in [#5982](https://github.com/FunkinCrew/Funkin/pull/5982)
- The game no longer lag spikes when Darnell throws his can in 2hot. ([a0bc6d6](https://github.com/FunkinCrew/funkin.assets/commit/a0bc6d61fde5799a7fc619b7fdea691b0d8bae05)) - by @KoloInDaCrib in [funkin.assets#313](https://github.com/FunkinCrew/funkin.assets/pull/313)
@@ -285,12 +522,12 @@ The LE SSERAFIM collab update!
- [ANDROID] Keyboard detection and strumline positioning now work properly. ([5763ae5](https://github.com/FunkinCrew/Funkin/commit/5763ae5b728359c5639bbc578f15b65a16fa57b1)) - by @NotHyper-474 in [#6328](https://github.com/FunkinCrew/Funkin/pull/6328)
- The game now properly parses .json files beginning with a bracket. ([c7367ae](https://github.com/FunkinCrew/Funkin/commit/c7367ae33d7e11f57b821f7d5fbff39a3edc1604)) - by @NotHyper-474 in [#6164](https://github.com/FunkinCrew/Funkin/pull/6164)
- The Newgrounds logo no longer covers the intro text. ([28883fb](https://github.com/FunkinCrew/Funkin/commit/28883fb9ed025abf9f9aee2621f365cd6f4d8b6c)) - by @hucks5 in [#6196](https://github.com/FunkinCrew/Funkin/pull/6196)
- Exiting from the Save Data Options menu no longer exits the Options Menu as well. ([26b253d](https://github.com/FunkinCrew/Funkin/commit/26b253d8cac97f0dcd09a5ef233f7058cd26008e)) - by @VirtuGuy in [#6036](https://github.com/FunkinCrew/Funkin/pull/6036)
- Exiting from the Save Data Options menu no longer exits the Options Menu as well. ([26b253d](https://github.com/FunkinCrew/Funkin/commit/26b253d8cac97f0dcd09a5ef233f7058cd26008e)) - by @realvirtu in [#6036](https://github.com/FunkinCrew/Funkin/pull/6036)
- Numeric values in the Options Menu are now rounded to prevent near-zero precision errors. ([934bce7](https://github.com/FunkinCrew/Funkin/commit/934bce7bdc5780e09623d845eda97a27c0ad0ecf)) - by @Starexify in [#6225](https://github.com/FunkinCrew/Funkin/pull/6225)
- The Test/Offset Calibration menu no longer starts playing after exiting the Lag Adjustment menu. ([23a38f7](https://github.com/FunkinCrew/Funkin/commit/23a38f76f9c79c5fab5b9af5e2d98e51597e05a8)) - by @VioletSnowLeopard in [#6088](https://github.com/FunkinCrew/Funkin/pull/6088)
- [MOBILE] The Back button now fades out when entering a Week in Story Mode. ([1ebce74](https://github.com/FunkinCrew/Funkin/commit/1ebce748d4e3306b4464a7bf82fab56bcb427a62)) - by @VirtuGuy in [#6255](https://github.com/FunkinCrew/Funkin/pull/6255)
- [MOBILE] The Back button now fades out when entering a Week in Story Mode. ([1ebce74](https://github.com/FunkinCrew/Funkin/commit/1ebce748d4e3306b4464a7bf82fab56bcb427a62)) - by @realvirtu in [#6255](https://github.com/FunkinCrew/Funkin/pull/6255)
- The Freeplay difficulty can now only be changed in one direction at a time. ([95af46c](https://github.com/FunkinCrew/Funkin/commit/95af46cbf72291d9d3226df91ed17f1aa3d3839f)) - by @Starexify in [#6262](https://github.com/FunkinCrew/Funkin/pull/6262)
- Pico's backing card now renders properly in widescreen aspect ratios. ([aa29b3d](https://github.com/FunkinCrew/funkin.assets/commit/aa29b3dcc1ee2f8e89d2622c480b2e997410d57d)) - by @VirtuGuy in [funkin.assets#297](https://github.com/FunkinCrew/funkin.assets/pull/297)
- Pico's backing card now renders properly in widescreen aspect ratios. ([aa29b3d](https://github.com/FunkinCrew/funkin.assets/commit/aa29b3dcc1ee2f8e89d2622c480b2e997410d57d)) - by @realvirtu in [funkin.assets#297](https://github.com/FunkinCrew/funkin.assets/pull/297)
- The album titles in Freeplay are now positioned consistently. ([ed8cca4](https://github.com/FunkinCrew/funkin.assets/commit/ed8cca4694a098ae6aa56c4d2a231587edb9688c)) - by @Donothan73 in [funkin.assets#257](https://github.com/FunkinCrew/funkin.assets/pull/257)
- Health icons now bop independently from the framerate. ([8e6fa51](https://github.com/FunkinCrew/Funkin/commit/8e6fa51c27ceaa830efec06bb8a52e281a008255)) - by @PurSnake in [#6035](https://github.com/FunkinCrew/Funkin/pull/6035)
- The note resetting animation on song restart is now consistent between Downscroll and Upscroll. ([7b8d657](https://github.com/FunkinCrew/Funkin/commit/7b8d6577eddba568f20c3d23663dded054699090)) - by @FuroYT in [#6220](https://github.com/FunkinCrew/Funkin/pull/6220)
@@ -299,19 +536,19 @@ The LE SSERAFIM collab update!
- The path for a notestyle's countdown sound is now properly loaded as a sound instead of an image. ([dd5ea77](https://github.com/FunkinCrew/Funkin/commit/dd5ea7748b3b1878139998c209aa06db0fa05e0b)) - by @gamerbross in [#6232](https://github.com/FunkinCrew/Funkin/pull/6232)
- The Pause Menu theme no longer plays at maximum volume for a split second when pausing. ([6ba44d6](https://github.com/FunkinCrew/Funkin/commit/6ba44d6cb0c71deb29eb23b82b61f58b2e95193e)) - by @ComedyLost in [#6334](https://github.com/FunkinCrew/Funkin/pull/6334)
- The scrolling text in the Results Screen is now positioned consistently. ([200f798](https://github.com/FunkinCrew/Funkin/commit/200f7984379cb1bd911e49de92be312750893420)) - by @NotHyper-474 in [#6595](https://github.com/FunkinCrew/Funkin/pull/6595)
- The scrolling text in the Results Screen is now FPS-independent. ([8c43f6f](https://github.com/FunkinCrew/Funkin/commit/8c43f6f67a362bde4de4ad8dbd72966d7c4a9f60)) - by @VirtuGuy in [#6476](https://github.com/FunkinCrew/Funkin/pull/6476)
- The scrolling text in the Results Screen is now FPS-independent. ([8c43f6f](https://github.com/FunkinCrew/Funkin/commit/8c43f6f67a362bde4de4ad8dbd72966d7c4a9f60)) - by @realvirtu in [#6476](https://github.com/FunkinCrew/Funkin/pull/6476)
- The Results Screen theme now loops more smoothly. ([592bf1a](https://github.com/FunkinCrew/Funkin/commit/592bf1a9221d4dcef53ae421571eddf78ed631e4)) - by @FuroYT in [#6477](https://github.com/FunkinCrew/Funkin/pull/6477)
- Transition stickers now render properly with the window resized to any aspect ratio. ([4215b1c](https://github.com/FunkinCrew/Funkin/commit/4215b1c72e4391b2176014825885799b81dde2ba)) - by @PurSnake in [#6156](https://github.com/FunkinCrew/Funkin/pull/6156)
- Boyfriend now stands in the same position in the Week 3 and Week 3 Erect stages. ([d2d15f1](https://github.com/FunkinCrew/funkin.assets/commit/d2d15f114256125d53c6331b46415701ae291c1f)) - by @CEliuxJV in [funkin.assets#261](https://github.com/FunkinCrew/funkin.assets/pull/261)
- Pico's game over music now properly loops after his explosion death in 2hot. ([f1a1db0](https://github.com/FunkinCrew/Funkin/commit/f1a1db08347c3f9248fd16909cff06027297ad13)) - by @KoloInDaCrib in [#6216](https://github.com/FunkinCrew/Funkin/pull/6216)
- 2hot now smoothly transitions into the cutscene. ([462b1b6](https://github.com/FunkinCrew/funkin.assets/commit/462b1b6e6e9b622ad8fd15f15a1f39c7dffa4764)) - by @hucks5 in [funkin.assets#286](https://github.com/FunkinCrew/funkin.assets/pull/286)
- Nene now swings her legs during in-game cutscenes. ([6a5d9b2](https://github.com/FunkinCrew/funkin.assets/commit/6a5d9b265732d60da28083fb1c3d7b7b854edf63)) - by @hucks5 in [funkin.assets#289](https://github.com/FunkinCrew/funkin.assets/pull/289)
- Nene's 50 combo animation now renders its heart properly. ([bcd96ee](https://github.com/FunkinCrew/funkin.assets/commit/bcd96eeb78b9b03cf7b24dc956ac3bc36438193e)) - by @VirtuGuy in [funkin.assets#296](https://github.com/FunkinCrew/funkin.assets/pull/296)
- Nene's 50 combo animation now renders its heart properly. ([bcd96ee](https://github.com/FunkinCrew/funkin.assets/commit/bcd96eeb78b9b03cf7b24dc956ac3bc36438193e)) - by @realvirtu in [funkin.assets#296](https://github.com/FunkinCrew/funkin.assets/pull/296)
- A-Bot (Christmas) now properly looks at the opponent. ([f81cc16](https://github.com/FunkinCrew/funkin.assets/commit/f81cc16c8f99655f76b7e27ce221819798c9c94e)) - by @ComedyLost in [funkin.assets#279](https://github.com/FunkinCrew/funkin.assets/pull/279)
- Nene (Pixel) now raises and lowers her knife properly. ([1d9f50d](https://github.com/FunkinCrew/funkin.assets/commit/1d9f50d405f202e07efd883aeef5d6c1e9eaaa90)) - by @VirtuGuy in [funkin.assets#274](https://github.com/FunkinCrew/funkin.assets/pull/274)
- Nene (Pixel) now raises and lowers her knife properly. ([1d9f50d](https://github.com/FunkinCrew/funkin.assets/commit/1d9f50d405f202e07efd883aeef5d6c1e9eaaa90)) - by @realvirtu in [funkin.assets#274](https://github.com/FunkinCrew/funkin.assets/pull/274)
- Pico (Pixel)'s game over theme now plays at the right time. ([e8a4d24](https://github.com/FunkinCrew/funkin.assets/commit/e8a4d2472ca2dc28b03be05953dff3d7b5ec7433)) - by @JackXson-Real and @ComedyLost in [funkin.assets#288](https://github.com/FunkinCrew/funkin.assets/pull/288)
- Pico holding Nene's idle animation no longer lasts too long. ([3483345](https://github.com/FunkinCrew/funkin.assets/commit/348334583746ec45f1c6ab2c5e1715a67038cc5c)) - by @JackXson-Real in [funkin.assets#271](https://github.com/FunkinCrew/funkin.assets/pull/271)
- The tankmen in Stress no longer briefly appear behind the speakers when restarting. ([7f79ad8](https://github.com/FunkinCrew/funkin.assets/commit/7f79ad8c08d66fb909a9382de2c09f0430b756f1)) - by @VirtuGuy in [funkin.assets#298](https://github.com/FunkinCrew/funkin.assets/pull/298)
- The tankmen in Stress no longer briefly appear behind the speakers when restarting. ([7f79ad8](https://github.com/FunkinCrew/funkin.assets/commit/7f79ad8c08d66fb909a9382de2c09f0430b756f1)) - by @realvirtu in [funkin.assets#298](https://github.com/FunkinCrew/funkin.assets/pull/298)
- Encountering a Set Health Icon event during Minimal playtesting no longer crashes the Chart Editor. ([9f0a498](https://github.com/FunkinCrew/Funkin/commit/9f0a4988a3cc47581916a9750731bb7e63f168f3)) - by @charlesisfeline in [#6481](https://github.com/FunkinCrew/Funkin/pull/6481)
- Typing in Chart Editor text fields no longer triggers bound key functions. ([3b5e589](https://github.com/FunkinCrew/Funkin/commit/3b5e5893c01c2b56036e53626eaea8d41e70f640)) - by @MightyTheArmiddilo in [#6601](https://github.com/FunkinCrew/Funkin/pull/6601)
- Clicking between Chart Editor events no longer converts the second event's dropdown values into those of the first. ([c170c25](https://github.com/FunkinCrew/Funkin/commit/c170c256934ae316a735d38620ad5e24c2f15f4d)) - by @NotHyper-474 in [#6211](https://github.com/FunkinCrew/Funkin/pull/6211)
@@ -319,19 +556,19 @@ The LE SSERAFIM collab update!
- Placing a note and removing it no longer breaks the cursor in the Chart Editor. ([8cb5ed9](https://github.com/FunkinCrew/Funkin/commit/8cb5ed91baf50b6f78eefc2e50612a01195a2742)) - by @Lasercar in [#4237](https://github.com/FunkinCrew/Funkin/pull/4237)
- Playtesting in the Chart Editor now properly loads song variation scripts. ([055f620](https://github.com/FunkinCrew/Funkin/commit/055f62026ef44a928876d9065cc388da0905e9f1)) - by @PurSnake in [#6405](https://github.com/FunkinCrew/Funkin/pull/6405)
- Playtesting in the Chart Editor no longer sometimes moves on to another song like Story Mode. ([9497378](https://github.com/FunkinCrew/Funkin/commit/9497378600bad44639ff8b3fc92cb329052fd08a)) - by @KoloInDaCrib in [#6192](https://github.com/FunkinCrew/Funkin/pull/6192)
- The cursor is now hidden when playtesting through the Chart Editor. ([0471872](https://github.com/FunkinCrew/Funkin/commit/047187257b6712e61bf05fdebab33c7b3e9ac0f6)) - by @VirtuGuy in [#6137](https://github.com/FunkinCrew/Funkin/pull/6137)
- The cursor is now hidden when playtesting through the Chart Editor. ([0471872](https://github.com/FunkinCrew/Funkin/commit/047187257b6712e61bf05fdebab33c7b3e9ac0f6)) - by @realvirtu in [#6137](https://github.com/FunkinCrew/Funkin/pull/6137)
- The Chart Editor note moving sound no longer plays when dragging outside the grid. ([593456e](https://github.com/FunkinCrew/Funkin/commit/593456e53e02c53e71189fdb154e4a3e4f2b3092)) - by @amyspark-ng in [#4157](https://github.com/FunkinCrew/Funkin/pull/4157)
- The Chart Editor music now fades in after a period of silence when enabled. ([960d2f3](https://github.com/FunkinCrew/Funkin/commit/960d2f3cf166400c6fecee212b87961f3df10c2e)) - by @Lasercar in [#4148](https://github.com/FunkinCrew/Funkin/pull/4148)
- The Chart Editor Difficulty toolbox no longer displays the incorrect song name. ([dff2a1e](https://github.com/FunkinCrew/Funkin/commit/dff2a1e487dc20f86ef4f526a259083a7726ea6a)) - by @VirtuGuy in [#6547](https://github.com/FunkinCrew/Funkin/pull/6547)
- The Chart Editor Difficulty toolbox no longer displays the incorrect song name. ([dff2a1e](https://github.com/FunkinCrew/Funkin/commit/dff2a1e487dc20f86ef4f526a259083a7726ea6a)) - by @realvirtu in [#6547](https://github.com/FunkinCrew/Funkin/pull/6547)
- Chart Editor notifications now display a bit higher. ([9e645db](https://github.com/FunkinCrew/Funkin/commit/9e645db0074424ffb2de42b27afb3adaff55de62)) - by @MightyTheArmiddilo in [#6445](https://github.com/FunkinCrew/Funkin/pull/6445)
- The Yes and No text in the Chart Editor exit confirmation prompt buttons now always render properly. ([4c0d925](https://github.com/FunkinCrew/Funkin/commit/4c0d92507ae0b81a744d223e5292bf8d27013abd)) - by @NotHyper-474 in [#6173](https://github.com/FunkinCrew/Funkin/pull/6173)
- Exiting the Chart Editor now consistently saves your audio preferences. ([2f77ccf](https://github.com/FunkinCrew/Funkin/commit/2f77ccfc6e93fabef27d3e06447f9f6edd8e840d)) - by @VioletSnowLeopard in [#6127](https://github.com/FunkinCrew/Funkin/pull/6127)
- The Chart Editor and Stage Editor backup window now properly retrieves the most recently edited backup. ([a8dec0c](https://github.com/FunkinCrew/Funkin/commit/a8dec0cd7053f88865757f30a7d9f0ca5eb0fb02)) - by @Lasercar in [#6119](https://github.com/FunkinCrew/Funkin/pull/6119)
- The Chart Editor backup dialog no longer appears if the latest backup is deleted. ([bc1d36d](https://github.com/FunkinCrew/Funkin/commit/bc1d36ddeab81a790e3604598248a9b2fe869cac)) - by @KoloInDaCrib in [#6027](https://github.com/FunkinCrew/Funkin/pull/6027)
- Switching between Animation and Spritesheet mode no longer crashes the Animation Editor. ([a61016d](https://github.com/FunkinCrew/Funkin/commit/a61016d2dfc2ac6a50aae230969c036f0753cfaa)) - by @VirtuGuy in [#6114](https://github.com/FunkinCrew/Funkin/pull/6114)
- Switching between Animation and Spritesheet mode no longer crashes the Animation Editor. ([a61016d](https://github.com/FunkinCrew/Funkin/commit/a61016d2dfc2ac6a50aae230969c036f0753cfaa)) - by @realvirtu in [#6114](https://github.com/FunkinCrew/Funkin/pull/6114)
- The Animation Editor no longer displays a missing object icon next to the dropdown menus. ([b30ea36](https://github.com/FunkinCrew/Funkin/commit/b30ea36fcc982ce4ac0be9143fd4701e180fc684)) - by @KoloInDaCrib in [#6177](https://github.com/FunkinCrew/Funkin/pull/6177)
- The Animation Editor onion skin now properly accounts for character scale and offsets. ([a76a868](https://github.com/FunkinCrew/Funkin/commit/a76a868cb6a27c1c76d09177b90cf6df3df29d17)) - by @VirtuGuy in [#6123](https://github.com/FunkinCrew/Funkin/pull/6123)
- The debug cursor is now properly hidden when exiting the Animation Editor. ([f2f6b4c](https://github.com/FunkinCrew/Funkin/commit/f2f6b4c8591e1ab4a8c6f0ed998d6d25d7cc9f43)) - by @VirtuGuy in [#6112](https://github.com/FunkinCrew/Funkin/pull/6112)
- The Animation Editor onion skin now properly accounts for character scale and offsets. ([a76a868](https://github.com/FunkinCrew/Funkin/commit/a76a868cb6a27c1c76d09177b90cf6df3df29d17)) - by @realvirtu in [#6123](https://github.com/FunkinCrew/Funkin/pull/6123)
- The debug cursor is now properly hidden when exiting the Animation Editor. ([f2f6b4c](https://github.com/FunkinCrew/Funkin/commit/f2f6b4c8591e1ab4a8c6f0ed998d6d25d7cc9f43)) - by @realvirtu in [#6112](https://github.com/FunkinCrew/Funkin/pull/6112)
- Plenty more tiny fixes.
## New Contributors for 0.8.0
@@ -390,13 +627,13 @@ The LE SSERAFIM collab update!
- Freeplay ranks no longer pop out when scrolling through song capsules. ([747446e](https://github.com/FunkinCrew/Funkin/commit/747446e2e420449f422fbc69aafda6128ac8d16e)) - by @VioletSnowLeopard in [#5822](https://github.com/FunkinCrew/Funkin/pull/5822)
- The Freeplay intro no longer plays when returning from a sticker transition. ([63ec749](https://github.com/FunkinCrew/Funkin/commit/63ec749c7a3c90d529e9e8f2f3ed1c8913e8f9a1)) - by @PurSnake in [#5942](https://github.com/FunkinCrew/Funkin/pull/5942)
- Hot-reloading with F5 after earning a rank no longer crashes Freeplay. ([79e8b5d](https://github.com/FunkinCrew/Funkin/commit/79e8b5d71e052953b77b81b66e0a83a7bbeeeeed)) - by @KoloInDaCrib in [#5971](https://github.com/FunkinCrew/Funkin/pull/5971)
- The Main Menu music now fades in consistently when exiting from Freeplay to the Title Screen. ([a10bbf6](https://github.com/FunkinCrew/Funkin/commit/a10bbf60acbbeadfb5a91930745ef4fd338b1a24)) - by @VirtuGuy in [#5855](https://github.com/FunkinCrew/Funkin/pull/5855)
- The Main Menu music now fades in consistently when exiting from Freeplay to the Title Screen. ([a10bbf6](https://github.com/FunkinCrew/Funkin/commit/a10bbf60acbbeadfb5a91930745ef4fd338b1a24)) - by @realvirtu in [#5855](https://github.com/FunkinCrew/Funkin/pull/5855)
- The game now falls back to default audio files when files specified by the metadata don't exist. ([b5357ac](https://github.com/FunkinCrew/Funkin/commit/b5357acf98bde81a4121a3723061f7c559a0640f)) - by @VioletSnowLeopard in [#5954](https://github.com/FunkinCrew/Funkin/pull/5954)
- The cutscene pause menu no longer persists across songs after exiting a video cutscene. ([c2305f3](https://github.com/FunkinCrew/Funkin/commit/c2305f32f0147f6326e8665d21a6b8a793f45033)) - by @KoloInDaCrib in [#5880](https://github.com/FunkinCrew/Funkin/pull/5880)
- Mashing to skip the Eggnog Erect cutscene no longer crashes the game. ([5ca3c6a](https://github.com/FunkinCrew/funkin.assets/commit/5ca3c6a5745b61a457db149c289784c08e560ee9)) - by @VioletSnowLeopard in [funkin.assets#258](https://github.com/FunkinCrew/funkin.assets/pull/258)
- Stress (Pico Mix) no longer lag spikes when loading in the background tankmen. ([6701405](https://github.com/FunkinCrew/funkin.assets/commit/670140571239ca08c1ae1c5286773d99c2875c2d)) - by @NotHyper-474 and @KoloInDaCrib in [funkin.assets#242](https://github.com/FunkinCrew/funkin.assets/pull/242)
- Stress (Pico Mix) no longer lag spikes when Tankman changes sprites. ([aa5956a](https://github.com/FunkinCrew/Funkin/commit/aa5956a30bdc47d53ebebb4b61a7ebb3f04c7dc6)) - by @NotHyper-474 in [#5939](https://github.com/FunkinCrew/Funkin/pull/5939)
- The bricks in Stress (Pico Mix) no longer move after restarting the song. ([9cfee03](https://github.com/FunkinCrew/Funkin/commit/9cfee0398a057567f80ad68ff6052964da63af09)) - by @VirtuGuy in [#5875](https://github.com/FunkinCrew/Funkin/pull/5875)
- The bricks in Stress (Pico Mix) no longer move after restarting the song. ([9cfee03](https://github.com/FunkinCrew/Funkin/commit/9cfee0398a057567f80ad68ff6052964da63af09)) - by @realvirtu in [#5875](https://github.com/FunkinCrew/Funkin/pull/5875)
- Pico now properly shoots after restarting Stress. ([b0ef0d3](https://github.com/FunkinCrew/funkin.assets/commit/b0ef0d352c199e93903652a95ffdf16a3dc2d569)) - by @7oltan in [funkin.assets#254](https://github.com/FunkinCrew/funkin.assets/pull/254)
- A-Bot's visualizer now zeroes out when restarting the song. ([ba3a8b0](https://github.com/FunkinCrew/funkin.assets/commit/ba3a8b0cbbf785a0729dcf85e25b6e59c0c12657)) - by @KoloInDaCrib in [funkin.assets#246](https://github.com/FunkinCrew/funkin.assets/pull/246)
- Notekinds now properly receive dispatched events last in PlayState. ([89b2b7f](https://github.com/FunkinCrew/Funkin/commit/89b2b7fcc3130db0af1f782594af72ae1f4ce320)) - by @Az989YT in [#5936](https://github.com/FunkinCrew/Funkin/pull/5936)
@@ -469,7 +706,7 @@ The LE SSERAFIM collab update!
- The HOME and END keys now jump to the top and bottom of the Story Mode menu, respectively. ([d1a96f7](https://github.com/FunkinCrew/Funkin/commit/d1a96f791f2ed35accc1c1e9ff548a75b2b9d7ef)) - by @JVNpixels in [#4591](https://github.com/FunkinCrew/Funkin/pull/4591)
- Freeplay favorite songs are now separated by variation. ([b4b2e8d](https://github.com/FunkinCrew/Funkin/commit/b4b2e8da9dde41d730556a41e6bb18b0f3d8d7db)) - by @KoloInDaCrib in [#5154](https://github.com/FunkinCrew/Funkin/pull/5154)
- Freeplay preview volumes now play at 70% volume, up from 40%. ([4ecef6d](https://github.com/FunkinCrew/Funkin/commit/4ecef6db744bab7e3fe5de0d680d813cc3bd1ea7)) - by @JackXson-Real in [#5645](https://github.com/FunkinCrew/Funkin/pull/5645)
- Selecting a song in the Freeplay menu now plays a fade-out transition. ([705e6b3](https://github.com/FunkinCrew/Funkin/commit/705e6b330806c3157bca7301b1e43cd78acdb23a)) - by @VirtuGuy in [#5626](https://github.com/FunkinCrew/Funkin/pull/5626)
- Selecting a song in the Freeplay menu now plays a fade-out transition. ([705e6b3](https://github.com/FunkinCrew/Funkin/commit/705e6b330806c3157bca7301b1e43cd78acdb23a)) - by @realvirtu in [#5626](https://github.com/FunkinCrew/Funkin/pull/5626)
- Implemented null safety to PlayState and LoadingState. ([34ce13c](https://github.com/FunkinCrew/Funkin/commit/34ce13c5dfd52760675a1d09efa489bcb108e607)) - by @NotHyper-474 in [#4789](https://github.com/FunkinCrew/Funkin/pull/4789)
- Health icons now have an offset variable. ([8bab619](https://github.com/FunkinCrew/Funkin/commit/8bab6196e50420c6586441f2d321bd1c139567c3)) - by @PurSnake in [#5760](https://github.com/FunkinCrew/Funkin/pull/5760)
- The "hey" notekind now plays the animation for BF (Christmas). ([91d5970](https://github.com/FunkinCrew/funkin.assets/commit/91d5970e0274aa0a31fc6f2b05c114730256408f)) - by @JackXson-Real in [funkin.assets#225](https://github.com/FunkinCrew/funkin.assets/pull/225)
@@ -517,8 +754,8 @@ The LE SSERAFIM collab update!
- Fullscreen keybinds now work properly on Web builds. ([1fbb760](https://github.com/FunkinCrew/Funkin/commit/1fbb7604ddf4fb8d311b9b414cbcfa0fd9bab255)) - by @NotHyper-474 in [#5664](https://github.com/FunkinCrew/Funkin/pull/5664)
- Corrected the heights of characters in the intro text font. ([90242e2](https://github.com/FunkinCrew/funkin.assets/commit/90242e2e200fca38f5f535986db49b7a53282d1f)) - by @SpritersBlock in [funkin.assets#190](https://github.com/FunkinCrew/funkin.assets/pull/190)
- PureColor shaders now properly apply anti-aliasing. ([8d1bfa1](https://github.com/FunkinCrew/Funkin/commit/8d1bfa105c89f68ab1f14a197f8c0a5e4fe7fb14)) - by @MaybeMaru in [#5781](https://github.com/FunkinCrew/Funkin/pull/5781)
- The Preferences menu camera now remembers its position when exiting and re-entering. ([3d88fbb](https://github.com/FunkinCrew/Funkin/commit/3d88fbb11fea2b52d399f37cb8154795329c31c2)) - by @VirtuGuy in [#5608](https://github.com/FunkinCrew/Funkin/pull/5608)
- The Freeplay DJ no longer flickers between animations. ([1b91f3b](https://github.com/FunkinCrew/Funkin/commit/1b91f3b57cda3310db2f5196650b89c8d88e69be)) - by @VirtuGuy in [#5598](https://github.com/FunkinCrew/Funkin/pull/5598)
- The Preferences menu camera now remembers its position when exiting and re-entering. ([3d88fbb](https://github.com/FunkinCrew/Funkin/commit/3d88fbb11fea2b52d399f37cb8154795329c31c2)) - by @realvirtu in [#5608](https://github.com/FunkinCrew/Funkin/pull/5608)
- The Freeplay DJ no longer flickers between animations. ([1b91f3b](https://github.com/FunkinCrew/Funkin/commit/1b91f3b57cda3310db2f5196650b89c8d88e69be)) - by @realvirtu in [#5598](https://github.com/FunkinCrew/Funkin/pull/5598)
- The Freeplay DJ's turntable lights now glow properly. ([0c5a965](https://github.com/FunkinCrew/funkin.assets/commit/0c5a965400937cbdac55ed9317a2a00a9d4343ae)) - by @Johferson in [funkin.assets#211](https://github.com/FunkinCrew/funkin.assets/pull/211)
- The Random capsule now opens the selected song with the correct variation. ([1605514](https://github.com/FunkinCrew/Funkin/commit/160551442453fccc0961c570701bdba7bee95ef0)) - by @PurSnake in [#5611](https://github.com/FunkinCrew/Funkin/pull/5611)
- Newly earned Freeplay ranks no longer appear larger than others. ([47813ea](https://github.com/FunkinCrew/Funkin/commit/47813eac3157927f851713cc4c41c5eb5fac2e19)) - by @anysad in [#5768](https://github.com/FunkinCrew/Funkin/pull/5768)
@@ -536,7 +773,7 @@ The LE SSERAFIM collab update!
- The Week 3 train now consistently plays its sound. ([469ce39](https://github.com/FunkinCrew/funkin.assets/commit/469ce397b8eef3be47f8fadaa61a500e1a87ca3a)) - by @Lasercar in [funkin.assets#212](https://github.com/FunkinCrew/funkin.assets/pull/212)
- Nene no longer freezes after playing two animations at once. ([d346ebd](https://github.com/FunkinCrew/funkin.assets/commit/d346ebdbf4781b49a081e0719221cf584fc3fe55)) - by @NotHyper-474 in [funkin.assets#228](https://github.com/FunkinCrew/funkin.assets/pull/228)
- The Week 4 car now properly pauses with the game. ([26d1cff](https://github.com/FunkinCrew/funkin.assets/commit/26d1cffe19793c67a89f299b7a60be95c5656282)) - by @NotHyper-474 in [funkin.assets#114](https://github.com/FunkinCrew/funkin.assets/pull/114)
- Pressing Reset and Pause at the same time no longer breaks the game over animation in Blazin'. ([8cd3785](https://github.com/FunkinCrew/Funkin/commit/8cd3785e3c3e913ed791204814eba86eb7142a5d)) - by @VirtuGuy in [#5639](https://github.com/FunkinCrew/Funkin/pull/5639)
- Pressing Reset and Pause at the same time no longer breaks the game over animation in Blazin'. ([8cd3785](https://github.com/FunkinCrew/Funkin/commit/8cd3785e3c3e913ed791204814eba86eb7142a5d)) - by @realvirtu in [#5639](https://github.com/FunkinCrew/Funkin/pull/5639)
- Pico's Blazin' death animation no longer lags and offsets improperly. ([2cb42fe](https://github.com/FunkinCrew/funkin.assets/commit/2cb42fec422313db4e8000c963be0539221c9e21)) - by @KoloInDaCrib in [funkin.assets#217](https://github.com/FunkinCrew/funkin.assets/pull/217)
- Pico and Darnell now properly punch with their other arms in Blazin'. ([4fb015f](https://github.com/FunkinCrew/funkin.assets/commit/4fb015f20261995ce41370910989094f4f2f26bb)) - by @Honton129 in [funkin.assets#221](https://github.com/FunkinCrew/funkin.assets/pull/221)
- Pico's Perfect Results Screen animation now syncs with the music. ([0531e27](https://github.com/FunkinCrew/funkin.assets/commit/0531e27feed83dcc9a1703b3df654fd3bba1bd8a)) - by @JackXson-Real in [funkin.assets#201](https://github.com/FunkinCrew/funkin.assets/pull/201)
@@ -550,12 +787,12 @@ The LE SSERAFIM collab update!
- Chart Editor event properties now have minimum values. ([9b81ebc](https://github.com/FunkinCrew/Funkin/commit/9b81ebc4f2c1c70b33d7351210c40c9a0e48ecc8)) - by @Lasercar in [#4110](https://github.com/FunkinCrew/Funkin/pull/4110)
- Added missing notekinds to the Chart Editor Notes window. ([b7a5761](https://github.com/FunkinCrew/Funkin/commit/b7a5761730d43f27891dfec1c23fcb5e66daccf1)) - by @Lasercar in [#4286](https://github.com/FunkinCrew/Funkin/pull/4286)
- Playback speed is now preserved when a new song or variation is loaded in the Chart Editor. ([3f82f37](https://github.com/FunkinCrew/Funkin/commit/3f82f3792b056a03724a0d1a320b7549a7b59844)) - by @Lasercar in [#4212](https://github.com/FunkinCrew/Funkin/pull/4212)
- The Legacy Chart Importer now properly imports scroll speeds. ([2645d56](https://github.com/FunkinCrew/Funkin/commit/2645d56514dd1a27a050ff432c3cd4122f958e10)) - by @VirtuGuy in [#5655](https://github.com/FunkinCrew/Funkin/pull/5655)
- The Legacy Chart Importer now properly imports scroll speeds. ([2645d56](https://github.com/FunkinCrew/Funkin/commit/2645d56514dd1a27a050ff432c3cd4122f958e10)) - by @realvirtu in [#5655](https://github.com/FunkinCrew/Funkin/pull/5655)
- Opponent characters now play singing animations when selected as the player character. ([8ee24c8](https://github.com/FunkinCrew/funkin.assets/commit/8ee24c84de6aa6e6313699198f35f61991612d04)) - by @Lasercar in [funkin.assets#141](https://github.com/FunkinCrew/funkin.assets/pull/141)
- The Chart Editor character selector window no longer opens when clicking while playtesting. ([223e837](https://github.com/FunkinCrew/Funkin/commit/223e837fe8d9ce227e289a38bdfc095e4d81c48a)) - by @Lasercar in [#4350](https://github.com/FunkinCrew/Funkin/pull/4350)
- Renamed Nene's pixel variant to Nene (Pixel) in the Chart Editor. ([69a7898](https://github.com/FunkinCrew/funkin.assets/commit/69a78988e3d6042d2e4779c9a4055c5de73ee775)) - by @JVNpixels in [funkin.assets#208](https://github.com/FunkinCrew/funkin.assets/pull/208)
- Renamed Tankman's variants in the Chart Editor. ([70c43b7](https://github.com/FunkinCrew/funkin.assets/commit/70c43b792078d913c4c4d9fc019e378249d08b78)) - by @ExtraCode75 in [funkin.assets#209](https://github.com/FunkinCrew/funkin.assets/pull/209)
- Pressing F4 in the Chart Editor now properly resets the window title. ([86e69cf](https://github.com/FunkinCrew/Funkin/commit/86e69cfbd1b1bd3daa49181b827fa813cb716703)) - by @VirtuGuy in [#5651](https://github.com/FunkinCrew/Funkin/pull/5651)
- Pressing F4 in the Chart Editor now properly resets the window title. ([86e69cf](https://github.com/FunkinCrew/Funkin/commit/86e69cfbd1b1bd3daa49181b827fa813cb716703)) - by @realvirtu in [#5651](https://github.com/FunkinCrew/Funkin/pull/5651)
- Saving a character in the Animation Editor no longer crashes the game. ([da5f691](https://github.com/FunkinCrew/Funkin/commit/da5f6918656d4a1ad3e83233b358034db92ca675)) - by @anysad in [#5519](https://github.com/FunkinCrew/Funkin/pull/5519)
- The Stage Editor can now properly load modded stages. ([50c601a](https://github.com/FunkinCrew/Funkin/commit/50c601a7f0f27fc0f155e2bfbcb8ef54631aeac7)) - by @KoloInDaCrib in [#5744](https://github.com/FunkinCrew/Funkin/pull/5744)
- XML files exported from the Stage Editor now account for rotated frames. ([661ddb1](https://github.com/FunkinCrew/Funkin/commit/661ddb15f72c2dae22f41a922a521740ab3617f0)) - by @KoloInDaCrib in [#5303](https://github.com/FunkinCrew/Funkin/pull/5303)
@@ -563,9 +800,10 @@ The LE SSERAFIM collab update!
## New Contributors for 0.7.4
* @Trofem made their first contribution in [#5476](https://github.com/FunkinCrew/Funkin/pull/5476)
* @ThatOneCalculator made their first contribution in [#5507](https://github.com/FunkinCrew/Funkin/pull/5507)
* @SrtHero278 made their first contribution in [#5565](https://github.com/FunkinCrew/Funkin/pull/5565)
* @VirtuGuy made their first contribution in [#5598](https://github.com/FunkinCrew/Funkin/pull/5598)
* @realvirtu made their first contribution in [#5598](https://github.com/FunkinCrew/Funkin/pull/5598)
* @SpritersBlock made their first contribution in [funkin.assets#190](https://github.com/FunkinCrew/funkin.assets/pull/190)
* @Johferson made their first contribution in [funkin.assets#211](https://github.com/FunkinCrew/funkin.assets/pull/211)
* @Honton129 made their first contribution in [funkin.assets#213](https://github.com/FunkinCrew/funkin.assets/pull/213)
+1 -1
Submodule assets updated: cd36d5bfcb...724eba9de9
+7 -1
View File
@@ -9,6 +9,10 @@
"asset": "assets/preload/images/NOTE_assets.png",
"blocksize": "4x4"
},
{
"asset": "assets/shared/images/characters/darnell/spritemap1.png",
"blocksize": "4x4"
},
{
"asset": "assets/preload/images/NOTE_hold_assets.png",
"blocksize": "4x4"
@@ -198,6 +202,8 @@
"assets/week1/images/erect/orangeLight.png",
"assets/week2/images/erect/stairsDark.png",
"assets/week2/images/erect/stairsLight.png",
"assets/week6/"
"assets/week6/",
"assets/week7/images/bricksGround.png",
"assets/week7/images/erect/bricksGround.png"
]
}
+19 -17
View File
@@ -1,8 +1,8 @@
FROM ubuntu:noble
ARG haxe_version=4.3.6
ARG haxelib_version=4.1.0
ARG neko_version=2.4.0
ARG haxe_version=4.3.7
ARG haxelib_version=4.2.0
ARG neko_version=2.4.1
# prepare runner
ENV GITHUB_HOME="/github/home"
@@ -80,11 +80,13 @@ EOF
# Haxe native dependencies
RUN <<EOF
apt-fast install -y --no-install-recommends \
libc6-dev libffi-dev \
libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev \
libgl-dev libgl1-mesa-dev \
build-essential \
libc6-dev libffi-dev libdbus-1-dev libudev-dev libgbm-dev \
libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev libxcursor-dev libxss-dev \
libgl-dev libgl1-mesa-dev libglu1-mesa-dev libdrm-dev \
libasound2-dev libpulse-dev \
libvlc-dev libvlccore-dev
libvlc-dev libvlccore-dev \
gcc-multilib g++-multilib
EOF
# Janky libffi.6 fix
@@ -98,11 +100,11 @@ EOF
# neko
# https://github.com/HaxeFoundation/neko/releases/download/v2-3-0/neko-2.3.0-linux64.tar.gz
RUN <<EOF
#neko_url=$(curl https://api.github.com/repos/HaxeFoundation/neko/releases -fL \
# | jq '.[] | select(.name == "'"$neko_version"'")' \
# | jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
# | jq -r '.browser_download_url')
neko_url="https://geo.thei.rs/funkin/neko-2.4.1-linux64.tar.gz"
neko_url=$(curl https://api.github.com/repos/HaxeFoundation/neko/releases -fL \
| jq '.[] | select(.name == "'"$neko_version"'")' \
| jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
| jq -r '.browser_download_url')
#neko_url="https://geo.thei.rs/funkin/neko-2.4.1-linux64.tar.gz"
curl -fL "$neko_url" | tar -xz -C /usr/local
EOF
@@ -112,16 +114,16 @@ ln -s "$neko_path" /usr/local/neko
EOF
ENV NEKOPATH="/usr/local/neko"
ENV LD_LIBRARY_PATH="$NEKOPATH:$LD_LIBRARY_PATH"
ENV LD_LIBRARY_PATH="$NEKOPATH"
ENV PATH="$NEKOPATH:$PATH"
# haxe
# https://github.com/HaxeFoundation/haxe/releases/download/4.0.5/haxe-4.0.5-linux64.tar.gz
RUN <<EOF
#haxe_url=$(curl https://api.github.com/repos/HaxeFoundation/haxe/releases -fL \
# | jq '.[] | select(.name == "'"$haxe_version"'")' \
# | jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
# | jq -r '.browser_download_url')
haxe_url=$(curl https://api.github.com/repos/HaxeFoundation/haxe/releases -fL \
| jq '.[] | select(.name == "'"$haxe_version"'")' \
| jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
| jq -r '.browser_download_url')
haxe_url="https://geo.thei.rs/funkin/haxe-4.3.6-linux64.tar.gz"
curl -fL "$haxe_url" | tar -xz -C /usr/local
EOF
+133 -30
View File
@@ -33,6 +33,9 @@
"allowReturn": true,
"allowFunction": true,
"allowCurlyBody": true,
"enforceArrowForNonMemberFunctions": true,
"severity": "INFO"
},
"type": "ArrowFunction"
@@ -47,6 +50,14 @@
"props": { "severity": "INFO" },
"type": "AvoidStarImport"
},
{
"comment": "If enabled, prevents ternary operators from being nested.",
"props": {
"severity": "INFO",
"maxDepth": 1
},
"type": "AvoidTernaryOperator"
},
{
"comment": "If enabled, prevents conditional compilation from crossing blocks. This prevents the case where conditional compilation could potentially create invalid syntax.",
"props": { "severity": "INFO" },
@@ -64,6 +75,7 @@
"comment": "If enabled, flags when large blocks of similar code should be extracted to a function.",
"props": {
"thresholdSimilar": 120,
"severity": "IGNORE",
"thresholdIdentical": 60,
"severityIdentical": "IGNORE"
},
@@ -84,11 +96,21 @@
"type": "ConditionalCompilation"
},
{
"comment": "Specifies a specific naming format for constant (static) identifiers.",
"comment": "Specifies a specific naming format for static var identifiers.",
"props": {
"ignoreExtern": true,
"format": "^?:_[a-zA-Z0-9]+(?:_[a-zA-Z0-9]+)*$",
"tokens": ["INLINE", "NOTINLINE"],
"tokens": ["INLINE", "NOTINLINE", "NOTFINAL"],
"severity": "INFO"
},
"type": "ConstantName"
},
{
"comment": "Specifies a specific naming format for static final identifiers.",
"props": {
"ignoreExtern": true,
"format": "^[A-Z]([_A-Z0-9]+)*$",
"tokens": ["INLINE", "NOTINLINE", "FINAL"],
"severity": "INFO"
},
"type": "ConstantName"
@@ -111,7 +133,13 @@
},
{
"comment": "Specifies the format for doc-style comments ().",
"props": { "lineStyle": "onestar", "startStyle": "ignore" },
"props": {
"startStyle": "twostars",
"endStyle": "onestar",
"lineStyle": "onestar",
"severity": "INFO"
},
"type": "DocCommentStyle"
},
{
@@ -188,7 +216,21 @@
"fieldType": "BOTH",
"requireReturn": true,
"ignoreOverride": true,
"tokens": ["ABSTRACT_DEF", "CLASS_DEF", "ENUM_DEF", "INTERFACE_DEF"],
"tokens": ["ABSTRACT_DEF", "CLASS_DEF", "INTERFACE_DEF"],
"modifier": "PUBLIC",
"excludeNames": ["new", "toString"],
"severity": "INFO"
},
"type": "FieldDocComment"
},
{
"comment": "If enabled, mandates documentation comments for public fields.",
"props": {
"requireParams": true,
"fieldType": "FUNCTIONS",
"requireReturn": true,
"ignoreOverride": true,
"tokens": ["ENUM_DEF"],
"modifier": "PUBLIC",
"excludeNames": ["new", "toString"],
"severity": "INFO"
@@ -240,7 +282,10 @@
},
{
"comment": "If enabled, warns about assignments performed within another expression, like 'if (a=b){}'",
"props": { "ignoreReturnAssignments": true, "severity": "WARNING" },
"props": {
"ignoreReturnAssignments": true,
"severity": "WARNING"
},
"type": "InnerAssignment"
},
{
@@ -270,7 +315,6 @@
"SWITCH",
"TRY",
"CATCH",
"REIFICATION",
"ARRAY_COMPREHENSION"
],
"severity": "INFO"
@@ -306,24 +350,48 @@
"type": "ListenerName"
},
{
"comment": "Specifies a specific naming format for local variables.",
"comment": "Specifies a specific naming format for local var variables.",
"props": {
"ignoreExtern": true,
"format": "^[a-z][a-zA-Z0-9]*$",
"tokens": [],
"tokens": ["NOTFINAL"],
"severity": "INFO"
},
"type": "LocalVariableName"
},
{
"comment": "Specifies a specific naming format for local final variables.",
"props": {
"ignoreExtern": true,
"format": "^[A-Z][_A-Z0-9]*$",
"tokens": ["FINAL"],
"severity": "INFO"
},
"type": "LocalVariableName"
},
{
"comment": "Puts a warning on long numbers without separators. 1000000 is invalid and 1_000_000 is valid.",
"props": {
"severity": "INFO",
"decimalGroupSize": 3,
"fractionalGroupSize": -1,
"binaryGroupSize": 8,
"hexadecimalGroupSize": 8,
"decimalMinimum": 10000
},
"type": "LongNumber"
},
{
"comment": "If enabled, warns when unlabelled numeric values get used. Use named constants instead to improve code clarity.",
"props": { "ignoreNumbers": [-1, 0, 1, 2], "severity": "INFO" },
"props": { "ignoreNumbers": [-1, 0, 1, 2], "severity": "IGNORE" },
"type": "MagicNumber"
},
{
"comment": "Specifies a specific naming format for public abstract member fields.",
"props": {
"format": "^[_a-zA-Z][a-z][a-zA-Z0-9]*$",
"format": "^[a-zA-Z][_a-zA-Z0-9]*$",
"tokens": ["PUBLIC", "ABSTRACT"]
},
"type": "MemberName"
@@ -340,7 +408,7 @@
{
"comment": "Specifies a specific naming format for public class member fields.",
"props": {
"format": "^[_a-zA-Z][a-z][a-zA-Z0-9]*$",
"format": "^[a-zA-Z][a-z][a-zA-Z0-9]*$",
"tokens": ["PUBLIC", "CLASS"]
},
"type": "MemberName"
@@ -348,7 +416,7 @@
{
"comment": "Specifies a specific naming format for private class member fields.",
"props": {
"format": "^[_a-zA-Z][a-z][a-zA-Z0-9]*$",
"format": "^[_a-zA-Z][_a-zA-Z0-9]*$",
"tokens": ["PRIVATE", "CLASS"]
},
"type": "MemberName"
@@ -356,8 +424,8 @@
{
"comment": "Specifies a specific naming format for enum member fields.",
"props": {
"format": "^[_a-zA-Z][a-z][a-zA-Z0-9]*$",
"tokens": ["ENUM"]
"format": "^[a-zA-Z][_a-zA-Z0-9]*$",
"tokens": ["PUBLIC", "ENUM"]
},
"type": "MemberName"
},
@@ -388,9 +456,9 @@
"comment": "Specifies a specific naming format for method names.",
"props": {
"ignoreExtern": true,
"format": "^[a-z][a-zA-Z0-9]*$",
"format": "^[a-z][_a-zA-Z0-9]*$",
"tokens": [],
"severity": "IGNORE"
"severity": "INFO"
},
"type": "MethodName"
},
@@ -398,15 +466,21 @@
"comment": "Specifies a specific order for modifiers on fields.",
"props": {
"modifiers": [
"OVERRIDE",
"OVERLOAD",
"PUBLIC_PRIVATE",
"STATIC",
"MACRO",
"OVERRIDE",
"ABSTRACT",
"EXTERN",
"INLINE",
"DYNAMIC",
"MACRO",
"FINAL"
],
"severity": "IGNORE"
"severity": "INFO"
},
"type": "ModifierOrder"
},
@@ -429,15 +503,16 @@
"comment": "If enabled, mandates the use of braces on specific block types, unless they fit on a single line.",
"props": {
"allowSingleLineStatement": true,
"tokens": [
"FUNCTION",
"FOR",
"IF",
"ELSE_IF",
"WHILE",
"DO_WHILE",
"CATCH"
],
"tokens": ["FUNCTION", "FOR", "IF", "IF_WITH_ELSE", "ELSE"],
"severity": "INFO"
},
"type": "NeedBraces"
},
{
"comment": "If enabled, mandates the use of braces on specific block types, and prevent them from being placed on a single line.",
"props": {
"allowSingleLineStatement": false,
"tokens": ["IF_WITH_ELSE", "CATCH", "WHILE", "DO_WHILE", "ELSE_IF"],
"severity": "INFO"
},
"type": "NeedBraces"
@@ -630,7 +705,11 @@
},
{
"comment": "If enabled, complains about overly complicated boolean expressions.",
"props": { "severity": "WARNING" },
"props": {
"severity": "WARNING",
"allowEqualsFalse": false
},
"type": "SimplifyBooleanExpression"
},
{
@@ -661,6 +740,14 @@
},
"type": "StringLiteral"
},
{
"comment": "If enabled, requires that switch conditions be wrapped in parenthesis.",
"props": {
"policy": "require",
"severity": "INFO"
},
"type": "SwitchParentheses"
},
{
"comment": "Puts a warning on unresolved TODO/FIXME comments.",
"props": {
@@ -679,6 +766,16 @@
"props": { "severity": "IGNORE" },
"type": "Trace"
},
{
"comment": "If enabled, complains about trailing commas at the end of array and object literals.",
"props": {
"severity": "INFO",
"enforceArrayComprehension": false,
"enforceArrayLiterals": false,
"enforceObjectLiterals": false
},
"type": "TrailingComma"
},
{
"comment": "If enabled, complains about trailing whitespaces at the end of lines.",
"props": { "severity": "INFO" },
@@ -692,7 +789,13 @@
{
"comment": "If enabled, mandates documentation comments on classes and interfaces.",
"props": {
"tokens": ["CLASS_DEF", "ENUM_DEF", "INTERFACE_DEF", "TYPEDEF_DEF"],
"tokens": [
"CLASS_DEF",
"INTERFACE_DEF",
"TYPEDEF_DEF",
"ABSTRACT_DEF",
"ENUM_DEF"
],
"severity": "INFO"
},
"type": "TypeDocComment"
+5 -5
View File
@@ -12,7 +12,7 @@ Check [COMPILING.md](./COMPILING.md) if you haven’t done that yet.
setx ANDROID_HOME "C:\path\to\your\folder" /M
```
3. Download [Android Studio Command-line Tools](https://developer.android.com/studio#command-line-tools-only).
4. Extract the ZIP into your folder from step 1.
4. Extract the ZIP into your folder from step 0.
5. (Optional) Close and reopen the terminal if needed.
6. Run:
```bash
@@ -69,10 +69,10 @@ Check [COMPILING.md](./COMPILING.md) if you haven’t done that yet.
```
## iOS
Note that you can only build the game for iOS on a computer running MacOS.
Note that you can only build the game for iOS on a computer running macOS.
0. Build the game for desktop to make sure everything works. Check [COMPILING.md](./COMPILING.md).
1. Get Xcode from the app store on your MacOS Machine.
1. Get Xcode from the app store on your macOS Machine.
2. Download the iPhone SDK (First thing that pops up in Xcode)
3. Open up a terminal tab and run `lime test ios -xcode`
4. You will need to sign your own copy in order to run the game with a real iOS device! That requires an Apple Developer account, sorry!
@@ -81,11 +81,11 @@ Note that you can only build the game for iOS on a computer running MacOS.
### iOS Troubleshooting
- **A required plugin failed to load. Please ensure system content is up-to-date — try running 'xcodebuild -runFirstLaunch'.**
Make sure you have the iOS SDK isntalled, see Step 2.
Make sure you have the iOS SDK installed, see Step 2.
- **error: No Accounts: Add a new account in Accounts settings. (in target 'Funkin' from project 'Funkin')**
Open XCode, press CMD+, to open Settings, select Accounts, add an Apple ID.
Open Xcode, press CMD+, to open Settings, select Accounts, add an Apple ID.
- error: No Account for Team "Z7G7AVNGSH". Add a new account in Accounts settings or verify that your accounts have valid credentials.
+3 -2
View File
@@ -60,8 +60,8 @@ This section provides guidelines to follow when [opening an issue](https://githu
## Requirements
Make sure you're playing:
- the latest version of the game (currently v0.8.3)
- without any mods
- the latest version of the game (currently v0.8.6, or v0.8.7 for Android) or a public playtest version (v0.9 Feature Preview builds)
- without any mods (unless the issue involves mods)
- on [Newgrounds](https://www.newgrounds.com/portal/view/770371) or downloaded from [itch.io](https://ninja-muffin24.itch.io/funkin)
## Rejected Features
@@ -86,6 +86,7 @@ Here's a list of commonly suggested features and the reasons why they won't be a
| Importing Charts from Psych Engine (and other mod content) | https://github.com/FunkinCrew/Funkin/issues/2586#issuecomment-2125733327 |
| Backwards Compatibility for Modding | https://github.com/FunkinCrew/Funkin/issues/3949#issuecomment-2608391329 |
| Lua Support | https://github.com/FunkinCrew/Funkin/issues/2643#issuecomment-2143718093 |
| Note Hitsounds | https://github.com/FunkinCrew/Funkin/pull/4112#issuecomment-5347549977 |
## Issue Types
Choose the issue template that best suits your needs!
+2 -3
View File
@@ -8,9 +8,7 @@ Most of this functionality is only available on debug builds of the game!
- `F3`: ***SCREENSHOT***: Takes a screenshot of the game and saves it to the local `screenshots` directory. Works outside of debug builds too!
- `F4`: ***EJECT***: Forcibly switch state to the Main Menu (with no extra transition). Useful if you're stuck in a level and you need to get out!
- `F5`: ***HOT RELOAD***: Forcibly reload the game's scripts and data files, then restart the current state. If any files in the `assets` folder have been modified, the game should process the changes for you! NOTE: Known bug, this does not reset song charts or song scripts, but it should reset everything else (such as stage layout data and character animation data).
- `CTRL-ALT-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace. (Only works in the Main Menu on debug builds).
- `CTRL-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace.
- `CTRL-ALT-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace.
## **Play State**
- `H`: ***HIDE UI***: Makes the user interface invisible. Works in Pause Menu, great for screenshots.
@@ -27,6 +25,7 @@ Most of this functionality is only available on debug builds of the game!
- `P`: ***SWITCH TO PICO/BF***: Switch to Pico or BF (reopens Freeplay as the other character).
- `T`: ***TEST RANK ANIMATION***: Play the Gold Perfect rank animation on the currently selected song.
- `SHIFT-ACCEPT`: ***BOTPLAY MODE***: Start a song with Botplay mode enabled.
- `CTRL-ACCEPT`: ***MIRRORED MODE***: Start a song with mirrored notes enabled.
- `CTRL-Switch Song`: Play the first unlocked alternate instrumental as the song preview.
## **Title State**
+5
View File
@@ -0,0 +1,5 @@
# Install Dox
`haxelib install dox`
# To generate documentation
Run the script for your operating system, and then it will generate docs into `docs/dox/output/`
+4
View File
@@ -0,0 +1,4 @@
{
"name": "Funkin' Theme",
"author": "The Funkin' Crew Inc"
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,332 @@
#theme-toggle:focus {
outline: none;
}
.dark-theme {
background-color: #111 !important;
color: #ccc;
color-scheme: dark;
}
.dark-theme body {
background-color: #111 !important;
color: #ccc;
}
.dark-theme .navbar-inner {
background-color: #222 !important;
}
.dark-theme .brand {
color: #CCC !important;
}
.dark-theme .brand .img {
margin-top: -5px;
}
.dark-theme .well {
background-color: #222;
border: 1px solid #222;
}
.dark-theme .input-append .add-on,
.dark-theme .input-prepend .add-on {
background-color: #333;
border: 1px solid #333;
padding: 3px 5px;
text-shadow: 0 0 0 #000;
}
.dark-theme h1 {
color: #ccc;
}
.dark-theme a {
color: #0087ff;
}
.dark-theme a:hover,
.dark-theme a:focus {
color: #00b7ff;
}
.dark-theme input,
.dark-theme textarea {
background-color: #151515;
border: 1px solid #333;
transition: none;
}
.dark-theme .btn-group.open .btn.dropdown-toggle {
background-color: #202020;
}
.dark-theme .dropdown-menu {
background-color: #111;
}
.dark-theme .dropdown-menu>li>a {
color: #EEE;
}
.dark-theme .dropdown-menu>li>a:hover,
.dark-theme .dropdown-menu>li>a:focus,
.dark-theme .dropdown-submenu:hover>a,
.dark-theme .dropdown-submenu:focus>a {
color: #EEE;
background-color: #2f2f2f;
background-image: linear-gradient(to bottom, #262626, #2f2f2f);
}
.dark-theme .btn:focus,
.dark-theme .btn:hover {
background-position: 0 0;
}
.dark-theme .nav>li>a:hover,
.dark-theme .nav>li>a:focus {
background-color: #333;
}
.dark-theme .nav-list>.active>a {
background-color: #444;
}
.dark-theme .nav-list>.active>a.treeLink,
.dark-theme .nav-list>.active>a.treeLink:hover,
.dark-theme .nav-list>.active>a.treeLink:focus {
background: #269;
}
.dark-theme .btn {
color: #d5d5d5;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);
background-color: #313131;
background-image: linear-gradient(to bottom, #313131, #282828);
border: 1px solid #424141;
border-bottom-color: #393939;
box-shadow: none;
}
.dark-theme .btn {
color: #d5d5d5;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);
background-color: #313131;
background-image: linear-gradient(to bottom, #313131, #282828);
border: 1px solid #424141;
border-bottom-color: rgb(66, 65, 65);
border-bottom-color: #393939;
box-shadow: none;
}
.dark-theme .btn:focus,
.dark-theme .btn:hover {
color: #fff;
text-decoration: none;
}
.dark-theme .btn.active,
.dark-theme .btn:active {
background-image: none;
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.dark-theme .btn.disabled,
.dark-theme .btn[disabled] {
cursor: not-allowed;
opacity: 0.65;
box-shadow: none;
border-color: #393939;
}
.dark-theme .btn:focus {
color: #d5d5d5;
background-color: #313131;
border-color: #424141;
}
.dark-theme .btn:active:hover,
.dark-theme .btn:focus:hover {
color: #fff;
background-color: #313131;
border-color: #393939;
}
.dark-theme a.btn.disabled {
pointer-events: none;
}
.dark-theme .section.site-footer {
background: #111 !important;
}
.dark-theme .copyright>p {
color: #CCC !important;
}
.dark-theme .table th,
.dark-theme .table td {
border-bottom: 1px solid #222;
}
.dark-theme .table .fa {
color: #222;
margin-right: 5px;
}
.dark-theme .alert,
.dark-theme .alert h4 {
color: #ffc96c;
}
.dark-theme .availability {
color: #69b;
}
.dark-theme .section-availability {
color: #69b;
}
.dark-theme .alert {
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
}
.dark-theme .alert {
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
background-color: #332b00;
border: none;
}
.dark-theme hr {
border-top: none;
border-bottom: 1px solid #222;
}
.dark-theme .page-header {
border-bottom: 1px solid #222;
}
.dark-theme .section {
border-bottom: 1px solid #222;
}
.dark-theme .field+.field {
border-top: 1px solid #222;
}
.dark-theme code {
color: #ddd;
background-color: #111;
border: 1px solid #222;
}
.dark-theme pre {
background-color: #222;
border: 1px solid #333;
}
.dark-theme .example code {
color: #ddd;
background-color: transparent;
border: none;
}
.dark-theme pre code {
background-color: transparent;
}
.dark-theme pre.example::before {
color: #DDD;
background: #191919;
}
.dark-theme h3 code {
box-shadow: 0 0 15px rgb(20, 20, 20);
}
.dark-theme .label,
.dark-theme .badge {
color: #DDD;
background-color: #404040;
}
.dark-theme .label.label-meta {
background: #333379;
}
.dark-theme code .identifier {
color: #eff;
}
.dark-theme table.params {
border-left: 5px solid #222;
margin-left: 20px;
}
.dark-theme .table-bordered {
border: 1px solid #222;
}
.dark-theme table.params th {
background: #111;
}
.dark-theme .table-bordered th,
.dark-theme .table-bordered td {
border-left: 1px solid #222;
}
.dark-theme .indent {
border-left: 5px solid #222;
}
/* Types without links */
.dark-theme code .type {
color: #29e;
}
/* dark code examples (from try-haxe) */
.dark-theme code,
.dark-theme pre {
color: #DDD;
}
.dark-theme code a {
color: #29e
}
.dark-theme pre .type {
color: #DECB6B
}
.dark-theme pre .kwd {
color: #C792EA
}
.dark-theme pre .val {
color: #FF5370
}
.dark-theme div.pre .str,
.dark-theme pre .str,
.dark-theme pre .str .kwd,
.dark-theme pre .str .type,
.dark-theme pre .str .val {
color: #C3E88D
}
.dark-theme pre .cmt,
.dark-theme pre .cmt .kwd,
.dark-theme pre .cmt .str,
.dark-theme pre .cmt .type,
.dark-theme pre .cmt .val {
color: #545454
}
.dark-theme .last-modified {
color: #666
}
@@ -0,0 +1 @@
/** to be overridden in sub-themes */
@@ -0,0 +1,189 @@
nav.nav {
font-family: "Open Sans", sans-serif;
font-size: 16px;
margin: 0;
}
nav .fa {
color: #777;
margin-right: 5px;
}
body nav * {
line-height: 20px;
}
nav .navbar-inner {
background: #13110f;
border: 0;
border-radius: 0;
}
nav .navbar .nav {
margin: 0;
}
nav .dropdown-menu {
background: #2c2722;
font-size: 14px;
border-radius: 0px 0px 2px 2px;
padding: 10px 0px;
border: 1px solid #2c2722;
margin-top: -1px;
}
nav .navbar .nav>li>a {
padding: 14px 12px 15px 12px;
color: #ccc;
}
nav .dropdown-menu li a {
color: #b8b5b5;
padding: 3px 15px;
}
nav .divider {
background-color: transparent;
border-right: 1px solid #39332d;
margin: 5px 20px 5px 10px;
height: 39px;
}
nav .dropdown-menu .divider {
background-color: transparent;
border: 0;
border-bottom: 1px solid #39332d;
margin: 5px 0;
}
nav .navbar-inverse .nav .active>a,
nav .navbar-inverse .nav .active>a:hover,
nav .navbar-inverse .nav .active>a:focus,
nav .navbar-inverse .nav li.dropdown.open>.dropdown-toggle,
nav .navbar-inverse .nav li.dropdown.active>.dropdown-toggle,
nav .navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle {
color: #fff;
background-color: transparent;
background-image: none;
}
nav .navbar-inverse .nav .active>a:hover {
background: #39332d;
}
nav .dropdown-menu>.active>a,
nav .dropdown-menu>.active>a:hover,
nav .dropdown-menu>.active>a:focus {
font-weight: bold;
color: #fff;
background-image: none;
background: #39332d;
}
nav .dropdown-menu>li>a:hover,
.dropdown-menu>li>a:focus,
nav .dropdown-submenu:hover>a,
nav .dropdown-submenu:focus>a {
background: #39332d;
}
nav .navbar .nav>li>.dropdown-menu:after {
border-bottom-color: #2c2722;
}
/** MEDIA Q **/
@media (max-width: 979px) {
nav .navbar-fixed-top .navbar-inner,
nav .navbar-fixed-bottom .navbar-inner {
padding: 0px;
}
nav .navbar-fixed-top {
margin-bottom: 0;
}
}
/** SUB BRAND LOGOS **/
.navbar .brand.haxe-logo {
padding-right: 0;
margin: 3px 0 0 0px;
}
.navbar .brand.haxe-logo:hover {
opacity: .9;
}
.navbar .brand.haxe-logo:after {
content: " ";
position: absolute;
/* create arrow */
width: 0;
height: 0;
border-top: 22px solid transparent;
border-bottom: 22px solid transparent;
border-left: 7px solid #13110f;
/* same color as nav bar */
top: 0;
}
.navbar .brand.sub {
background: #39332d;
/* Old browsers */
background: -moz-linear-gradient(top, #39332d 50%, #2c2722 51%);
/* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(50%, #39332d), color-stop(51%, #2c2722));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #39332d 50%, #2c2722 51%);
/* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #39332d 50%, #2c2722 51%);
/* Opera 11.10+ */
background: -ms-linear-gradient(top, #39332d 50%, #2c2722 51%);
/* IE10+ */
background: linear-gradient(to bottom, #39332d 50%, #2c2722 51%);
/* W3C */
padding: 14px 20px 13px 20px;
margin: 0 10px 0 0;
font: bold 18px "arial black", "open sans";
line-height: 22px;
color: rgb(255, 255, 255);
}
.navbar .brand.sub:hover {
color: rgb(230, 230, 230);
background: #2c2722;
/* Old browsers */
}
.navbar .brand.sub:before {
content: "..";
/* two dots */
position: absolute;
margin-left: -33px;
margin-top: -28px;
line-height: 0px;
font: bold 40px "Open Sans", sans-serif;
letter-spacing: 0px;
color: #fff200;
}
/** SUB BRAND COLORS **/
.navbar .brand.sub.try:before {
color: #f89c0e;
}
.navbar .brand.sub.api:before {
color: #eedc16;
}
.navbar .brand.sub.lib:before {
color: #f1471d;
}
.navbar .brand.sub.ide:before {
color: #f89c0e;
}
@@ -0,0 +1,65 @@
/**
Code Highlighting
**/
html pre,
html pre code {
font-family: consolas, monospace;
white-space: pre;
overflow-x: auto;
}
code {
color: #333;
}
code a {
color: #08c;
}
pre {
color: #333;
margin: 15px 0;
padding: 0.5em;
}
pre .type {
color: #0086b3;
}
pre .kwd {
color: #00a;
}
pre .val {
color: #44a;
}
pre .str,
div.pre .str,
pre .str .kwd,
pre .str .val,
pre .str .type {
color: #a00;
}
pre .cmt {
color: #008800;
color: #998;
font-style: italic;
}
/* Make sure keywords inside comments are not highlighted*/
pre .cmt .kwd,
pre .cmt .str,
pre .cmt .val,
pre .cmt .type {
color: #998;
}
.last-modified {
color: #999;
}
.semantic {
display: none;
}
@@ -0,0 +1,43 @@
// highlighter adapted/modified from code.haxe.org
(function (console) { "use strict";
var EReg = function(r,opt) {
opt = opt.split("u").join("");
this.r = new RegExp(r,opt);
};
EReg.prototype = {
replace: function(s,by) {
return s.replace(this.r,by);
}
};
var Highlighter = function() { };
Highlighter.main = function() {
var _g = 0;
var _g1 = window.document.body.querySelectorAll("pre code");
while(_g < _g1.length) {
var el = _g1[_g];
++_g;
if(!Highlighter.hasClass(el,"highlighted")) {
el.innerHTML = Highlighter.syntaxHighlight(el.innerHTML);
el.className += " highlighted";
}
}
};
Highlighter.hasClass = function(el,className) {
return el.className.indexOf(className) != -1;
};
Highlighter.syntaxHighlight = function(html) {
var kwds = ["abstract","break","case","cast","catch","class","continue","default","do","dynamic","else","enum","extends","extern","false","final","for","function","if","implements","import","in","inline","interface","macro","new","operator","overload","override","package","private","public","return","static","switch","this","throw","true","try","typedef","untyped","using","var","while"];
var kwds1 = new EReg("\\b(" + kwds.join("|") + ")\\b","g");
var vals = ["null","true","false","this"];
var vals1 = new EReg("\\b(" + vals.join("|") + ")\\b","g");
var types = new EReg("\\b([A-Z][a-zA-Z0-9]*)\\b","g");
html = kwds1.replace(html,"<span class='kwd'>$1</span>");
html = vals1.replace(html,"<span class='val'>$1</span>");
html = types.replace(html,"<span class='type'>$1</span>");
html = new EReg("(\"[^\"]*\")","g").replace(html,"<span class='str'>$1</span>");
html = new EReg("(//.+?)(\n|$)","g").replace(html,"<span class='cmt'>$1</span>$2");
html = new EReg("(/\\*\\*?(.|\n)+?\\*?\\*/)","g").replace(html,"<span class='cmt'>$1</span>");
return html;
};
Highlighter.main();
})(typeof console != "undefined" ? console : {log:function(){}});
+319
View File
@@ -0,0 +1,319 @@
function createCookie(name, value) {
localStorage.setItem(name, value);
}
function readCookie(name) {
return localStorage.getItem(name);
}
function isDarkTheme() {
return document.querySelector("html").classList.contains("dark-theme");
}
function toggleTheme() {
const htmlTag = document.querySelector("html");
let isDark = isDarkTheme();
if (isDark) {
htmlTag.classList.remove("dark-theme");
} else {
htmlTag.classList.add("dark-theme");
}
isDark = isDarkTheme();
localStorage.theme = isDark ? "dark" : "light";
}
function toggleInherited(el) {
var toggle = $(el).closest(".toggle");
toggle.toggleClass("toggle-on");
if (toggle.hasClass("toggle-on")) {
$("i", toggle).removeClass("fa-folder").addClass("fa-folder-open");
} else {
$("i", toggle).addClass("fa-folder").removeClass("fa-folder-open");
}
return false;
}
function toggleCollapsed(el) {
var toggle = $(el).closest(".expando");
toggle.toggleClass("expanded");
if (toggle.hasClass("expanded")) {
$(toggle).find("i").first().removeClass("fa-folder").addClass("fa-folder-open");
} else {
$(toggle).find("i").first().addClass("fa-folder").removeClass("fa-folder-open");
}
updateTreeState();
return false;
}
function updateTreeState() {
var states = [];
$("#nav .expando").each(function (i, e) {
states.push($(e).hasClass("expanded") ? 1 : 0);
});
var treeState = JSON.stringify(states);
createCookie("treeState", treeState);
}
function setPlatform(platform) {
createCookie("platform", platform);
$("#select-platform").val(platform);
var styles = ".platform { display:none }";
var platforms = dox.platforms;
if (platform == "flash" || platform == "js") {
styles += ".package-sys { display:none; } ";
}
for (var i = 0; i < platforms.length; i++) {
var p = platforms[i];
if (platform == "sys") {
if (p != "flash" && p != "js") {
styles += ".platform-" + p + " { display:inherit } ";
}
}
else {
if (platform == "all" || p == platform) {
styles += ".platform-" + p + " { display:inherit } ";
}
}
}
if (platform != "flash" && platform != "js") {
styles += ".platform-sys { display:inherit } ";
}
$("#dynamicStylesheet").text(styles);
}
$(document).ready(function () {
$("#nav").html(navContent);
var treeState = readCookie("treeState");
$("#nav .expando").each(function (i, e) {
$("i", e).first().addClass("fa-folder").removeClass("fa-folder-open");
});
$(".treeLink").each(function () {
this.href = this.href.replace("::rootPath::", dox.rootPath);
});
if (treeState != null) {
var states = JSON.parse(treeState);
$("#nav .expando").each(function (i, e) {
if (states[i]) {
$(e).addClass("expanded");
$("i", e).first().removeClass("fa-folder").addClass("fa-folder-open");
}
});
}
$("head").append("<style id='dynamicStylesheet'></style>");
setPlatform(readCookie("platform") == null ? "all" : readCookie("platform"));
$("#search").on("input", function (e) {
searchQuery(e.target.value);
});
$(document).bind("keyup keydown", function (e) {
if (e.ctrlKey && e.keyCode == 80) { // ctrl + p
$("#search").focus();
return false;
}
return true;
});
function getItems() {
return $("#search-results-list a").toArray();
}
$("#search").bind("keyup", function (e) {
switch (e.keyCode) {
case 27: // escape
searchQuery("");
$("#search").val("")
$("#search").blur();
return false;
case 13: // enter
var items = getItems();
for (i = 0; i < items.length; i++) {
var item = $(items[i]);
if (item.hasClass("selected")) {
window.location = items[i].href;
break;
}
}
return false;
}
});
$("#search").bind("keydown", function (e) {
function mod(a, b) {
var r = a % b;
return r < 0 ? r + b : r;
}
function changeSelection(amount) {
var previousSelection = null;
var items = getItems();
for (i = 0; i < items.length; i++) {
var item = $(items[i]);
if (item.hasClass("selected")) {
item.removeClass("selected");
previousSelection = i;
break;
}
}
var newSelection = mod(previousSelection + amount, items.length);
$(items[newSelection]).addClass("selected");
items[newSelection].scrollIntoView(false);
}
switch (e.keyCode) {
case 38: // up
changeSelection(-1);
return false;
case 40: // down
changeSelection(1);
return false;
case 13: // enter
return false;
}
});
$("#select-platform").selectpicker().on("change", function (e) {
var value = $(":selected", this).val();
setPlatform(value);
});
$("#nav a").each(function () {
if (this.href == location.href) {
$(this.parentElement).addClass("active");
}
});
$("a.expand-button").click(function (e) {
var container = $(this).parent().next();
container.toggle();
$("i", this).removeClass("fa-folder-open")
.removeClass("fa-folder")
.addClass(container.is(":visible") ? "fa-folder-open" : "fa-folder");
return false;
});
// Because there is no CSS parent selector
$("code.prettyprint").parents("pre").addClass("example");
});
function searchQuery(query) {
$("#searchForm").removeAttr("action");
query = query.replace(/[&<>"']/g, "");
if (!query || query.length < 2) {
$("#nav").removeClass("searching");
$("#nav li").each(function (index, element) {
var e = $(element);
e.css("display", "");
});
$("#nav ul:first-child").css("display", "block");
$("#search-results-list").css("display", "none");
return;
}
var queryParts = query.toLowerCase().split(" ");
var listItems = [];
var bestMatch = 200;
$("#nav").addClass("searching");
$("#nav ul:first-child").css("display", "none");
$("#nav li").each(function (index, element) {
var e = $(element);
if (!e.hasClass("expando")) {
var content = e.attr("data_path");
var score = searchMatch(content, queryParts);
if (score >= 0) {
if (score < bestMatch) {
var url = dox.rootPath + e.attr("data_path").split(".").join("/") + ".html";
$("#searchForm").attr("action", url);
// best match will be form action
bestMatch = score;
}
var elLink = $("a", element);
// highlight matched parts
var elLinkContent = elLink.text().replace(new RegExp("(" + queryParts.join("|").split(".").join("|") + ")", "ig"), "<strong>$1</strong>");
var liStyle = (score == 0) ? ("font-weight:bold") : "";
listItems.push({ score: score, item: "<li style='" + liStyle + "'><a href='" + elLink.attr("href") + "'>" + elLinkContent + "</a></li>" });
}
}
});
if ($("#search-results-list").length == 0) {
// append to nav
$("#nav").parent().append("<ul id='search-results-list' class='nav nav-list'></ul>");
}
listItems.sort(function (x, y) { return x.score - y.score; }); // put in order
$("#search-results-list").css("display", "block").html(listItems.map(function (x) { return x.item; }).join(""));
// pre-select the first item
$("#search-results-list a").removeClass("selected");
$("#search-results-list a:first").addClass("selected");
}
function match(textParts, query) {
var queryParts = query.split(".");
if (queryParts.length == 1) {
var queryPart = queryParts[0];
for (var i = 0; i < textParts.length; ++i) {
var textPart = textParts[i];
if (textPart.indexOf(queryPart) > -1) {
// We don't want to match the same part twice, so let's remove it
textParts[i] = textParts[i].split(queryPart).join("");
return textPart.length - queryPart.length;
}
}
} else {
var offset = -1;
outer:
while (true) {
++offset;
if (queryParts.length + offset > textParts.length) {
return -1;
}
var scoreSum = 0;
for (var i = 0; i < queryParts.length; ++i) {
var queryPart = queryParts[i];
var textPart = textParts[i + offset];
var index = textPart.indexOf(queryPart);
if (index != 0) {
continue outer;
}
scoreSum += textPart.length - queryPart.length;
}
return scoreSum;
}
}
}
function searchMatch(text, queryParts) {
text = text.toLowerCase();
var textParts = text.split(".");
var scoreSum = 0;
for (var i = 0; i < queryParts.length; ++i) {
var score = match(textParts, queryParts[i]);
if (score == -1) {
return -1;
}
scoreSum += score + text.length;
}
return scoreSum;
}
function errorSearch() {
var errorURL = "";
if (!!window.location.pathname) {
errorURL = window.location.pathname;
} else if (!!window.location.href) {
errorURL = window.location.href;
}
if (!!errorURL) {
var searchTerm = errorURL.split("/").pop();
if (searchTerm.indexOf(".html") > -1) { searchTerm = searchTerm.split(".html").join(""); }
if (!!searchTerm) {
// update filter with search term
$("#search").val(searchTerm);
searchQuery(searchTerm);
}
}
}
File diff suppressed because one or more lines are too long
+527
View File
@@ -0,0 +1,527 @@
.main-content {
margin-top: 15px;
}
.dark {
background: rgb(20, 20, 25);
color: white;
}
.dark a {
color: white;
}
.dark a:hover {
color: rgb(200, 200, 200);
}
.dark blockquote {
border-left: 3px solid rgb(126, 126, 129);
}
.dark blockquote small {
color: white;
font-weight: bold;
}
.dark blockquote small:before {
display: none;
}
/* #nav { */
/* float: left; */
/* width: 250px; */
/* background: green; */
/* } */
/*#content .header { position:absolute; background:rgba(255,255,255,0.9); left:250px; right:15px; padding:0px 12px; border-bottom:1px solid #EEE;}*/
/*#content .body { padding-top:80px;}*/
.nav-list {
padding-right: 0;
}
.nav-list>li>a,
.nav-list .nav-header {
margin-right: 0;
}
.nav-list>li>a.treeLink {
padding-left: 20px;
}
.nav-list a {
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px;
text-shadow: none !important;
}
.nav-list>.active>a.treeLink,
.nav-list>.active>a.treeLink:hover,
.nav-list>.active>a.treeLink:focus {
background: #999;
color: #fff;
}
.nav>li>a.selected,
.nav>li>a:hover {
background-color: #00000010;
}
.nav-list li i.fa {
height: 16px;
width: 16px;
color: rgb(200, 200, 200);
font-weight: normal;
font-size: 16px;
padding-right: 5px;
}
.viewsource {
float: right
}
/** Footer sitemap **/
footer {
font-size: 14px;
margin-top: auto;
}
.main-content {
margin-bottom: 40px;
}
.section.site-footer {
border-bottom: 0px;
}
.copyright {
padding: 6px;
overflow: hidden;
text-align: center;
margin: 40px 0;
}
.dark .copyright a {
color: #F48821;
}
/* .doc { margin-top:16px; } */
.toggle-hide {
display: block;
}
.toggle-show {
display: none;
}
.toggle-on .toggle-hide {
display: none !important;
}
.toggle-on .toggle-show {
display: block !important;
}
.related-types .toggle-hide {
padding-top: 4px;
}
/* #nav li { list-style-type: none; } */
#nav .expando>ul {
display: none;
}
#nav .expando.expanded>ul {
display: inherit;
}
/* #nav ul, #nav li li { margin-left: 10px; } */
#nav img {
padding-right: 4px;
}
#nav .pack {
display: none;
}
/* .nav .nav li { margin-left: 14px; } */
.dropdown {
padding: 0 9px;
}
#nav.searching .expando>ul {
display: inherit;
}
#nav.searching .expando>a {
display: none;
}
#nav.searching ul {
margin-left: 0px;
}
#nav.searching .pack {
display: inline;
}
#nav.searching .nav-list .nav-list {
padding-left: 0;
padding-right: 0;
}
.nav-header {
text-transform: none;
font-size: 14px;
color: #555;
text-shadow: none;
}
.availability {
color: #e48931;
font-size: 90%;
}
.section-availability {
color: #e48931;
}
h3 code {
background: none;
box-shadow: 0 0 15px rgb(240, 240, 240);
padding: 4px 8px;
white-space: inherit;
display: inline-block;
line-height: 1.5em;
margin-left: -10px;
}
h3 span.label,
.label-meta {
margin-right: 5px;
}
.label.label-meta {
background: #5959AC;
}
/* only show some specific whitelisted metadata */
.label-meta {
display: none;
}
.label-meta-callable,
.label-meta-commutative,
.label-meta-op,
.label-meta-arrayAccess,
.label-meta-resolve,
.label-meta-to,
.label-meta-from,
.label-meta-using,
.label-meta-forward,
.label-meta-forwardStatics {
display: inline;
}
.alert.alert-deprecated {
font-size: 90%;
margin-bottom: 10px;
padding: 4px 35px 4px 14px;
}
code {
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
font-weight: normal;
color: #666;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
white-space: nowrap;
border-radius: 3px;
padding: 2px 4px;
font-size: 13px;
}
code .identifier {
font-family: bold 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #002b36;
padding: 0 0 0 5px;
}
code .identifier,
code.type {
font-weight: bold;
}
/* code { background:#FDF6E3; color:#002b36; tab-size:4; } [> light <] */
code a {
text-decoration: none;
}
code a:hover {
text-decoration: underline;
}
/*code.dark { background:#272822; color:#F8F8F2; border:none; } */
code .type {
color: #268bd2;
}
/* code .keyword { color:#dc322f; } */
/* code .directive { color:#2aa198; } */
/* code .constant { color:#AE81FF; } */
/* code .comment { color:#75715E; } */
/* code .string { color:#E6DB74; } */
/* code .macro { color:#A6E22A; } */
/* code .inactive { color:#75715E; } */
/* .navbar-fixed-top { position: fixed; } */
/* .navbar-fixed-top .navbar-inner, */
/* .navbar-fixed-bottom .navbar-inner { padding: 0; } */
html,
body {
height: 100%;
margin: 0;
}
body {
margin: 0px;
padding: 0px;
font-size: 16px;
font-family: "Open Sans", sans-serif;
color: #1e1e1e;
line-height: 1.5;
display: flex;
flex-direction: column;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: "Source Sans Pro", sans-serif;
font-weight: 600;
word-wrap: break-word;
}
h1 {
font-size: 36px;
color: #171717;
}
h1 small {
font-size: 14px;
color: #999;
font-weight: normal;
}
h2 {
font-size: 30px;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 20px;
}
h5,
h5 code {
font-size: 18px;
}
h6 {
font-size: 16px;
}
.sidebar-nav {
padding: 9px 0;
}
#explorer {
max-height: 70vh;
overflow-y: auto;
}
#searchForm {
padding: 0 9px;
margin-bottom: 10px;
}
#searchForm .control-group {
margin: 0;
}
.indent {
margin-left: 20px;
border-left: 5px solid #eeeeee;
padding-left: 20px;
}
table.params {
border-left: 5px solid #eeeeee;
margin-left: 20px;
}
table.params th {
background: #fcfcfc;
}
.doc-main {
margin-bottom: 40px;
}
.section {
border-bottom: 1px solid #eee;
}
.table p {
margin: 3px 0;
}
.table th,
.table td {
border-top: 0;
border-bottom: 1px solid #ccc;
}
.table a small {
color: #666;
}
.table .fa {
color: rgb(200, 200, 200);
margin-right: 5px;
}
.javadoc {
/* font-weight: normal; */
/* font-size: small; */
margin-top: 20px;
}
.inline-content * {
display: inline;
}
/**
* Stuff for input-block-level:
* http://stackoverflow.com/questions/13306670/bootstrap-prepended-and-appended-input-how-to-max-input-field-width
*/
.input-append.input-block-level,
.input-prepend.input-block-level {
display: table;
}
.input-append.input-block-level .add-on,
.input-prepend.input-block-level .add-on {
display: table-cell;
}
.input-append.input-block-level>input,
.input-prepend.input-block-level>input {
box-sizing: border-box;
/* use bootstrap mixin or include vendor variants */
-moz-box-sizing: border-box;
/* for Firefox */
-webkit-box-sizing: border-box;
/* for Firefox */
-ms-box-sizing: border-box;
/* for Firefox */
-o-box-sizing: border-box;
/* for Firefox */
display: table;
/* table-cell is not working well in Chrome for small widths */
min-height: inherit;
width: 100%;
}
.input-append.input-block-level>input {
border-right: 0;
}
.input-prepend.input-block-level>input {
border-left: 0;
}
.field {
padding-bottom: 10px;
}
.field+.field {
border-top: 1px solid #eee;
margin-top: 10px;
}
.fields {
margin-left: 40px;
}
.field-source {
margin-top: 15px;
visibility: hidden;
}
.field:hover .field-source {
visibility: inherit;
}
pre.example {
position: relative;
padding-top: 34.5px;
}
pre.example:before {
position: absolute;
top: -1px;
left: -1px;
content: "Example";
color: #999;
padding: 2px 6px;
background: #fff;
font-weight: bold;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-moz-border-radius: 4px 0;
-ms-border-radius: 4px 0;
-webkit-border-radius: 4px 0;
border-radius: 4px 0;
border: 1px solid rgba(0, 0, 0, 0.15);
}
.inherited-fields {
padding: 5px 20px;
margin-top: 1em;
background: #fcfcfc;
}
@media (max-width: 767px) {
.navbar-fixed-top,
.navbar-fixed-bottom,
.navbar-static-top {
margin-right: 0;
margin-left: 0;
}
.navbar .divider {
display: none;
}
.main-content {
margin-top: 0px;
}
}
@media (max-width: 979px) {
.main-content {
margin-top: 15px;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

+12
View File
@@ -0,0 +1,12 @@
::use 'main.mtt'::
<script type="text/javascript">
$(document).ready(errorSearch);
</script>
<h1><small>404</small> Page not found</h1>
<p>Page not found, sorry.</p>
::end::
@@ -0,0 +1,35 @@
::use 'main.mtt'::
<div class="page-header">
<span ::cond api.hasSourceLink(type):: class="viewsource">
<a href="::api.getSourceLink(type)::" class="btn btn-medium"><i class="fa fa-eye"></i> View source</a>
</span>
<h1><small>::if api.isEnumAbstract(type)::enum ::end::abstract</small> ::api.getPathName(type.path)::$$printTypeParams(::type.params::)::if !api.isCoreType(type)::($$printLinkedType(::type.athis::,::false::))::end::</h1>
$$printPackage(::type::)
<h4 ::cond (type.from != null || type.to != null)::>
::foreach t type.from::
::if t.field == null::
<small>::if(repeat.t.index==0)::from ::end::$$printLinkedType(::t.t::,::false::)::if((type.from.length!=1)&&(repeat.t.index<type.from.length-1))::, ::end::</small>
::end::
::end::
::foreach t type.to::
::if t.field == null::
<small>::if(repeat.t.index==0):: to ::end::$$printLinkedType(::t.t::,::false::)::if((type.to.length!=1)&&(repeat.t.index<type.to.length-1))::, ::end::</small>
::end::
::end::
</h4>
$$printModule(::type.module::)
$$printMeta(::type::)
$$printDeprecation(::type::)
$$printPlatforms(::type.platforms::,::true::)
</div>
<div class="body">
<div class="doc doc-main" ::cond type.doc != null::>
::raw type.doc::
</div>
::if type.impl != null::
$$printClassBody(::type.impl::)
::end::
</div>
::end::
+68
View File
@@ -0,0 +1,68 @@
::use 'main.mtt'::
<div class="page-header">
<span ::cond api.hasSourceLink(type):: class="viewsource">
<a href="::api.getSourceLink(type)::" class="btn btn-medium"><i class="fa fa-eye"></i> View source</a>
</span>
<h1>
<small>::if type.isFinal::final ::end::::if type.isInterface::interface::else::class::end::</small> ::api.getPathName(type.path)::$$printTypeParams(::type.params::)
</h1>
$$printPackage(::type::)
::if type.superClass != null::
<h4>
::set inheritedFields = api.getInheritedFields(type)::
<small>extends
::if (inheritedFields.types.length>0)::
::foreach t inheritedFields.types::
$$printLinkedPath(::t.path::,::null::,::false::)::if ((inheritedFields.types.length!=1)&&(repeat.t.index<(inheritedFields.types.length-1))):: &rsaquo; ::end::
::end::
::else::
$$printLinkedPath(::type.superClass.path::,::null::,::false::)
::end::
</small>
</h4>
::end::
<h4 ::cond (type.interfaces.length>0)::>
<small>::if type.isInterface::extends::else::implements::end::
::foreach i type.interfaces::
$$printLinkedPath(::i.path::,::i.params::,::false::)::if ((type.interfaces.length!=1)&&(repeat.i.index<(type.interfaces.length-1)))::, ::end::
::end::
</small>
</h4>
$$printModule(::type.module::)
<h4 ::cond subClasses !=null::>
<small>
::set title = "extended by "::
::set infos = subClasses::
::use "related_types.mtt"::::end::
</small>
</h4>
<h4 ::cond implementors !=null::>
<small>
::if type.isInterface::
::set title = "extended by "::
::else::
::set title = "implemented by "::
::end::
::set infos = implementors::
::use "related_types.mtt"::::end::
</small>
</h4>
$$printMeta(::type::)
$$printDeprecation(::type::)
$$printPlatforms(::type.platforms::,::true::)
</div>
<div class="body">
<div class="doc doc-main" ::cond type.doc != null::>
::raw type.doc::
</div>
$$printClassBody(::type::)
$$printInheritedFields(::type::)
</div>
::end::
@@ -0,0 +1,27 @@
::if (field.doc != null && field.doc != "<p></p>") || !field.isOverride::
<div class="field ::if (depth == 0 && api.isPlatform(name)) " platform platform-" + name else ""::">
::if source_url != null && field.line != null::
<a href="::source_url::#L::field.line::" class="field-source pull-right" target="_blank">
<i class="fa fa-eye"></i> View source
</a>
::end::
<a ::attr name field.name::></a>
<h3 class="anchor">$$printFieldSignature(::field::,::isStatic::,::type::)</h3>
::if field.overloads != null::
::foreach field field.overloads::
<h3 class="anchor">$$printFieldSignature(::field::,::isStatic::,::type::)</h3>
::end::
::end::
$$printDeprecation(::field::)
$$printFieldPlatforms(::field::)
::if field.doc != null::
<div class="doc">::raw field.doc::</div>
::end::
</div>
::end::
+56
View File
@@ -0,0 +1,56 @@
::if info.deprecated != null::
<div class="alert inline-content">
<strong>Deprecated</strong>: ::raw info.deprecated.doc::
</div>
::end::
::raw info.doc::
::if info.params.length > 0::
<p class="javadoc">Parameters:</p>
<table class="table table-bordered params">
::foreach param info.params::
<tr><th style="width:25%;"><code>::param.value::</code></th><td>::raw param.doc::</td></tr>
::end::
</table>
::end::
::if info.returns != null::
<p class="javadoc">Returns:</p>
<div class="indent inline-content">
::raw info.returns.doc::
</div>
::end::
::if info.throws.length > 0::
<p class="javadoc">Throws:</p>
<table class="table table-bordered params">
::foreach throws info.throws::
<tr class="indent"><th style="width:25%;"><code>::throws.value::</code></th><td>::raw throws.doc::</td></tr>
::end::
</table>
::end::
::if info.events.length > 0::
<p class="javadoc">Events:</p>
<table class="table table-bordered params">
::foreach event info.events::
<tr class="indent"><th style="width:25%;"><code>::event.value::</code></th><td>::raw event.doc::</td></tr>
::end::
</table>
::end::
::if info.since != null::
<div class="javadoc inline-content">
Available since ::raw info.since.doc::.
</div>
::end::
::if info.sees.length > 0::
<p class="javadoc">See also:</p>
<ul>
::foreach see info.sees::
<li><div class="inline-content">::raw see.doc::</div></li>
::end::
</ul>
::end::
+26
View File
@@ -0,0 +1,26 @@
::use 'main.mtt'::
<div class="page-header">
<span ::cond api.hasSourceLink(type):: class="viewsource">
<a href="::api.getSourceLink(type)::" class="btn btn-medium"><i class="fa fa-eye"></i> View source</a>
</span>
<h1><small>enum</small> ::api.getPathName(type.path)::$$printTypeParams(::type.params::)</h1>
$$printPackage(::type::)
$$printModule(::type.module::)
$$printMeta(::type::)
$$printDeprecation(::type::)
$$printPlatforms(::type.platforms::,::true::)
</div>
<div class="body">
<div class="doc doc-main" ::cond type.doc != null::>
::raw type.doc::
</div>
::if type.constructors.length > 0::
<h3 class="section">Values</h3>
<div class="fields">
::foreach ctor type.constructors::
::use "enum_field.mtt"::::end::
::end::
</div>
::end::
</div>
::end::
@@ -0,0 +1,19 @@
<div class="field">
<h3>
<code>
<a name="::ctor.name::" href="#::ctor.name::">
<span class="identifier">::ctor.name::</span>
</a>
::if ctor.args != null::
(::foreach arg ctor.args::::arg.name:::$$printLinkedType(::arg.t::,::false::)::if !repeat.arg.last::, ::end::::end::)
::end::
</code>
</h3>
$$printDeprecation(::ctor::)
$$printFieldPlatforms(::ctor::)
<div class="doc" ::cond ctor.doc != null::>
::raw ctor.doc::
</div>
</div>
@@ -0,0 +1 @@
@@ -0,0 +1,10 @@
<footer class="section site-footer" style="background:$$getHexValue(::themeColor::)">
<div class="container">
<div class="copyright">
<p ::cond api.isDefined("version")::>This documentation is generated for version ::api.getValue('version')::</p>
<p>&copy; ::api.config.date.getFullYear():: &nbsp;
<a ::cond api.isDefined("website"):: ::attr href api.getValue("website")::>The Funkin' Crew Inc</a>
</p>
</div>
</div>
</footer>
@@ -0,0 +1,36 @@
<head>
<meta charset='utf-8'/>
<link href="::api.config.rootPath::bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="::api.config.rootPath::bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" />
<link href="::api.config.rootPath::bootstrap/css/bootstrap-select.min.css" rel="stylesheet" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700,700italic,400italic' rel='stylesheet' type='text/css'/>
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:200,600,600italic,400' rel='stylesheet' type='text/css'/>
<link href='https://netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.css' rel='stylesheet' type='text/css' />
<script src="::api.config.rootPath::jquery-3.6.0.min.js"></script>
<script src="::api.config.rootPath::bootstrap/js/bootstrap.min.js"></script>
<script src="::api.config.rootPath::bootstrap/js/bootstrap-select.min.js"></script>
<link href="::api.config.rootPath::styles.css" rel="stylesheet" />
<link href="::api.config.rootPath::extra-styles.css" rel="stylesheet" />
<link href="::api.config.rootPath::haxe-nav.css" rel="stylesheet" />
<link href="::api.config.rootPath::dark-mode.css" rel="stylesheet" />
<script>var dox = {
rootPath: "::api.config.rootPath::",
platforms: [
::foreach pf api.config.platforms::
"::pf::"
::if !repeat.pf.last::,::end::
::end::
]
};</script>
<script src="::api.config.rootPath::nav.js"></script>
<script src="::api.config.rootPath::index.js"></script>
<link rel="icon" href="https://funkin.me/img/construction-icon.ico" type="image/x-icon"/>
<title>::api.currentPageName::::if api.config.pageTitle !=null:: - ::api.config.pageTitle::::end::</title>
::set description = api.getShortDesc(type)::
::set description = description.substr(3, description.length-7)::
<meta name="description" ::cond type.doc!=null && description.length>0:: content="::description::"/>
::use "extra-headers.mtt"::::end::
</head>
+336
View File
@@ -0,0 +1,336 @@
<macro name="printTypeParams(params)">
::if params.length > 0::
&lt;
::foreach param params::
<span class="type">::param::</span>
::if !repeat.param.last::, ::end::
::end::
&gt;
::end::
</macro>
<macro name="getHexValue(value)">::value.split("0x").join("#")::</macro>
<macro name="printPlatforms(platforms, useSeparator)">
::if (useSeparator && api.config.platforms.length>1)::<hr/>::end::
<p class="availability" ::cond (api.config.platforms.length>1)::>
<em>
Available on
::if platforms.length == api.config.platforms.length:: all platforms
::elseif platforms.length > 1:: ::platforms.join(", ")::
::else:: ::platforms.join("")::
::end::
</em>
</p>
</macro>
<macro name="printFieldPlatforms(field)">
::if field.platforms.length != type.platforms.length && field.platforms.length > 0 && field.platforms.length < api.config.platforms.length::
$$printPlatforms(::field.platforms::,::false::)
::end::
</macro>
<macro name="printLinkedPath(path, params, qualified)">
::if api.isKnownType(path)::
<a class="type" title="::api.getSentenceDesc(api.resolveType(path))::" ::attr href api.pathToUrl(path)::>
::if qualified::
::path::
::else::
::api.getPathName(path)::
::end::
</a>
::else::
<span class="type">::api.getPathName(path)::</span>
::end::
::if params != null && params.length > 0::
&lt;
::foreach param params::
$$printLinkedType(::param::,::qualified::)
::if !repeat.param.last::, ::end::
::end::
&gt;
::end::
</macro>
<macro name="printLinkedType(ctype, qualified)">
::switch ctype::
::case::Unknown
::case::$$printLinkedPath(::args[0]::,::args[1]::,::qualified::)
::case::$$printLinkedPath(::args[0]::,::args[1]::,::qualified::)
::case::$$printLinkedPath(::args[0]::,::args[1]::,::qualified::)
::case::
::if args[0].length != 1 || args[0][0].name != ""::(::end::
::foreach arg args[0]::
::if arg.name != ""::
::arg.name:::
::end::
$$printLinkedType(::arg.t::,::qualified::)
::if !repeat.arg.last::, ::end::
::end::
::if args[0].length != 1 || args[0][0].name != ""::)::end::
&nbsp;&#8209;&gt;&nbsp;
$$printLinkedType(::args[1]::,::qualified::)
::case::
{
::foreach field args[0]::
::field.name:::$$printLinkedType(::field.type::,::qualified::)
::if !repeat.field.last::, ::end::
::end::
}
::case::$$printLinkedPath(::"Dynamic"::,::null::,::qualified::)::if args[0] != null::&lt;$$printLinkedType(::args[0]::,::qualified::)&gt;::end::
::case::$$printLinkedPath(::args[0]::,::args[1]::,::qualified::)
::end::
</macro>
<macro name="printModule(module)">
<h4 ::cond module != null && module != "StdTypes"::><small>import <a ::attr href api.pathToUrl(module)::>::module::</a></small></h4>
</macro>
<macro name="printDeprecation(field)">
::if (field.meta != null)::
::foreach meta field.meta::
::if (meta.name == ":deprecated")::
<div class="alert alert-warning alert-deprecated">
<strong>Deprecated:</strong>
::if (meta.params != null && meta.params.length > 0)::
::foreach param meta.params::
::param::
::if !repeat.param.last::, ::end::
::end::
::end::
</div>
::end::
::end::
::end::
</macro>
<macro name="printMeta(field)">
::if (field.meta != null)::
::foreach meta field.meta::
::if (meta.name != ":deprecated")::::if false::<!--skip deprecation meta, see printDeprecation -->::end::
::set metaName = meta.name.substr(1)::
::set displayMetaName = "@" + meta.name::
<span class="label label-meta label-meta-::metaName::" title="::api.getMetaDesc(meta.name)::">::displayMetaName::
::if (meta.params != null && meta.params.length > 0)::(
::foreach param meta.params::
$$printMetaParam(::param::)
::if !repeat.param.last::,::end::
::end::
)::end::</span>
::end::
::end::
::end::
</macro>
<macro name="printMetaParam(param)">::if (param.substr(0,9) == "<![CDATA[")::::param.substr(9,param.length-3-9)::::else::::param::::end::</macro>
<macro name="printFieldSignature(field, isStatic, type)">
<code>
::if !field.isPublic::
<span class="label label-private">private</span>
::end::
$$printMeta(::field::)
::if isStatic::
<span class="label label-static">static</span>
::end::
::set fieldInfo = api.getFieldInfo(field)::
::if fieldInfo.modifiers.isOptional::
<span class="label label-optional">optional</span>
::end::
::if fieldInfo.modifiers.isFinal::
<span class="label label-final">final</span>
::end::
::if fieldInfo.modifiers.isDynamic::
<span class="label label-dynamic">dynamic</span>
::end::
::if fieldInfo.modifiers.isInline::
<span class="label label-inline">inline</span>
::end::
::switch fieldInfo.kind::
::switch field.set::
::case 1::
<span class="label">read only</span>
::end::
::switch field.get::
::case 1::
<span class="label">write only</span>
::end::
<a href="#::field.name::"><span class="identifier">::field.name::</span></a>:$$printLinkedType(::field.type::,::false::)$$printInitExpr(::field.expr::)
::case 2::
<a href="#::field.name::"><span class="identifier">::field.name::</span></a>
$$printTypeParams(::field.params::)(
::foreach arg args[0]::
<span style="white-space:nowrap">
::if arg.opt && (arg.value == null || arg.value == "null")::?::end::
::arg.name:::$$printLinkedType(::arg.t::,::false::)
::if arg.value != null && arg.value != "null":: = ::arg.value::::end::
::if !repeat.arg.last::,::end::
</span>
::if !repeat.arg.last:: ::end::
::end::
)
::if field.name != "new"::
:$$printLinkedType(::args[1]::,::false::)
::end::
::end::
</code>
</macro>
<macro name="printInitExpr(expr)">
<span ::cond expr != null::>
= ::expr::
</span>
</macro>
<macro name="printClassBody(type)">
::set showSection = false::
::foreach field type.statics::
::if !api.isMethod(field)::
::eval showSection = true::
::end::
::end::
::if showSection::
<h3 class="section">Static variables</h3>
<div class="fields">
::foreach field type.statics::
::set isStatic = true::
::if !api.isMethod(field)::
::use "class_field.mtt"::::end::
::end::
::end::
</div>
::end::
::set showSection = false::
::foreach field type.statics::
::if api.isMethod(field)::
::eval showSection = true::
::end::
::end::
::if showSection::
<h3 class="section">Static methods</h3>
<div class="fields">
::foreach field type.statics::
::set isStatic = true::
::if api.isMethod(field)::
::use "class_field.mtt"::::end::
::end::
::end::
</div>
::end::
::set showSection = false::
::foreach field type.fields::
::if field.name == "new" && api.isMethod(field)::
::eval showSection = true::
::end::
::end::
::if showSection::
<h3 class="section">Constructor</h3>
<div class="fields">
::foreach field type.fields::
::set isStatic = false::
::if field.name == "new" && api.isMethod(field)::
::use "class_field.mtt"::::end::
::end::
::end::
</div>
::end::
::set showSection = false::
::foreach field type.fields::
::if !api.isMethod(field)::
::eval showSection = true::
::end::
::end::
::if showSection::
<h3 class="section">Variables</h3>
<div class="fields">
::foreach field type.fields::
::set isStatic = false::
::if !api.isMethod(field)::
::use "class_field.mtt"::::end::
::end::
::end::
</div>
::end::
::set showSection = false::
::foreach field type.fields::
::if field.name != "new" && api.isMethod(field)::
::eval showSection = true::
::end::
::end::
::if showSection::
<h3 class="section">Methods</h3>
<div class="fields">
::foreach field type.fields::
::set isStatic = false::
::if field.name != "new" && api.isMethod(field)::
::use "class_field.mtt"::::end::
::end::
::end::
</div>
::end::
</macro>
<macro name="printInheritedFields(type)">
::if type.superClass != null::
::set inheritedFields = api.getInheritedFields(type)::
::set hasFields = inheritedFields.fields.keys().hasNext()::
::set hasMethods = inheritedFields.methods.keys().hasNext()::
<div class="inherited-fields well" ::cond hasFields || hasMethods::>
<h3 class="section" ::cond hasFields::>Inherited Variables</h3>
<div class="fields" ::cond hasFields::>
::set fields=inheritedFields.fields::
::foreach cl inheritedFields.types::
<h4 ::cond fields.get(cl).length>0::><a href="#" class="expand-button"><i class="fa fa-arrow-circle-o-right"></i></a> Defined by $$printLinkedPath(::cl.path::,::null::,::false::)</h4>
<div style="display:none">
::foreach field fields.get(cl)::
::set isStatic = false::
::set type=cl::
::use "class_field.mtt"::::end::
::end::
</div>
::end::
</div>
<h3 class="section" ::cond hasMethods::>Inherited Methods</h3>
<div class="fields" ::cond hasMethods::>
::set fields=inheritedFields.methods::
::foreach cl inheritedFields.types::
<h4 ::cond fields.get(cl).length>0::><a href="#" class="expand-button"><i class="fa fa-arrow-circle-o-right"></i></a> Defined by $$printLinkedPath(::cl.path::,::null::,::false::)</h4>
<div style="display:none">
::foreach field fields.get(cl)::
::set isStatic = false::
::if field.name != "new" ::
::set type=cl::
::use "class_field.mtt"::::end::
::end::
::end::
</div>
::end::
</div>
</div>
::end::
</macro>
<macro name="printPackage(type)">
::if type.path.indexOf(".", 0) >= 0::
::set packagePath = type.path.split(".").slice(0, -1).join(".")::
<h4><small>package <a ::attr href api.packageToUrl(packagePath)::>::packagePath::</a></small></h4>
::else::
<h4><small><a href="./">no package</a></small></h4>
::end::
</macro>
+73
View File
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<!-- use theme color or fallback -->
::set themeColor="0xFAFAFA"::
::if (api.isDefined("themeColor"))::::set themeColor=api.getValue("themeColor")::::end::
<!--use textcolor from settings, otherwise create a contrasting color to theme color-->
::set textColor="0xFFFFFF"::
::if (api.isDefined("textColor"))::::set textColor=api.getValue("textColor")::
::elseif (api.std.parseInt(themeColor) > 7829367)::::set textColor="0x000000"::::end::
::use "header.mtt"::::end::
<body>
<script>
/* Here to prevent flash of unstyled content */
let systemDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
if ((!localStorage.theme && systemDarkMode) || localStorage.theme == "dark") {
document.body.style.backgroundColor = "#111";
document.body.style.opacity = "0";
document.addEventListener("DOMContentLoaded", function(event) {
toggleTheme();
document.body.style.backgroundColor = "";
document.body.style.opacity = "";
});
}
</script>
::use "topbar.mtt"::::end::
<div class="container main-content">
<div class="row-fluid">
<div class="span3">
<div class="well sidebar-nav">
<form class="form-search" id="searchForm">
<div class="input-prepend input-block-level">
<span class="add-on"><i class="fa fa-search"></i></span>
<input id="search" type="text" placeholder="Filter (Ctrl+P)" autocomplete="off"/>
</div>
</form>
<div class="dropdown" ::cond (api.config.platforms.length>1)::>
<select id="select-platform" class="selectpicker" title="Filter by platform" data-width="100%">
<option value="all" selected="selected">All Platforms</option>
::foreach i api.config.platforms::
<option>::i::</option>
::end::
</select>
</div>
</div>
<div class="well sidebar-nav" id="explorer">
<div id="nav"></div>
</div>
</div>
<div class="span9">::raw __content__::</div>
</div>
</div>
::use "footer.mtt"::::end::
<script src="::api.config.rootPath::highlighter.js"></script>
<link href="::api.config.rootPath::highlighter.css" rel="stylesheet" />
::if (api.isDefined("googleAnalytics"))::
::set trackingID=api.getValue("googleAnalytics")::
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=::trackingID::"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '::trackingID::');
</script>
::end::
</body>
</html>
+33
View File
@@ -0,0 +1,33 @@
<macro name="makeTree(tree,depth)">
::switch tree::
<li ::attr data_path api.getTreePath(tree)::>
::set pack = api.getTreePack(tree)::
<a class="treeLink" href="::api.getTreeUrl(tree)::" title=":: pack + "." + api.getTreeName(tree) ::">
::api.getTreeName(tree)::
::if pack != ""::
<span class="pack">&nbsp;-&nbsp;::pack::</span>
::end::
</a>
</li>
::case::
::set name = args[0]::
<li ::cond name.charAt(0) != "_"::
::attr class "expando " + if (depth == 0 && api.isPlatform(name)) "platform platform-" + name else if (depth == 0) "package-" + name else "" ::>
<a class="nav-header" href="#" onclick="return toggleCollapsed(this)">
<i class="fa fa-folder"></i>
::api.getTreeName(tree)::
</a>
<ul class="nav nav-list">
::foreach sub args[2]::
$$makeTree(::sub::,::depth + 1::)
::end::
</ul>
</li>
::end::
</macro>
var navContent='<ul class="nav nav-list">
::foreach tree root::
$$makeTree(::tree::,::0::)
::end::
</ul>
';
@@ -0,0 +1,37 @@
::use 'main.mtt'::
::use 'package_description.mtt'::::end::
<table class="table table-condensed">
<tbody>
<tr ::cond full != ""::>
<th style="width:200px;">
<i class="fa fa-folder-o"></i>
<a href="::api.packageToUrl(full.split(".").slice(0,-1).join("."))::" title="::full.split(".").slice(0,-1).join(".")::">..</a>
</th>
<td></td>
</tr>
::foreach tree subs::
::set name = api.getTreeName(tree)::
::set treeType = api.getTreeType(tree)::
<tr class="::treeType::" ::cond name.charAt(0) != "_"::>
::if (treeType=="package")::
<td colspan="2">
<i class="fa fa-folder-o"></i>
<a href="::api.getTreeUrl(tree)::" title="::full::.::name::">::name::</a>
</td>
::else::
<td style="width:200px;">
<a href="::api.getTreeUrl(tree)::" title="::full::.::name::">::name::</a>
</td>
<td>
::raw api.getTreeShortDesc(tree)::
</td>
::end::
</tr>
::end::
</tbody>
</table>
::end::
@@ -0,0 +1,2 @@
<h1>::api.currentPageName:: <small ::cond api.isDefined("version") && full == ""::>version ::api.getValue('version')::</small></h1>
<p ::cond api.isDefined("description")::>::api.getValue("description")::</p>
@@ -0,0 +1,4 @@
<span class="muted">::title::</span>
::foreach info infos::
$$printLinkedPath(::info.path::,::null::,::false::)::if !repeat.info.last::, ::end::
::end::
@@ -0,0 +1,23 @@
<style>
::raw "
.navbar .brand {
display: inline-block;
float: none;
text-shadow: 0 0 0 transparent;
}
"::
</style>
<nav class="nav">
<div class="navbar">
<div class="navbar-inner" style="background:$$getHexValue(::themeColor::); border-bottom:1px solid rgba(0,0,0,.09)">
<div class="container">
<a href="https://funkin.me/" class="brand"><img alt="The Funkin' Crew Inc main website" src="https://funkin.me/img/api/funkin-api-export.svg" width="150" height="50"/></a>
<a href="https://funkin.me/api-reference/" class="brand" style="color:$$getHexValue(::textColor::)">::if api.config.pageTitle!=null::::api.config.pageTitle::::else::API Documentation::end::</a>
<div class="brand">
<p>|</p>
</div>
<a href="https://funkin.me/cookbook/" class="brand" style="color:$$getHexValue(::textColor::)">Cookbook</a>
</div>
</div>
</div>
</nav>
@@ -0,0 +1,49 @@
::use 'main.mtt'::
<div class="page-header">
<span ::cond api.hasSourceLink(type):: class="viewsource">
<a href="::api.getSourceLink(type)::" class="btn btn-medium"><i class="fa fa-eye"></i> View source</a>
</span>
<h1><small>typedef</small> ::api.getPathName(type.path)::$$printTypeParams(::type.params::)</h1>
$$printPackage(::type::)
$$printModule(::type.module::)
$$printMeta(::type::)
$$printDeprecation(::type::)
$$printPlatforms(::type.platforms::,::true::)
</div>
<div class="body">
<div class="doc doc-main" ::cond type.doc != null::>
::raw type.doc::
</div>
::set multiplePlatforms = api.lambda.array(type.types).length > 1::
::foreach platform type.types.keys()::
::set platformType = type.types.get(platform)::
::if multiplePlatforms::
<h4 class="section section-availability">::platform::</h4>
::end::
::switch platformType::
::if !multiplePlatforms::<h3 class="section">Alias</h3>::end::
<div class="fields">
<div class="field">
<em>alias for </em><code>$$printLinkedType(::platformType::,::true::)</code>
</div>
</div>
::case 5::
::if !multiplePlatforms::<h3 class="section">Fields</h3>::end::
<div class="fields">
::switch platformType::
::case 5::
::if args[0].length == 0::
<em>empty structure</em>
::else::
::foreach field args[0]::
::use "class_field.mtt"::::end::
::end::
::end::
::end::
</div>
::end::
::end::
</div>
::end::
+42
View File
@@ -0,0 +1,42 @@
cd ../..
# ask for version
$version = Read-Host "Enter version (Will display on the website)"
# regenerate XML files?
$regenerateXml = Read-Host "Regenerate XML files? (y/n)"
if ($regenerateXml -eq "y") {
Write-Host "Regenerating XML files..."
echo "Generating docs for version $version..."
lime build linux -xml -cpp --no-output -Ddoc-gen
lime build windows -xml -cpp --no-output -Ddoc-gen
copy export\release\windows\types.xml docs\dox\Windows.xml
copy export\release\linux\types.xml docs\dox\Linux.xml
} else {
Write-Host "Skipping XML regeneration..."
}
# Then run dox
haxelib run dox `
-i .\docs\dox\ `
-o docs/dox/output `
--title "Funkin'" `
-theme "docs/dox/funkin-theme" `
-D version "$version" `
-D source-path "https://github.com/FunkinCrew/Funkin/tree/main/source" `
-D website "https://funkin.me/" `
-D description "Friday Night Funkin' API Reference" `
-in "funkin" `
-in "openfl" `
-in "lime" `
-in "flixel" `
-ex "funkin.ui.debug.*" `
-ex "funkin.macro.*" `
-ex "funkin.save.*" `
-ex "funkin.api.*" `
-ex "funkin.vis.*"
cd docs/dox
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
cd ../..
# ask for version
read -p "Enter version (Will display on the website): " version
# regenerate XML files?
read -p "Regenerate XML files? (y/n): " regenerateXml
if [ "$regenerateXml" == "y" ]; then
echo "Regenerating XML files..."
echo "Generating docs for version $version..."
lime build windows -xml -cpp --no-output -Ddoc-gen
lime build linux -xml -cpp --no-output -Ddoc-gen
cp export/release/linux/types.xml docs/dox/Linux.xml
cp export/release/windows/types.xml docs/dox/Windows.xml
else
echo "Skipping XML regeneration..."
fi
# Then run dox
haxelib run dox \
-i ./docs/dox/ \
-o docs/dox/output \
-theme "docs/dox/funkin-theme" \
--title "Funkin'" \
-D version "$version" \
-D source-path "https://github.com/FunkinCrew/Funkin/tree/main/source" \
-D website "https://funkin.me/" \
-D description "Friday Night Funkin' API Reference" \
-in "funkin" \
-in "openfl" \
-in "lime" \
-in "flixel" \
-ex "funkin.ui.debug.*" \
-ex "funkin.macro.*" \
-ex "funkin.save.*" \
-ex "funkin.api.*" \
-ex "funkin.vis.*"
cd docs/dox
+45 -27
View File
@@ -4,62 +4,73 @@
"name": "FlxPartialSound",
"type": "git",
"dir": null,
"ref": "26ed20b9c181a576f4cbe18ccdea38912c01476e",
"ref": "13a0949395250216b9b500ca0731b46841e46085",
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
},
{
"name": "astc-compressor",
"type": "git",
"dir": null,
"ref": "b7a91b3072dc16e785a9bde847f17ba0ef15dd47",
"ref": "6c0fa6f46d3547ca58859b6ede87e659018a7ff5",
"url": "https://github.com/KarimAkra/astc-compressor"
},
{
"name": "extension-admob",
"type": "git",
"dir": null,
"ref": "4c69bb43f1fb89fd6003dc98d2f3a9d75c5364b6",
"ref": "68fc73c4090c5765709597b68fbe87389f3548c0",
"url": "https://github.com/FunkinCrew/extension-admob"
},
{
"name": "extension-agesignals",
"type": "git",
"ref": "dd3f56ccbb313a43d40cba8826fca2b1ec7c7e5d",
"url": "https://github.com/FunkinCrew/extension-agesignals"
},
{
"name": "extension-androidtools",
"type": "haxelib",
"version": "2.2.2"
},
{
"name": "extension-haptics",
"name": "dox",
"type": "haxelib",
"version": "1.0.4"
"version": "1.6.0"
},
{
"name": "extension-haptics",
"type": "git",
"ref": "8978b34b437f943a0d164bd6b3d8b69bd0025081",
"url": "https://github.com/LimeExtensions/extension-haptics"
},
{
"name": "extension-iapcore",
"type": "haxelib",
"version": "1.0.4"
"type": "git",
"ref": "5fbb4a8e56ff0f4d8ffc71b561d57a367419ead8",
"url": "https://github.com/LimeExtensions/extension-iapcore"
},
{
"name": "extension-iarcore",
"type": "haxelib",
"version": "1.0.3"
"type": "git",
"ref": "a78e49fe69feecef9abcdbcfd08ccc510ed00c6c",
"url": "https://github.com/LimeExtensions/extension-iarcore"
},
{
"name": "extension-webviewcore",
"type": "git",
"dir": null,
"ref": "d13109450d65c40678244ca23b1aa88ac18d77e6",
"ref": "98c059722491b182ee932ff47c5d7b564c967165",
"url": "https://github.com/LimeExtensions/extension-webviewcore"
},
{
"name": "flixel",
"type": "git",
"dir": null,
"ref": "c8e79d2a42f9c11c639519ef2a6fd7ef2379a8aa",
"ref": "141f23c400c0508c76d5a09a143f5ce6790f8122",
"url": "https://github.com/FunkinCrew/flixel"
},
{
"name": "flixel-addons",
"type": "git",
"dir": null,
"ref": "6fa30b3f5209146c852c25f3d1003e08898083e2",
"ref": "7628435364c4a45440d1e5db656741b66a8cd2ec",
"url": "https://github.com/FunkinCrew/flixel-addons"
},
{
@@ -72,7 +83,12 @@
{
"name": "format",
"type": "haxelib",
"version": "3.5.0"
"version": "3.8.0"
},
{
"name": "svg",
"type": "haxelib",
"version": "1.1.3"
},
{
"name": "funkin.vis",
@@ -88,6 +104,11 @@
"ref": "6409f3c6d1b4c52176813d3ede86c0d34e8af2c1",
"url": "https://github.com/FunkinCrew/grig.audio"
},
{
"name": "tink_core",
"type": "haxelib",
"version": "1.26.0"
},
{
"name": "hamcrest",
"type": "haxelib",
@@ -97,7 +118,7 @@
"name": "haxeui-core",
"type": "git",
"dir": null,
"ref": "088b153b35985f8e4419ef710057ebd5b3749513",
"ref": "998534fb830450ca1e60c47a9524af5730431145",
"url": "https://github.com/FunkinCrew/haxeui-core"
},
{
@@ -110,8 +131,7 @@
{
"name": "hxcpp",
"type": "git",
"dir": null,
"ref": "5932340d095a7eea8635fe4d1355f1c0efd0b3c2",
"ref": "0376e9b19af9a4d91f9d9afc131a358467856a10",
"url": "https://github.com/FunkinCrew/hxcpp"
},
{
@@ -146,13 +166,13 @@
{
"name": "hxvlc",
"type": "haxelib",
"version": "2.2.5"
"version": "2.3.0"
},
{
"name": "json2object",
"type": "git",
"dir": null,
"ref": "59e0467c953d1f26e3cbf2a070f140e2d2e8457d",
"ref": "dc945d58c1239a6ab6e37e0a6c128387193c9af5",
"url": "https://github.com/FunkinCrew/json2object"
},
{
@@ -168,29 +188,27 @@
{
"name": "lime",
"type": "git",
"dir": null,
"ref": "cae0c0bc10915f6281625d07e5527f3cecb4347f",
"ref": "268dacfb2609766e14bef9ea5b669e91501852d2",
"url": "https://github.com/FunkinCrew/lime"
},
{
"name": "newgrounds",
"type": "git",
"dir": null,
"ref": "b2b53cd0a5f030af74efd325732951cddbea8826",
"ref": "60162762e6ca65da011ffee7a6617f547ea5dff9",
"url": "https://github.com/FunkinCrew/Newgrounds"
},
{
"name": "openfl",
"type": "git",
"dir": null,
"ref": "5399946b68fd98f345d6b3e52b95ed6b78bf427c",
"ref": "74a51908a116d6df74be1083e219abb9fa057636",
"url": "https://github.com/FunkinCrew/openfl"
},
{
"name": "polymod",
"type": "git",
"dir": null,
"ref": "5d47a5c7c6b4e0cb94bd8fd45d012ca93bde9ab7",
"ref": "acfdc2e26722f20339a2bc0cc8cd7dd5fe0c6b5e",
"url": "https://github.com/FunkinCrew/polymod"
},
{
+272 -19
View File
@@ -18,8 +18,8 @@
"betweenTypes": 1,
"lineCommentsBetweenTypes": "keep",
"lineCommentsBetweenFunctions": "keep",
"lineCommentsBetweenTypes": "one",
"lineCommentsBetweenFunctions": "one",
"betweenSingleLineTypes": 0,
@@ -37,7 +37,7 @@
"betweenVars": 0,
"afterVars": 1,
"betweenFunctions": 1,
"existingBetweenFields": "keep"
"existingBetweenFields": "remove"
},
"classEmptyLines": {
@@ -54,7 +54,7 @@
"afterPrivateFunctions": 1,
"betweenFunctions": 1,
"existingBetweenFields": "keep"
"existingBetweenFields": "remove"
},
"macroClassEmptyLines": {
@@ -71,7 +71,7 @@
"afterPrivateFunctions": 1,
"betweenFunctions": 1,
"existingBetweenFields": "keep"
"existingBetweenFields": "remove"
},
"externClassEmptyLines": {
@@ -81,7 +81,7 @@
"betweenVars": 0,
"afterVars": 0,
"betweenFunctions": 0,
"existingBetweenFields": "keep"
"existingBetweenFields": "remove"
},
"abstractEmptyLines": {
@@ -98,7 +98,7 @@
"afterPrivateFunctions": 1,
"betweenFunctions": 1,
"existingBetweenFields": "keep"
"existingBetweenFields": "remove"
},
"interfaceEmptyLines": {
@@ -108,7 +108,7 @@
"betweenVars": 0,
"afterVars": 0,
"betweenFunctions": 0,
"existingBetweenFields": "keep"
"existingBetweenFields": "remove"
},
"enumEmptyLines": {
@@ -116,7 +116,7 @@
"endType": 0,
"betweenFields": 0,
"existingBetweenFields": "keep"
"existingBetweenFields": "remove"
},
"typedefEmptyLines": {
@@ -124,7 +124,7 @@
"endType": 0,
"betweenFields": 0,
"existingBetweenFields": "keep"
"existingBetweenFields": "remove"
},
"conditionalsEmptyLines": {
@@ -159,9 +159,9 @@
"lineEnds": {
"lineEndCharacter": "auto",
"metadataType": "none",
"metadataVar": "none",
"metadataFunction": "none",
"metadataType": "after",
"metadataVar": "forceAfterLast",
"metadataFunction": "forceAfterLast",
"metadataOther": "none",
"caseColon": "after",
@@ -214,7 +214,7 @@
"expressionIf": "same",
"expressionIfWithBlocks": false,
"forBody": "next",
"forBody": "same",
"comprehensionFor": "same",
@@ -229,7 +229,7 @@
"tryCatch": "next",
"caseBody": "next",
"expressionCase": "keep",
"expressionCase": "next",
"expressionTry": "same",
"functionBody": "same",
@@ -241,9 +241,45 @@
},
"whitespace": {
"parenConfig": {},
"parenConfig": {
"metadataParens": {
"openingPolicy": "none",
"closingPolicy": "none",
"removeInnerWhenEmpty": true
}
},
"bracesConfig": {},
"bracketConfig": {},
"bracketConfig": {
"arrayLiteralBrackets": {
"openingPolicy": "noneAfter",
"closingPolicy": "none",
"removeInnerWhenEmpty": true
},
"mapLiteralBrackets": {
"openingPolicy": "noneAfter",
"closingPolicy": "none",
"removeInnerWhenEmpty": true
},
"accessBrackets": {
"openingPolicy": "noneAfter",
"closingPolicy": "none",
"removeInnerWhenEmpty": true
},
"comprehensionBrackets": {
"openingPolicy": "none",
"closingPolicy": "none",
"removeInnerWhenEmpty": true
},
"unknownBrackets": {
"openingPolicy": "noneAfter",
"closingPolicy": "none",
"removeInnerWhenEmpty": true
}
},
"typeParamOpenPolicy": "none",
"typeParamClosePolicy": "none",
@@ -280,20 +316,237 @@
"wrapping": {
"maxLineLength": 160,
"arrayMatrixWrap": "matrixWrapWithAlign",
"arrayWrap": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0,
"rules": [
{
"type": "noWrap",
"conditions": [
{
"cond": "itemCount <= n",
"value": 1
},
{
"cond": "totalItemLength <= n",
"value": 160
}
]
},
{
"type": "onePerLine",
"conditions": [
{
"cond": "anyItemLength >= n",
"value": 32
}
]
},
{
"type": "onePerLine",
"conditions": [
{
"cond": "itemCount >= n",
"value": 5
}
]
},
{
"type": "onePerLine",
"conditions": [
{
"cond": "hasMultilineItems",
"value": 1
}
]
},
{
"type": "onePerLine",
"conditions": [
{
"cond": "totalItemLength >= n",
"value": 160
}
]
}
]
},
"mapWrap": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0,
"rules": [
{
"type": "onePerLine",
"conditions": [
{
"cond": "anyItemLength >= n",
"value": 32
}
]
},
{
"type": "onePerLine",
"conditions": [
{
"cond": "itemCount >= n",
"value": 5
}
]
},
{
"type": "onePerLine",
"conditions": [
{
"cond": "hasMultilineItems",
"value": 1
}
]
},
{
"type": "onePerLine",
"conditions": [
{
"cond": "lineLength >= n",
"value": 160
}
]
}
]
},
"methodChain": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0,
"rules": [
{
"additionalIndent": 0,
"location": "afterLast",
"type": "onePerLine",
"conditions": [
{
"cond": "lineLength >= n",
"value": 160
}
]
}
]
},
"callParameter": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0,
"rules": [
{
"additionalIndent": 0,
"location": "afterLast",
"type": "onePerLine",
"conditions": [
{
"cond": "lineLength >= n",
"value": 160
}
]
}
]
},
"objectLiteral": {
"defaultWrap": "onePerLine",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
},
"opBoolChain": {
"defaultWrap": "noWrap",
"defaultLocation": "beforeLast",
"defaultAdditionalIndent": 0,
"rules": [
{
"additionalIndent": 0,
"location": "beforeLast",
"type": "onePerLine",
"conditions": [
{
"cond": "lineLength >= n",
"value": 160
}
]
}
]
},
"opAddSubChain": {
"defaultWrap": "noWrap",
"defaultLocation": "beforeLast",
"defaultAdditionalIndent": 0,
"rules": [
{
"additionalIndent": 0,
"location": "beforeLast",
"type": "onePerLine",
"conditions": [
{
"cond": "lineLength >= n",
"value": 160
}
]
}
]
},
"implementsExtends": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
},
"mapWrap": {
"metadataCallParameter": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
},
"anonFunctionSignature": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
},
"anonType": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
},
"casePattern": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
},
"functionSignature": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
},
"multiVar": {
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
},
"typeParameter": {
"defaultWrap": "noWrap"
"defaultWrap": "noWrap",
"defaultLocation": "afterLast",
"defaultAdditionalIndent": 0
}
},
+129 -182
View File
@@ -32,13 +32,13 @@ class Project extends HXProject
* REMEMBER TO CHANGE THIS WHEN THE GAME UPDATES!
* You only have to change it here, the rest of the game will query this value.
*/
static final VERSION:String = "0.8.3";
static final VERSION:String = "0.8.7";
/**
* The build's number and version code.
* Used when publishing the game to mobile app stores. Should increment with each patch.
*/
static final BUILD_NUMBER:Int = 77;
static final BUILD_NUMBER:Int = 102;
/**
* The game's name. Used as the default window title.
@@ -105,15 +105,8 @@ class Project extends HXProject
//
/**
* The app's minimal Android SDK version.
* The app's lime Android java extensions.
*/
static final ANDROID_MINIMUM_SDK_VERSION:Int = 28;
/**
* The app's target Android SDK version.
*/
static final ANDROID_TARGET_SDK_VERSION:Int = 35;
static final ANDROID_EXTENSIONS:Array<String> = [
"funkin.extensions.CallbackUtil",
"funkin.extensions.FNFCExtension",
@@ -171,11 +164,7 @@ class Project extends HXProject
/**
* Asset path globs to exclude on platforms with `CENSOR_EXPLETIVES` disabled.
*/
static final EXCLUDE_ASSETS_UNCENSORED:Array<String> = [
"stressCutscene-censored.mp4",
"stressPicoCutscene-censored.mp4",
"darnellCutscene-censored.mp4"
];
static final EXCLUDE_ASSETS_UNCENSORED:Array<String> = ["stressCutscene-censored.mp4", "stressPicoCutscene-censored.mp4", "darnellCutscene-censored.mp4"];
//
// ASSET EMBEDDING
@@ -392,10 +381,16 @@ class Project extends HXProject
/**
* `-DFEATURE_MOBILE_WEBVIEW`
* If this feature flag is enabled, the user may sometimes be prompted to review the app on their respective store.
* If this feature flag is enabled, the game will be able to load WebViews, mainly needed for the Newgrounds impl.
*/
static final FEATURE_MOBILE_WEBVIEW:FeatureFlag = "FEATURE_MOBILE_WEBVIEW";
/**
* `-DFEATURE_MOBILE_AGESIGNALS`
* If this feature flag is enabled, the game will be able to use age singals.
*/
static final FEATURE_MOBILE_AGESIGNALS:FeatureFlag = "FEATURE_MOBILE_AGESIGNALS";
/**
* `-DFEATURE_NAUGHTYNESS`
* If this feature flag is enabled, naughtyness will be a toggleable option in the Options Menu.
@@ -539,19 +534,34 @@ class Project extends HXProject
{
super();
#if !target.unicode
if (isWindowsHost())
{
// Enable code page 65001 for unicode support
Sys.command("chcp 65001 > nul");
}
#end
envConfig = readEnvironmentFile("./.env");
flair();
displayTarget();
configureApp();
displayTarget();
configureOutputDir();
if (isRun() || isInstall())
{
// These commands dont really need much in order to run so to improve the speed, we return here.
return;
}
configureFeatureFlags();
configureCompileDefines();
configureIncludeMacros();
configureCustomMacros();
configureOutputDir();
configurePolymod();
configureHaxelibs();
configureASTCTextures();
@@ -582,7 +592,7 @@ class Project extends HXProject
buildHxCppTools();
}
if (!isDisplay())
if (!(isDisplay() || isCleanCommand()))
{
checkLibraries();
}
@@ -611,11 +621,6 @@ class Project extends HXProject
{
this.meta.title = isMobile() ? TITLE_MOBILE : TITLE;
// ios uses this character code instead of spaces...
// We don't have spaces in our title for mobile anymore
// But keeping incase anybody source-modding ever does add spaces
if (isIOS()) this.meta.title = ~/ /ig.replace(TITLE_MOBILE, "\u2002");
this.meta.version = VERSION;
this.meta.packageName = PACKAGE_NAME;
this.meta.company = COMPANY;
@@ -641,17 +646,6 @@ class Project extends HXProject
// Set the build number, required for publishing the game to mobile stores.
this.meta.buildNumber = Std.string(BUILD_NUMBER);
// These values are only used by the SWF target I think.
// this.app.path
// this.app.init
// this.app.swfVersion
// this.app.url
// These values are only used by... FIREFOX MARKETPLACE WHAT?
// this.meta.description = "";
// this.meta.companyId = COMPANY;
// this.meta.companyUrl = COMPANY;
// Configure the window.
// Automatically configure FPS.
this.window.fps = 60;
@@ -696,8 +690,28 @@ class Project extends HXProject
this.excludeArchitectures.push(Architecture.ARMV7);
}
config.set("android.minimum-sdk-version", ANDROID_MINIMUM_SDK_VERSION);
config.set("android.target-sdk-version", ANDROID_TARGET_SDK_VERSION);
if (isRelease())
{
if (envConfig != null)
{
keystore = new Keystore();
keystore.path = Std.string(envConfig.get('KEYSTORE_PATH'));
keystore.alias = Std.string(envConfig.get('KEYSTORE_ALIAS'));
keystore.password = Std.string(envConfig.get('KEYSTORE_PASSWORD'));
}
if (isBundle())
{
config.set("android.gradle-project-directory", "bin-bundle");
}
}
}
if (isIOS())
{
config.set("ios.non-exempt-encryption", "false");
config.set("ios.team-id", IOS_TEAM_ID);
config.set("ios.deployment", "16.0");
}
}
@@ -731,7 +745,6 @@ class Project extends HXProject
// case Platform.PS3:
// case Platform.PS4:
// case Platform.TIZEN:
// case Platform.TVOS:
// case Platform.VITA:
// case Platform.WEBOS:
// case Platform.WIIU:
@@ -743,42 +756,22 @@ class Project extends HXProject
switch (this.platformType)
{
case PlatformType.DESKTOP:
info('Platform Type: Desktop');
info('Target Platform Type: Desktop');
case PlatformType.MOBILE:
info('Platform Type: Mobile');
info('Target Platform Type: Mobile');
case PlatformType.WEB:
info('Platform Type: Web');
info('Target Platform Type: Web');
case PlatformType.CONSOLE:
info('Platform Type: Console');
info('Target Platform Type: Console');
default:
error('Unknown platform type (got ${platformType})');
}
// Print whether we are using HXCPP, HashLink, or something else.
// Print whether we are using HXCPP, JavaScript, or something else.
if (isWeb())
{
info('Target Language: JavaScript (HTML5)');
}
else if (isHashLink())
{
info('Target Language: HashLink');
}
else if (isNeko())
{
info('Target Language: Neko');
}
else if (isJava())
{
info('Target Language: Java');
}
else if (isNodeJS())
{
info('Target Language: JavaScript (NodeJS)');
}
else if (isCSharp())
{
info('Target Language: C#');
}
else if (isCPP())
{
info('Target Language: C++');
@@ -794,23 +787,13 @@ class Project extends HXProject
switch (arch)
{
case Architecture.X86:
info('Architecture: x86');
info('Target Architecture: x86');
case Architecture.X64:
info('Architecture: x64');
case Architecture.ARMV5:
info('Architecture: ARMv5');
case Architecture.ARMV6:
info('Architecture: ARMv6');
info('Target Architecture: x64');
case Architecture.ARMV7:
info('Architecture: ARMv7');
case Architecture.ARMV7S:
info('Architecture: ARMv7S');
info('Target Architecture: ARMv7');
case Architecture.ARM64:
info('Architecture: ARMx64');
case Architecture.MIPS:
info('Architecture: MIPS');
case Architecture.MIPSEL:
info('Architecture: MIPSEL');
info('Target Architecture: ARM64');
case null:
if (!isWeb())
{
@@ -818,7 +801,7 @@ class Project extends HXProject
}
else
{
info('Architecture: Web');
info('Target Architecture: Web');
}
default:
error('Unsupported architecture (got ${arch})');
@@ -869,10 +852,6 @@ class Project extends HXProject
// FEATURE FLAGS
//
// Should be true on debug builds or if GITHUB_BUILD is enabled.
FEATURE_DEBUG_FUNCTIONS.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this));
FEATURE_RESULTS_DEBUG.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this));
FEATURE_FUNKVIS.apply(this, true);
FEATURE_LOG_TRACE.apply(this, true);
FEATURE_DEBUG_FILE_LOGGING.apply(this, FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
@@ -882,8 +861,7 @@ class Project extends HXProject
FEATURE_POLYMOD_MODS.apply(this, true);
// Video playback should be enabled on desktop, web, and mobile.
// HXCPP has trouble with iOS simulator builds though...
FEATURE_VIDEO_PLAYBACK.apply(this, !(isIOSSimulator() || isHashLink()));
FEATURE_VIDEO_PLAYBACK.apply(this, true);
// Video subtitles only work via using hxvlc.
FEATURE_VIDEO_SUBTITLES.apply(this, FEATURE_VIDEO_PLAYBACK.isEnabled(this) && !isWeb());
@@ -918,13 +896,13 @@ class Project extends HXProject
// Should be true except on web builds (some asset stuff breaks it)
FEATURE_LAG_ADJUSTMENT.apply(this, !isWeb());
// Should be true except on web and mobile builds.
// Screenshots doesn't work there, and mobile has its own screenshots anyway.
FEATURE_SCREENSHOTS.apply(this, !(isWeb() || isMobile()));
// Should be true only on Desktop builds.
// Mobile has its own screenshot methods.
// Web has it disabled due to performance cost of `preserveDrawingBuffer`.
FEATURE_SCREENSHOTS.apply(this, isDesktop());
// Should be true except on MacOS and mobile builds.
// Dragging and dropping files onto the window doesn't work there.
FEATURE_FILE_DROP.apply(this, !(isMac() || isMobile()));
// Should be true except on mobile builds.
FEATURE_FILE_DROP.apply(this, !isMobile());
// Audio context issues only exist on web builds.
FEATURE_TOUCH_HERE_TO_PLAY.apply(this, isWeb());
@@ -934,10 +912,11 @@ class Project extends HXProject
FEATURE_TOUCH_CONTROLS.apply(this, isMobile());
// Should be true only on mobile release builds. Remember you can add the flag manually for testing.
FEATURE_MOBILE_ADVERTISEMENTS.apply(this, (isMobile() && isRelease() && !isIOSSimulator()) && envConfig != null);
FEATURE_MOBILE_IAP.apply(this, (isMobile() && isRelease() && !isIOSSimulator()) && envConfig != null);
FEATURE_MOBILE_IAR.apply(this, isMobile() && isRelease() && !isIOSSimulator());
FEATURE_MOBILE_ADVERTISEMENTS.apply(this, (isMobile() && isRelease()) && envConfig != null);
FEATURE_MOBILE_IAP.apply(this, (isMobile() && isRelease()) && envConfig != null);
FEATURE_MOBILE_IAR.apply(this, isMobile() && isRelease());
FEATURE_MOBILE_WEBVIEW.apply(this, isMobile() && FEATURE_NEWGROUNDS.isEnabled(this));
FEATURE_MOBILE_AGESIGNALS.apply(this, isMobile() && isRelease());
// The coveted ghost tapping feature.
// Essential on mobile but delayed on desktop.
@@ -968,16 +947,6 @@ class Project extends HXProject
var unicodeCheck:String = "✓ ";
var unicodeCross:String = "× ";
if (isWindowsHost())
{
#if (!target.unicode)
// lime build tools uses neko (unless compiling with `-eval`), and neko on windows doesn't support UTF8/unicode characters
// so we need to remove our cute emoji!
unicodeCheck = "o ";
unicodeCross = "x ";
#end
}
for (flagStr in this.haxedefs.keys())
{
if (!flagStr.startsWith(FeatureFlag.INVERSE_PREFIX))
@@ -1026,6 +995,9 @@ class Project extends HXProject
*/
function configureCompileDefines()
{
// Add Funkin's version as a compilation flag so Polymod scripts can use it.
setHaxedef("funkin", VERSION);
// Enable OpenFL's error handler. Required for the crash logger.
setHaxedef("openfl-enable-handle-error");
@@ -1039,8 +1011,6 @@ class Project extends HXProject
setHaxedef("HXCPP_STACK_TRACE");
setHaxedef("hscriptPos");
setHaxedef("safeMode");
if (FEATURE_DEBUG_FUNCTIONS.isDisabled(this))
{
setHaxedef("FLX_NO_DEBUG"); // If we aren't using the Flixel debugger, strip it out.
@@ -1133,6 +1103,13 @@ class Project extends HXProject
// Ensure all flixel-animate classes are available at runtime.
addHaxeMacro("include('animate')");
// Ensure all openfl classes are available at runtime.
addHaxeMacro("include('openfl')");
// Ensure all lime classes are available at runtime.
// Explicitly ignore tools and internal packages.
addHaxeMacro("include('lime', true, ['lime.tools.*', 'lime._internal.*'])");
// Ensure all Flixel classes are available at runtime.
// Explicitly ignore packages which require additional dependencies.
addHaxeMacro("include('flixel', true, [ 'flixel.addons.editors.spine.*', 'flixel.addons.nape.*', 'flixel.system.macros.*', 'flixel.addons.tile.FlxRayCastTilemap' ])");
@@ -1143,8 +1120,9 @@ class Project extends HXProject
*/
function configureCustomMacros()
{
// This macro allows addition of new functionality to existing Flixel. -->
// These macros allow additions of new functionality to existing Flixel. -->
addHaxeMacro("addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxBasic())', 'flixel.FlxBasic')");
addHaxeMacro("addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxSprite())', 'flixel.FlxSprite')");
}
function configureOutputDir()
@@ -1168,22 +1146,6 @@ class Project extends HXProject
{
javaPaths.push(Path.join([SOURCE_DIR, 'funkin/external/android/java']));
if (isRelease())
{
if (envConfig != null)
{
keystore = new Keystore();
keystore.path = Std.string(envConfig.get('KEYSTORE_PATH'));
keystore.alias = Std.string(envConfig.get('KEYSTORE_ALIAS'));
keystore.password = Std.string(envConfig.get('KEYSTORE_PASSWORD'));
}
if (isBundle())
{
config.set("android.gradle-project-directory", "bin-bundle");
}
}
// Custom android.application XML Children for the AndroidManifest
final modsFolderProvider:Xml = Xml.createElement('provider');
modsFolderProvider.set('android:authorities', '$PACKAGE_NAME.docprovider');
@@ -1228,21 +1190,12 @@ class Project extends HXProject
intentFilter.addChild(category);
}
final intentFilterDatas:Map<String, Array<String>> = [
"android:mimeType" => ["application/zip"],
// When this is added, it makes the game show up only when it's a FNFC file.
final intentFilterDatas:Map<String,
Array<String>> = ["android:mimeType" => ["application/zip"], // When this is added, it makes the game show up only when it's a FNFC file.
// But it also for some reason make it not show up at all in ZArchiver no matter what the file is...
// "android:host" => ["*"],
"android:scheme" => ["file", "content"],
// I think having all these makes it so the extension check would work even when the files has dots like "epic-song-v2.0.fnfc"
"android:pathPattern" => [
".*\\.fnfc",
".*\\..*\\.fnfc",
".*\\..*\\..*\\.fnfc",
".*\\..*\\..*\\..*\\.fnfc",
".*\\..*\\..*\\..*\\..*\\.fnfc"
]
];
"android:scheme" => ["file", "content"], // I think having all these makes it so the extension check would work even when the files has dots like "epic-song-v2.0.fnfc"
"android:pathPattern" => [".*\\.fnfc", ".*\\..*\\.fnfc", ".*\\..*\\..*\\.fnfc", ".*\\..*\\..*\\..*\\.fnfc", ".*\\..*\\..*\\..*\\..*\\.fnfc"]];
for (key => values in intentFilterDatas)
{
@@ -1279,10 +1232,6 @@ class Project extends HXProject
function configureIOS()
{
config.set("ios.non-exempt-encryption", "false");
config.set("ios.team-id", IOS_TEAM_ID);
config.set("ios.deployment", "16.0");
// launchStoryboard = new LaunchStoryboard();
// launchStoryboard.path = "./LaunchScreen.storyboard";
@@ -1351,15 +1300,13 @@ class Project extends HXProject
addHaxelib('thx.core'); // General utility library, "the lodash of Haxe"
addHaxelib('thx.semver'); // Version string handling
if (isDebug())
if (isDebug() && isCPP())
{
addHaxelib('hxcpp-debug-server'); // VSCode debug support
}
if (isDesktop() || isMobile() && !isHashLink() && FEATURE_VIDEO_PLAYBACK.isEnabled(this))
if ((isDesktop() || isMobile()) && FEATURE_VIDEO_PLAYBACK.isEnabled(this))
{
// hxvlc doesn't function on HashLink or non-desktop platforms
// It's also unnecessary if video playback is disabled
addHaxelib('hxvlc'); // Video playback
}
@@ -1418,12 +1365,20 @@ class Project extends HXProject
{
addHaxelib('extension-webviewcore'); // WebView Extension
}
if (FEATURE_MOBILE_AGESIGNALS.isEnabled(this))
{
addHaxelib('extension-agesignals'); // WebView Extension
}
}
function configureAssets()
{
// Delete the assets folder from the export folder before adding anything.
clearAssets();
if (!(isDisplay() || isCleanCommand()))
{
// Delete the assets folder from the export folder before adding anything.
clearAssets();
}
var exclude = EXCLUDE_ASSETS.concat(isWeb() ? EXCLUDE_ASSETS_WEB : EXCLUDE_ASSETS_NATIVE);
var shouldPreload = PRELOAD_ALL.isEnabled(this);
@@ -1535,7 +1490,7 @@ class Project extends HXProject
var exportPath:Null<String> = app.path ?? "";
// mac target uses `macos` for the export folder instead of `mac`
var platform:String = (!isMac() ? Std.string(this.target) : 'macos');
var platform:String = !isMac() ? Std.string(this.target) : 'macos';
var basePath:String = Path.join([exportPath, platform, "bin"]);
var assetsPath:String = "";
@@ -1657,14 +1612,10 @@ class Project extends HXProject
*/
function configureASTCTextures()
{
if (!(isDisplay() || isClean()))
if (!(isDisplay() && isCleanCommand()) && FEATURE_COMPRESSED_TEXTURES.isEnabled(this))
{
readASTCExclusion();
if (FEATURE_COMPRESSED_TEXTURES.isEnabled(this))
{
runASTCCompressor();
}
runASTCCompressor();
}
}
@@ -1770,31 +1721,6 @@ class Project extends HXProject
return this.target == Platform.IOS && this.targetFlags.exists("simulator");
}
public function isHashLink():Bool
{
return this.targetFlags.exists("hl");
}
public function isNeko():Bool
{
return this.targetFlags.exists("neko");
}
public function isJava():Bool
{
return this.targetFlags.exists("java");
}
public function isNodeJS():Bool
{
return this.targetFlags.exists("nodejs");
}
public function isCSharp():Bool
{
return this.targetFlags.exists("cs");
}
public function isCPP():Bool
{
return this.defines.exists("cpp");
@@ -1805,11 +1731,26 @@ class Project extends HXProject
return this.command == "display";
}
public function isClean():Bool
public function isCleanCommand():Bool
{
return this.command == "clean";
}
public function isCleanFlag():Bool
{
return this.targetFlags.exists("clean");
}
public function isRun():Bool
{
return this.command == "run";
}
public function isInstall():Bool
{
return this.command == "install";
}
public function isBuild():Bool
{
return this.command == "test" || this.command == "build";
@@ -2171,8 +2112,8 @@ class Project extends HXProject
if (haxe.io.Path.isAbsolute(devPath))
{
Sys.println("- " + libraryName.replace(",", ".") + " (Development Build)".blue().bold());
Sys.println((" Path: " + haxe.io.Path.removeTrailingSlashes(devPath)).blue());
Sys.println("- " + libraryName.replace(",", ".") + " (Development Build)".bright_cyan());
Sys.println((" Path: " + haxe.io.Path.removeTrailingSlashes(devPath)).bright_blue());
}
else
{
@@ -2338,7 +2279,7 @@ class Project extends HXProject
*/
public function info(message:String):Void
{
if (!(isDisplay() || isClean()))
if (!(isDisplay() || isCleanCommand() || isRun() || isInstall()))
{
Sys.println(' INFO '.bold().bg_blue() + " " + message);
}
@@ -2349,7 +2290,7 @@ class Project extends HXProject
*/
public function warn(message:String):Void
{
if (!(isDisplay() || isClean()))
if (!(isDisplay() || isCleanCommand() || isRun() || isInstall()))
{
Sys.println(' WARNING '.bold().bg_yellow() + " " + message);
}
@@ -2495,8 +2436,14 @@ class Project extends HXProject
info('Compressing ASTC textures...');
var args:Array<String> = ['run', 'astc-compressor', 'compress-from-json'];
args = args.concat(['-json', './astc-compression-data.json']);
if (isCleanFlag())
{
args = args.concat(['-clean']);
}
Sys.command('haxelib', args);
info('Done compressing ASTC textures.');
+9 -10
View File
@@ -31,16 +31,15 @@ class Postbuild
else
{
var bytes:haxe.io.Bytes = haxe.io.Bytes.ofData(sys.io.File.getBytes(path).getData());
var entry:haxe.zip.Entry =
{
fileName: StringTools.replace(path, inDir, ""),
fileSize: bytes.length,
fileTime: Date.now(),
compressed: false,
dataSize: sys.FileSystem.stat(path).size,
data: bytes,
crc32: haxe.crypto.Crc32.make(bytes)
};
var entry:haxe.zip.Entry = {
fileName: StringTools.replace(path, inDir, ""),
fileSize: bytes.length,
fileTime: Date.now(),
compressed: false,
dataSize: sys.FileSystem.stat(path).size,
data: bytes,
crc32: haxe.crypto.Crc32.make(bytes)
};
entries.push(entry);
}
}
+1
View File
@@ -23,6 +23,7 @@ class SongConverter
// TODO
// Update engine shit, to accomodate single file
static function main()
{
// trace(Compiler.get);
+28 -19
View File
@@ -11,6 +11,8 @@ import funkin.util.logging.CrashHandler;
import funkin.ui.debug.FunkinDebugDisplay;
import funkin.ui.debug.FunkinDebugDisplay.DebugDisplayMode;
import funkin.save.Save;
import funkin.FunkinMemory;
import funkin.audio.FunkinSound;
#if hxvlc
import hxvlc.util.Handle;
#end
@@ -87,11 +89,28 @@ class Main extends Sprite
removeEventListener(Event.ADDED_TO_STAGE, init);
}
#if (!html5 && !mobile)
// Force-kill the game to prevent background processing.
openfl.Lib.application.onExit.add((_) ->
{
// Dispose of cached audio and textures.
funkin.audio.FunkinSound.stopAllAudio(true, true);
funkin.FunkinMemory.purgeCache(true);
// Dispose of any assets still in the OpenFL cache, just incase.
openfl.Assets.cache.clear();
trace(' EXITING '.bold().bg_red() + ' Resources are disposed, Game is closing now.');
Sys.exit(0);
}, 99);
#end
// Manually crash the game when using a software renderer in order to give a nicer error message.
var context = stage.window.context.type;
if (context != WEBGL && context != OPENGL && context != OPENGLES)
{
var tech:String = #if web "WebGL" #elseif desktop "OpenGL" #else "OpenGL ES" #end;
var tech:String = #if web 'WebGL' #elseif desktop 'OpenGL' #else 'OpenGL ES' #end;
var requiredVersion:String = #if web '$tech 1.0 or newer' #elseif desktop '$tech 3.0 or newer' #else '$tech 2.0 or newer' #end;
var desc:String = 'Failed to initialize the $tech rendering context!\n\n';
#if web
@@ -149,20 +168,15 @@ class Main extends Sprite
});
#end
// Don't call anything from the preferences until the save is loaded!
#if web
// set this variable (which is a function) from the lime version at lime/_internal/backend/html5/HTML5Application.hx
// The framerate cap will more thoroughly initialize via Preferences in InitState.hx
funkin.Preferences.lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
#end
WindowUtil.setVSyncMode(funkin.Preferences.vsyncMode);
// Force a `FunkinCamera` to be the default camera.
// This allows the blend mode shader to work everywhere.
untyped FlxG.cameras = new funkin.graphics.FunkinCameraFrontEnd();
var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, Preferences.framerate, Preferences.framerate, skipSplash,
var framerate:Int = Preferences.unlockedFramerate ? 0 : Preferences.framerate;
var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, framerate, framerate, skipSplash,
(FlxG.stage.window.fullscreen || Preferences.autoFullscreen));
// FlxG.game._customSoundTray wants just the class, it calls new from
@@ -174,7 +188,7 @@ class Main extends Sprite
addChild(game);
#if FEATURE_DEBUG_FUNCTIONS
game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil());
#if !FLX_NO_DEBUG game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil()); #end
funkin.util.macro.ConsoleMacro.init();
#end
@@ -236,14 +250,7 @@ class Main extends Sprite
function repositionCounters(lerp:Bool):Void
{
// Calling this so it gets scaled based on the resolution of the game and device's resolution.
var scale:Float = Math.min(FlxG.stage.stageWidth / FlxG.width, FlxG.stage.stageHeight / FlxG.height);
#if android
scale = Math.max(scale, 1);
#else
scale = Math.min(scale, 1);
#end
final thypos:Float = Math.max(FullScreenScaleMode.notchSize.x, 10);
var scale:Float = Math.max(Math.min(FlxG.stage.stageWidth / FlxG.width, FlxG.stage.stageHeight / FlxG.height), 1);
if (debugDisplay != null)
{
@@ -251,13 +258,15 @@ class Main extends Sprite
if (FlxG.game != null)
{
final thypos:Float = Math.max(FullScreenScaleMode.notchSize.x, 10);
if (lerp)
{
debugDisplay.x = flixel.math.FlxMath.lerp(debugDisplay.x, FlxG.game.x + thypos, FlxG.elapsed * 3);
}
else
{
debugDisplay.x = FlxG.game.x + FullScreenScaleMode.notchSize.x + 10;
debugDisplay.x = FlxG.game.x + thypos;
}
debugDisplay.y = FlxG.game.y + (3 * scale);
+5 -5
View File
@@ -36,7 +36,7 @@ class Postbuild
static function format(time:Float, decimals:Int = 1):String
{
var units = [{name: "day", secs: 86400}, {name: "hour", secs: 3600}, {name: "minute", secs: 60}, {name: "second", secs: 1}];
var units = [{name: 'day', secs: 86400}, {name: 'hour', secs: 3600}, {name: 'minute', secs: 60}, {name: 'second', secs: 1}];
var parts:Array<String> = [];
var remaining:Float = time;
@@ -44,13 +44,13 @@ class Postbuild
for (u in units)
{
var value:Float = (u.name == "second") ? Math.round(remaining * factor) / factor : Math.floor(remaining / u.secs);
var value:Float = (u.name == 'second') ? Math.round(remaining * factor) / factor : Math.floor(remaining / u.secs);
if (u.name != "second") remaining %= u.secs;
if (u.name != 'second') remaining %= u.secs;
if (value > 0 || (u.name == "second" && parts.length == 0)) parts.push('${value} ${u.name}${value == 1 ? "" : "s"}');
if (value > 0 || (u.name == 'second' && parts.length == 0)) parts.push('${value} ${u.name}${value == 1 ? "" : "s"}');
}
return parts.join(" ");
return parts.join(' ');
}
}
+4 -2
View File
@@ -2,6 +2,8 @@ package source; // Yeah, I know...
import sys.io.File;
using tools.AnsiUtil;
/**
* A script which executes before the game is built.
*/
@@ -12,13 +14,13 @@ class Prebuild
static function main():Void
{
var start:Float = Sys.time();
// Sys.println('[INFO] Performing pre-build tasks...');
// Sys.println(' INFO '.bold().bg_blue() + " Performing pre-build tasks...");
saveBuildTime();
var end:Float = Sys.time();
var duration:Float = end - start;
// Sys.println('[INFO] Finished pre-build tasks in $duration seconds.');
// Sys.println(' INFO '.bold().bg_blue() + ' Finished pre-build tasks in $duration seconds.');
}
static function saveBuildTime():Void
+28 -28
View File
@@ -1,4 +1,4 @@
/*
/**
* Pulled from Tracey profiler PR
* @see https://github.com/HaxeFoundation/haxe/pull/11772
*/
@@ -6,7 +6,7 @@
package cpp.vm.tracy;
#if (!HXCPP_TRACY)
#error "This class cannot be used without -D HXCPP_TRACY"
#error 'This class cannot be used without -D HXCPP_TRACY'
#end
enum abstract PlotFormatType(cpp.UInt8) from cpp.UInt8 to cpp.UInt8
{
@@ -19,68 +19,68 @@ enum abstract PlotFormatType(cpp.UInt8) from cpp.UInt8 to cpp.UInt8
extern class Native_TracyProfiler
{
/**
Mark a frame. Call this at the end of each frame loop.
**/
* Mark a frame. Call this at the end of each frame loop.
*/
@:native('::__hxcpp_tracy_framemark')
public static function frameMark():Void;
/**
Mark a named frame. Allows creating multiple frame sets for different timing categories.
Each unique name creates a separate frame set in the Tracy timeline.
**/
* Mark a named frame. Allows creating multiple frame sets for different timing categories.
* Each unique name creates a separate frame set in the Tracy timeline.
*/
@:native('::__hxcpp_tracy_framemark_named')
public static function frameMarkNamed(_name:String):Void;
/**
Mark the start of a discontinuous frame. Use for periodic work with gaps.
Must be paired with frameMarkEnd() using the same name.
**/
* Mark the start of a discontinuous frame. Use for periodic work with gaps.
* Must be paired with frameMarkEnd() using the same name.
*/
@:native('::__hxcpp_tracy_framemark_start')
public static function frameMarkStart(_name:String):Void;
/**
Mark the end of a discontinuous frame. Use for periodic work with gaps.
Must be paired with frameMarkStart() using the same name.
**/
* Mark the end of a discontinuous frame. Use for periodic work with gaps.
* Must be paired with frameMarkStart() using the same name.
*/
@:native('::__hxcpp_tracy_framemark_end')
public static function frameMarkEnd(_name:String):Void;
/**
Print a message into Tracy's log.
**/
* Print a message into Tracy's log.
*/
@:native('::__hxcpp_tracy_message')
public static function message(_msg:String, ?_color:Int = 0x000000):Void;
/**
Tracy can collect additional information about the profiled application,
which will be available in the trace description.
This can include data such as the source repository revision,
the application’s environment (dev/prod), etc.
**/
* Tracy can collect additional information about the profiled application,
* which will be available in the trace description.
* This can include data such as the source repository revision,
* the application’s environment (dev/prod), etc.
*/
@:native('::__hxcpp_tracy_message_app_info')
public static function messageAppInfo(_info:String):Void;
/**
Plot a named value to tracy. This will generate a graph in the profiler for you.
**/
* Plot a named value to tracy. This will generate a graph in the profiler for you.
*/
@:native('::__hxcpp_tracy_plot')
public static function plot(_name:String, _val:cpp.Float32):Void;
/**
Configure how values are plotted and displayed.
**/
* Configure how values are plotted and displayed.
*/
@:native('::__hxcpp_tracy_plot_config')
public static function plotConfig(_name:String, _format:PlotFormatType, ?_step:Bool = false, ?_fill:Bool = false, ?_color:Int = 0x000000):Void;
/**
Set a name for the current thread this function is called in. Supply an optional groupHint so threads become grouped in Tracy's UI.
**/
* Set a name for the current thread this function is called in. Supply an optional groupHint so threads become grouped in Tracy's UI.
*/
@:native('::__hxcpp_tracy_set_thread_name_and_group')
public static function setThreadName(_name:String, ?_groupHint:Int = 1):Void;
/**
Create a custom named scoped zone in your code.
**/
* Create a custom named scoped zone in your code.
*/
@:native('HXCPP_TRACY_ZONE')
public static function zoneScoped(_name:String):Void;
}
+10 -6
View File
@@ -362,7 +362,7 @@ class Conductor
static function get_instance():Conductor
{
if (Conductor._instance == null) set_instance(new Conductor());
if (Conductor._instance == null) throw "Could not initialize singleton Conductor!";
if (Conductor._instance == null) throw 'Could not initialize singleton Conductor!';
return Conductor._instance;
}
@@ -849,7 +849,7 @@ class Conductor
* @param type The type of length to return. Either "step", "beat", or "measure" works, along with their first character.
* @return The length of a step/beat/measure in milliseconds.
*/
public function getTypeLengthAtMs(ms:Float, type:String = "beat"):Float
public function getTypeLengthAtMs(ms:Float, type:String = 'beat'):Float
{
if (timeChanges.length == 0) return 0;
var wantedTimeChange:SongTimeChange = timeChanges[0];
@@ -868,10 +868,14 @@ class Conductor
var wantedBeatLengthMs:Float = ((Constants.SECS_PER_MIN / wantedTimeChange.bpm) * Constants.MS_PER_SEC) * (4 / wantedTimeChange.timeSignatureDen);
return switch (type.toLowerCase())
{
case "measure", "m": wantedBeatLengthMs * wantedTimeChange.timeSignatureNum;
case "beat", "b": wantedBeatLengthMs;
case "step", "s": wantedBeatLengthMs / Constants.STEPS_PER_BEAT;
default: wantedBeatLengthMs;
case 'measure', 'm':
wantedBeatLengthMs * wantedTimeChange.timeSignatureNum;
case 'beat', 'b':
wantedBeatLengthMs;
case 'step', 's':
wantedBeatLengthMs / Constants.STEPS_PER_BEAT;
default:
wantedBeatLengthMs;
}
}
+76 -66
View File
@@ -20,12 +20,10 @@ class FunkinMemory
static var permanentCachedTextures:Map<String, FlxGraphic> = [];
static var currentCachedTextures:Map<String, FlxGraphic> = [];
static var previousCachedTextures:Map<String, FlxGraphic> = [];
static var permanentCachedSounds:Map<String, Sound> = [];
static var currentCachedSounds:Map<String, Sound> = [];
static var previousCachedSounds:Map<String, Sound> = [];
static var purgeFilter:Array<String> = ["/week", "/characters", "/charSelect", "/results"];
static var purgeFilter:Array<String> = ['/week', '/characters', '/charSelect', '/results'];
/**
* Caches textures that are always required.
@@ -36,42 +34,42 @@ class FunkinMemory
for (file in allImages)
{
if (!(file.endsWith(".png") #if FEATURE_COMPRESSED_TEXTURES || file.endsWith(".astc") #end)
|| file.contains("chart-editor")
|| !file.contains("ui/"))
if (!(file.endsWith('.png') #if FEATURE_COMPRESSED_TEXTURES || file.endsWith('.astc') #end)
|| file.contains('chart-editor')
|| !file.contains('ui/'))
{
continue;
}
file = file.replace(" ", ""); // Handle stray spaces.
file = file.replace(' ', ''); // Handle stray spaces.
if (file.contains("shared") || Assets.exists('shared:$file', AssetType.IMAGE))
if (file.contains('shared') || Assets.exists('shared:$file', AssetType.IMAGE))
{
file = 'shared:$file';
}
permanentCacheTexture(file);
}
permanentCacheTexture(Paths.image("healthBar"));
permanentCacheTexture(Paths.image("menuDesat"));
permanentCacheTexture(Paths.image("notes", "shared"));
permanentCacheTexture(Paths.image("noteSplashes", "shared"));
permanentCacheTexture(Paths.image("noteStrumline", "shared"));
permanentCacheTexture(Paths.image("NOTE_hold_assets"));
permanentCacheTexture(Paths.image('healthBar'));
permanentCacheTexture(Paths.image('menuDesat'));
permanentCacheTexture(Paths.image('notes', 'shared'));
permanentCacheTexture(Paths.image('noteSplashes', 'shared'));
permanentCacheTexture(Paths.image('noteStrumline', 'shared'));
permanentCacheTexture(Paths.image('NOTE_hold_assets'));
// dude
permanentCacheTexture(Paths.image("fonts/bold", null));
permanentCacheTexture(Paths.image("fonts/default", null));
permanentCacheTexture(Paths.image("fonts/freeplay-clear", null));
permanentCacheTexture(Paths.image('fonts/bold', null));
permanentCacheTexture(Paths.image('fonts/default', null));
permanentCacheTexture(Paths.image('fonts/freeplay-clear', null));
var allSounds:Array<String> = Assets.list(AssetType.SOUND);
for (file in allSounds)
{
if (!file.endsWith(".ogg") || !file.contains("countdown/")) continue;
if (!file.endsWith('.ogg') || !file.contains('countdown/')) continue;
file = file.replace(" ", "");
file = file.replace(' ', '');
if (file.contains("shared") || Assets.exists('shared:$file', AssetType.SOUND))
if (file.contains('shared') || Assets.exists('shared:$file', AssetType.SOUND))
{
file = 'shared:$file';
}
@@ -79,19 +77,19 @@ class FunkinMemory
permanentCacheSound(file);
}
permanentCacheSound(Paths.sound("cancelMenu"));
permanentCacheSound(Paths.sound("confirmMenu"));
permanentCacheSound(Paths.sound("screenshot"));
permanentCacheSound(Paths.sound("scrollMenu"));
permanentCacheSound(Paths.sound("soundtray/Voldown"));
permanentCacheSound(Paths.sound("soundtray/VolMAX"));
permanentCacheSound(Paths.sound("soundtray/Volup"));
permanentCacheSound(Paths.music("freakyMenu/freakyMenu"));
permanentCacheSound(Paths.music("offsetsLoop/offsetsLoop"));
permanentCacheSound(Paths.music("offsetsLoop/drumsLoop"));
permanentCacheSound(Paths.sound("missnote1", "shared"));
permanentCacheSound(Paths.sound("missnote2", "shared"));
permanentCacheSound(Paths.sound("missnote3", "shared"));
permanentCacheSound(Paths.sound('cancelMenu'));
permanentCacheSound(Paths.sound('confirmMenu'));
permanentCacheSound(Paths.sound('screenshot'));
permanentCacheSound(Paths.sound('scrollMenu'));
permanentCacheSound(Paths.sound('soundtray/Voldown'));
permanentCacheSound(Paths.sound('soundtray/VolMAX'));
permanentCacheSound(Paths.sound('soundtray/Volup'));
permanentCacheSound(Paths.music('freakyMenu/freakyMenu'));
permanentCacheSound(Paths.music('offsetsLoop/offsetsLoop'));
permanentCacheSound(Paths.music('offsetsLoop/drumsLoop'));
permanentCacheSound(Paths.sound('missnote1', 'shared'));
permanentCacheSound(Paths.sound('missnote2', 'shared'));
permanentCacheSound(Paths.sound('missnote3', 'shared'));
}
/**
@@ -100,6 +98,8 @@ class FunkinMemory
*/
public static inline function purgeCache(callGarbageCollector:Bool = false):Void
{
trace(' CLEARING CACHE '.bg_bright_lilac().bold() + ' Disposing all cached textures, assets and sounds...');
preparePurgeTextureCache();
purgeTextureCache();
preparePurgeSoundCache();
@@ -175,7 +175,7 @@ class FunkinMemory
/**
* Prepares the cache for purging unused textures.
*/
public inline static function preparePurgeTextureCache():Void
public static inline function preparePurgeTextureCache():Void
{
previousCachedTextures = currentCachedTextures.copy();
@@ -203,7 +203,7 @@ class FunkinMemory
continue;
}
if (graphicKey.contains("fonts")) continue;
if (graphicKey.contains('fonts')) continue;
var graphic:Null<FlxGraphic> = previousCachedTextures.get(graphicKey);
if (graphic != null)
@@ -227,7 +227,7 @@ class FunkinMemory
{
var obj:Null<FlxGraphic> = FlxG.bitmap.get(key);
if (obj == null || (obj.persist && permanentCachedTextures.exists(key)) || key.contains("fonts"))
if (obj == null || (obj.persist && permanentCachedTextures.exists(key)) || key.contains('fonts'))
{
continue;
}
@@ -251,7 +251,7 @@ class FunkinMemory
* Forces the GPU to load and upload a FlxGraphic.
* @param graphic The graphic to force render.
*/
private static function forceRender(graphic:FlxGraphic):Void
static function forceRender(graphic:FlxGraphic):Void
{
if (graphic == null) return;
@@ -286,30 +286,30 @@ class FunkinMemory
public static function cacheNoteStyle(style:NoteStyle):Void
{
// TODO: Texture paths should fall back to the default values.
cacheTexture(Paths.image(style.getNoteAssetPath() ?? "note"));
cacheTexture(style.getHoldNoteAssetPath() ?? "noteHold");
cacheTexture(Paths.image(style.getStrumlineAssetPath() ?? "strumline"));
cacheTexture(Paths.image(style.getSplashAssetPath() ?? "noteSplash"));
cacheTexture(Paths.image(style.getNoteAssetPath() ?? 'note'));
cacheTexture(style.getHoldNoteAssetPath() ?? 'noteHold');
cacheTexture(Paths.image(style.getStrumlineAssetPath() ?? 'strumline'));
cacheTexture(Paths.image(style.getSplashAssetPath() ?? 'noteSplash'));
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(LEFT) ?? "LEFT"));
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(RIGHT) ?? "RIGHT"));
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(UP) ?? "UP"));
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(DOWN) ?? "DOWN"));
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(LEFT) ?? 'LEFT'));
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(RIGHT) ?? 'RIGHT'));
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(UP) ?? 'UP'));
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(DOWN) ?? 'DOWN'));
// cacheTexture(Paths.image(style.buildCountdownSpritePath(THREE) ?? "THREE"));
cacheTexture(Paths.image(style.buildCountdownSpritePath(TWO) ?? "TWO"));
cacheTexture(Paths.image(style.buildCountdownSpritePath(ONE) ?? "ONE"));
cacheTexture(Paths.image(style.buildCountdownSpritePath(GO) ?? "GO"));
cacheTexture(Paths.image(style.buildCountdownSpritePath(TWO) ?? 'TWO'));
cacheTexture(Paths.image(style.buildCountdownSpritePath(ONE) ?? 'ONE'));
cacheTexture(Paths.image(style.buildCountdownSpritePath(GO) ?? 'GO'));
cacheSound(style.getCountdownSoundPath(THREE) ?? "THREE");
cacheSound(style.getCountdownSoundPath(TWO) ?? "TWO");
cacheSound(style.getCountdownSoundPath(ONE) ?? "ONE");
cacheSound(style.getCountdownSoundPath(GO) ?? "GO");
cacheSound(style.getCountdownSoundPath(THREE) ?? 'THREE');
cacheSound(style.getCountdownSoundPath(TWO) ?? 'TWO');
cacheSound(style.getCountdownSoundPath(ONE) ?? 'ONE');
cacheSound(style.getCountdownSoundPath(GO) ?? 'GO');
cacheTexture(Paths.image(style.buildJudgementSpritePath("sick") ?? 'sick'));
cacheTexture(Paths.image(style.buildJudgementSpritePath("good") ?? 'good'));
cacheTexture(Paths.image(style.buildJudgementSpritePath("bad") ?? 'bad'));
cacheTexture(Paths.image(style.buildJudgementSpritePath("shit") ?? 'shit'));
cacheTexture(Paths.image(style.buildJudgementSpritePath('sick') ?? 'sick'));
cacheTexture(Paths.image(style.buildJudgementSpritePath('good') ?? 'good'));
cacheTexture(Paths.image(style.buildJudgementSpritePath('bad') ?? 'bad'));
cacheTexture(Paths.image(style.buildJudgementSpritePath('shit') ?? 'shit'));
cacheTexture(Paths.image(style.buildComboNumSpritePath(0) ?? '0'));
cacheTexture(Paths.image(style.buildComboNumSpritePath(1) ?? '1'));
@@ -343,9 +343,14 @@ class FunkinMemory
}
var sound:Null<Sound> = Assets.getSound(key, true);
if (sound == null) return;
if (sound == null)
{
return;
}
else
{
currentCachedSounds.set(key, sound);
}
}
/**
@@ -357,9 +362,14 @@ class FunkinMemory
if (permanentCachedSounds.exists(key)) return;
var sound:Null<Sound> = Assets.getSound(key, true);
if (sound == null) return;
if (sound == null)
{
return;
}
else
{
permanentCachedSounds.set(key, sound);
}
if (sound != null) currentCachedSounds.set(key, sound);
}
@@ -402,10 +412,10 @@ class FunkinMemory
previousCachedSounds.remove(key);
}
}
Assets.cache.clear("songs");
Assets.cache.clear("music");
Assets.cache.clear('songs');
Assets.cache.clear('music');
// Felt lazy.
var key = Paths.music("freakyMenu/freakyMenu");
var key = Paths.music('freakyMenu/freakyMenu');
var sound:Null<Sound> = Assets.getSound(key, true);
if (sound != null)
{
@@ -426,8 +436,8 @@ class FunkinMemory
@:privateAccess
for (key in FlxG.bitmap._cache.keys())
{
if (!key.contains("freeplay")) continue;
if (permanentCachedTextures.exists(key) || key.contains("fonts")) continue;
if (!key.contains('freeplay')) continue;
if (permanentCachedTextures.exists(key) || key.contains('fonts')) continue;
keysToRemove.push(key);
}
@@ -460,8 +470,8 @@ class FunkinMemory
@:privateAccess
for (key in FlxG.bitmap._cache.keys())
{
if (!key.contains("stickers")) continue;
if (permanentCachedTextures.exists(key) || key.contains("fonts")) continue;
if (!key.contains('stickers')) continue;
if (permanentCachedTextures.exists(key) || key.contains('fonts')) continue;
keysToRemove.push(key);
}
@@ -485,7 +495,7 @@ class FunkinMemory
* Sends a trace with fancy ANSI colors.
* @param message The message to log.
*/
private static function log(message:String):Void
static function log(message:String):Void
{
trace(' MEMORY '.bg_bright_lilac().bold() + ' ${message}');
}
-2
View File
@@ -82,9 +82,7 @@ typedef RawTallies =
var good:Int;
var sick:Int;
var maxCombo:Int;
var score:Int;
var isNewHighscore:Bool;
/**
+45 -22
View File
@@ -10,7 +10,6 @@ import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import flixel.system.debug.log.LogStyle;
import flixel.util.FlxColor;
import funkin.graphics.FunkinSprite;
import funkin.data.dialogue.ConversationRegistry;
import funkin.data.dialogue.DialogueBoxRegistry;
import funkin.data.dialogue.SpeakerRegistry;
@@ -67,7 +66,7 @@ class InitState extends FlxState
/**
* Perform a bunch of game setup, then immediately transition to the title screen.
*/
public override function create():Void
override public function create():Void
{
// Setup a bunch of important Flixel stuff.
setupShit();
@@ -125,6 +124,11 @@ class InitState extends FlxState
funkin.mobile.util.WebViewUtil.init();
#end
#if FEATURE_MOBILE_AGESIGNALS
// Setup AgeSignals
funkin.mobile.util.AgeSignalsUtil.init();
#end
#if android
// Setup Callback util.
funkin.external.android.CallbackUtil.init();
@@ -137,7 +141,7 @@ class InitState extends FlxState
#if mobile
// Setup Mobile FNFC launcher.
funkin.mobile.util.FNFCUtil.init();
funkin.mobile.util.FNFCProvider.init();
#end
SongEventHelper.generateEaseGraphsBitmaps();
@@ -221,7 +225,10 @@ class InitState extends FlxState
// DISCORD API SETUP
//
#if FEATURE_DISCORD_RPC
DiscordClient.instance.init();
if (Preferences.enabledDiscordRPC)
{
DiscordClient.instance.init();
}
lime.app.Application.current.onExit.add(function(exitCode)
{
@@ -237,7 +244,9 @@ class InitState extends FlxState
// ANDROID SETUP
//
#if android
FlxG.android.preventDefaultKeys = [flixel.input.android.FlxAndroidKey.BACK];
FlxG.android.preventDefaultKeys = [
flixel.input.android.FlxAndroidKey.BACK
];
#end
//
@@ -309,22 +318,38 @@ class InitState extends FlxState
}
#if FEATURE_LOST_FOCUS_VOLUME
@:noCompletion var _lastFocusVolume:Null<Float>;
@:noCompletion
var _lastFocusVolume:Null<Float>;
function onLostFocus()
function onLostFocus():Void
{
if (FlxG.sound.muted || FlxG.sound.volume == 0 || FlxG.autoPause) return;
_lastFocusVolume = FlxG.sound.volume;
FlxG.sound.volume *= Constants.LOST_FOCUS_VOLUME_MULTIPLIER;
}
function onGainFocus()
{
if (FlxG.sound.muted || FlxG.autoPause) return;
if (_lastFocusVolume != null) FlxG.sound.volume = _lastFocusVolume;
}
#end
function onGainFocus():Void
{
#if !mobile
if (Preferences.unlockedFramerate)
{
FlxG.updateFramerate = 0;
FlxG.drawFramerate = 0;
}
else
{
FlxG.updateFramerate = Preferences.framerate;
FlxG.drawFramerate = Preferences.framerate;
}
#end
#if FEATURE_LOST_FOCUS_VOLUME
if (FlxG.sound.muted || FlxG.sound.volume == 0 || FlxG.autoPause) return;
if (_lastFocusVolume != null) FlxG.sound.volume = _lastFocusVolume;
#end
}
/**
* Start the game.
*
@@ -368,10 +393,10 @@ class InitState extends FlxState
// -DRESULTS
FlxG.switchState(() -> new funkin.play.ResultState({
storyMode: true,
title: "Cum Song Erect by Kawai Sprite",
songId: "cum",
characterId: "pico",
difficultyId: "hard",
title: 'Cum Song Erect by Kawai Sprite',
songId: 'cum',
characterId: 'pico',
difficultyId: 'hard',
isNewHighscore: true,
scoreData: {
score: 1_234_567,
@@ -411,7 +436,6 @@ class InitState extends FlxState
function startGameNormally():Void
{
var params:CLIParams = CLIUtil.processArgs();
trace('Command line args: ${params}');
if (params.chart.shouldLoadChart)
{
@@ -443,9 +467,8 @@ class InitState extends FlxState
}
else
{
// FlxG.sound.cache(Paths.music('freakyMenu/freakyMenu'));
#if mobile
funkin.mobile.util.FNFCUtil.onFNFCOpen.add(function(fnfcFile:String)
funkin.mobile.util.FNFCProvider.onFNFCOpen.add(function(fnfcFile:String)
{
flixel.tweens.FlxTween.globalManager.clear();
flixel.util.FlxTimer.globalManager.clear();
@@ -459,7 +482,7 @@ class InitState extends FlxState
FlxG.switchState(() -> new ChartPlaytestMenu(fnfcFile));
});
final fnfcFile = funkin.mobile.util.FNFCUtil.queryFNFC();
final fnfcFile = funkin.mobile.util.FNFCProvider.queryFNFC();
if (fnfcFile != null)
{
trace('launching FNFC from $fnfcFile');
@@ -574,7 +597,7 @@ class InitState extends FlxState
//
// FLIXEL DEBUG SETUP
//
#if FEATURE_DEBUG_FUNCTIONS
#if (FEATURE_DEBUG_FUNCTIONS && !FLX_NO_DEBUG)
trace('Initializing Flixel debugger...');
#if !debug
+8 -8
View File
@@ -107,7 +107,7 @@ class Paths implements ConsoleClass
return getPath('data/$key.json', TEXT, library);
}
public static function srt(key:String, ?library:String, ?directory:String = "data/"):String
public static function srt(key:String, ?library:String, ?directory:String = 'data/'):String
{
return getPath('$directory$key.srt', TEXT, library);
}
@@ -181,10 +181,10 @@ class Paths implements ConsoleClass
public static function getAnimateAtlas(key:String, ?library:String, settings:AtlasSpriteSettings):FlxAnimateFrames
{
var assetLibrary:String = library ?? "";
var graphicKey:String = "";
var assetLibrary:String = library ?? '';
var graphicKey:String = '';
if (assetLibrary != "")
if (assetLibrary != '')
{
graphicKey = Paths.animateAtlas(key, assetLibrary);
}
@@ -229,8 +229,8 @@ class Paths implements ConsoleClass
enum abstract PathsFunction(String)
{
var MUSIC;
var INST;
var VOICES;
var SOUND;
public var MUSIC;
public var INST;
public var VOICES;
public var SOUND;
}
+7 -5
View File
@@ -21,7 +21,6 @@ class PlayerSettings
public static var player1(default, null):PlayerSettings;
@:nullSafety(Off)
public static var player2(default, null):PlayerSettings;
public static var onAvatarAdd(default, null) = new FlxTypedSignal<PlayerSettings->Void>();
public static var onAvatarRemove(default, null) = new FlxTypedSignal<PlayerSettings->Void>();
@@ -45,9 +44,12 @@ class PlayerSettings
{
return switch (id)
{
case 1: player1;
case 2: player2;
default: null;
case 1:
player1;
case 2:
player2;
default:
null;
};
}
@@ -98,7 +100,7 @@ class PlayerSettings
*/
function new(id:Int)
{
trace('loading player settings for id: $id');
trace('Loading player settings for id: $id');
this.id = id;
this.controls = new Controls('player$id', None);
+100 -46
View File
@@ -8,6 +8,9 @@ import funkin.save.Save;
import funkin.util.WindowUtil;
import funkin.util.HapticUtil.HapticsMode;
import funkin.ui.debug.FunkinDebugDisplay.DebugDisplayMode;
#if FEATURE_DISCORD_RPC
import funkin.api.discord.DiscordClient;
#end
/**
* A core class which provides a store of user-configurable, globally relevant values.
@@ -41,12 +44,23 @@ class Preferences
{
#if web
return 60;
#elseif mobile
var refreshRate:Int = FlxG.stage.window.displayMode.refreshRate;
if (refreshRate < 60) refreshRate = 60;
return refreshRate;
#else
var save:Save = Save.instance;
save.options.framerate = value;
Save.system.flush();
FlxG.updateFramerate = value;
FlxG.drawFramerate = value;
if (!unlockedFramerate)
{
FlxG.updateFramerate = value;
FlxG.drawFramerate = value;
}
return value;
#end
}
@@ -69,13 +83,13 @@ class Preferences
static function set_naughtyness(value:Bool):Bool
{
#if NO_FEATURE_NAUGHTYNESS
value = false;
#end
return false;
#else
var save:Save = Save.instance;
save.options.naughtyness = value;
Save.system.flush();
return value;
#end
}
/**
@@ -146,19 +160,23 @@ class Preferences
{
#if NO_FEATURE_DEBUG_DISPLAY
return DebugDisplayMode.Off;
#end
#else
return Save?.instance?.options?.debugDisplay ?? 'Off';
#end
}
static function set_debugDisplay(value:DebugDisplayMode):DebugDisplayMode
{
#if NO_FEATURE_DEBUG_DISPLAY
return DebugDisplayMode.Off;
#else
if (value != Save.instance.options.debugDisplay) setDebugDisplayMode(value);
var save = Save.instance;
save.options.debugDisplay = value;
Save.system.flush();
return value;
#end
}
/**
@@ -190,13 +208,13 @@ class Preferences
static function get_hapticsMode():HapticsMode
{
var value = Save?.instance?.options?.hapticsMode ?? "All";
var value = Save?.instance?.options?.hapticsMode ?? 'All';
return switch (value)
{
case "None":
case 'None':
HapticsMode.NONE;
case "Notes Only":
case 'Notes Only':
HapticsMode.NOTES_ONLY;
default:
HapticsMode.ALL;
@@ -210,11 +228,11 @@ class Preferences
switch (value)
{
case HapticsMode.NONE:
string = "None";
string = 'None';
case HapticsMode.NOTES_ONLY:
string = "Notes Only";
string = 'Notes Only';
default:
string = "All";
string = 'All';
};
var save:Save = Save.instance;
@@ -253,18 +271,23 @@ class Preferences
{
#if mobile
return false;
#end
#else
return Save?.instance?.options?.autoPause ?? true;
#end
}
static function set_autoPause(value:Bool):Bool
{
#if mobile
return false;
#else
if (value != Save.instance.options.autoPause) FlxG.autoPause = value;
var save:Save = Save.instance;
save.options.autoPause = value;
Save.system.flush();
return value;
#end
}
/**
@@ -314,35 +337,42 @@ class Preferences
static function get_vsyncMode():lime.ui.WindowVSyncMode
{
var value = Save?.instance?.options?.vsyncMode ?? "Off";
#if (mobile || web)
return lime.ui.WindowVSyncMode.OFF;
#else
var value = Save?.instance?.options?.vsyncMode ?? 'Off';
return switch (value)
{
case "Off":
case 'Off':
lime.ui.WindowVSyncMode.OFF;
case "On":
case 'On':
lime.ui.WindowVSyncMode.ON;
case "Adaptive":
case 'Adaptive':
lime.ui.WindowVSyncMode.ADAPTIVE;
default:
lime.ui.WindowVSyncMode.OFF;
};
#end
}
static function set_vsyncMode(value:lime.ui.WindowVSyncMode):lime.ui.WindowVSyncMode
{
#if (mobile || web)
return lime.ui.WindowVSyncMode.OFF;
#else
var string;
switch (value)
{
case lime.ui.WindowVSyncMode.OFF:
string = "Off";
string = 'Off';
case lime.ui.WindowVSyncMode.ON:
string = "On";
string = 'On';
case lime.ui.WindowVSyncMode.ADAPTIVE:
string = "Adaptive";
string = 'Adaptive';
default:
string = "Off";
string = 'Off';
};
WindowUtil.setVSyncMode(value);
@@ -351,49 +381,75 @@ class Preferences
save.options.vsyncMode = string;
Save.system.flush();
return value;
#end
}
public static var unlockedFramerate(get, set):Bool;
static function get_unlockedFramerate():Bool
{
#if (mobile || web)
return false;
#else
return Save?.instance?.options?.unlockedFramerate ?? false;
#end
}
static function set_unlockedFramerate(value:Bool):Bool
{
#if (mobile || web)
return false;
#else
if (value != Save.instance.options.unlockedFramerate)
{
#if web
toggleFramerateCap(value);
#end
}
var save:Save = Save.instance;
save.options.unlockedFramerate = value;
Save.system.flush();
return value;
#end
}
#if web
// We create a haxe version of this just for readability.
// We use these to override `window.requestAnimationFrame` in Javascript to uncap the framerate / "animation" request rate
// Javascript is crazy since u can just do stuff like that lol
public static var enabledDiscordRPC(get, set):Bool;
public static function unlockedFramerateFunction(callback, element)
static function get_enabledDiscordRPC():Bool
{
var currTime = Date.now().getTime();
var timeToCall = 0;
var id = js.Browser.window.setTimeout(function()
{
callback(currTime + timeToCall);
}, timeToCall);
return id;
return Save?.instance?.options?.enabledDiscordRPC ?? true;
}
// Lime already implements their own little framerate cap, so we can just use that
// This also gets set in the init function in Main.hx, since we need to definitely override it
public static var lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
static function set_enabledDiscordRPC(value:Bool):Bool
{
#if FEATURE_DISCORD_RPC
toggleDiscordRPC(value);
#end
var save:Save = Save.instance;
save.options.enabledDiscordRPC = value;
Save.system.flush();
return value;
}
#if FEATURE_DISCORD_RPC
public static function toggleDiscordRPC(enable:Bool)
{
if (DiscordClient.instance == null) return;
if (enable)
{
DiscordClient.instance.init();
if (DiscordClient.presenceParamsCache != null)
{
DiscordClient.instance.setPresence(DiscordClient.presenceParamsCache);
}
}
else
{
DiscordClient.instance.shutdown();
}
}
#end
/**
@@ -485,9 +541,7 @@ class Preferences
setDebugDisplayMode(Preferences.debugDisplay);
setDebugDisplayBGOpacity(Preferences.debugDisplayBGOpacity / 100);
#if web
toggleFramerateCap(Preferences.unlockedFramerate);
#end
#if mobile
// Apply the allowScreenTimeout setting.
@@ -497,21 +551,21 @@ class Preferences
static function toggleFramerateCap(unlocked:Bool):Void
{
#if web
var framerateFunction = unlocked ? unlockedFramerateFunction : lockedFramerateFunction;
untyped js.Syntax.code("window.requestAnimationFrame = framerateFunction;");
#if !(mobile || web)
FlxG.drawFramerate = unlocked ? 0 : framerate;
FlxG.updateFramerate = unlocked ? 0 : framerate;
#end
}
public static function setDebugDisplayMode(mode:DebugDisplayMode):Void
{
if (FlxG.game.parent.contains(Main.debugDisplay)) FlxG.game.parent.removeChild(Main.debugDisplay);
if (FlxG.game.contains(Main.debugDisplay)) FlxG.game.removeChild(Main.debugDisplay);
if (mode == DebugDisplayMode.Off) return;
Main.debugDisplay.isAdvanced = (mode == DebugDisplayMode.Advanced);
FlxG.game.parent.addChild(Main.debugDisplay);
FlxG.game.addChild(Main.debugDisplay);
}
static function setDebugDisplayBGOpacity(value:Float):Void
+26 -25
View File
@@ -8,25 +8,36 @@ import hxdiscord_rpc.Types.DiscordRichPresence;
import hxdiscord_rpc.Types.DiscordUser;
import sys.thread.Thread;
@:build(funkin.util.macro.EnvironmentMacro.build())
@:nullSafety
/**
* Handles integration with the Discord Rich Presence API.
*/
@:build(funkin.util.macro.EnvironmentMacro.build()) @:nullSafety
class DiscordClient
{
@:envField
static final DISCORD_CLIENT_ID:Null<String>;
/**
* The current instance of the singleton Discord client.
*/
public static var instance(get, never):DiscordClient;
static var _instance:Null<DiscordClient> = null;
static function get_instance():DiscordClient
{
if (DiscordClient._instance == null) _instance = new DiscordClient();
if (DiscordClient._instance == null) throw "Could not initialize singleton DiscordClient!";
if (DiscordClient._instance == null) throw 'Could not initialize singleton DiscordClient!';
return DiscordClient._instance;
}
var handlers:DiscordEventHandlers;
/**
* Latest passed parameters for the presence.
*/
public static var presenceParamsCache:Null<DiscordClientPresenceParams>;
private function new()
{
trace(' DISCORD '.bold().bg_blue() + ' Initializing event handlers...');
@@ -44,13 +55,13 @@ class DiscordClient
if (!hasValidCredentials())
{
FlxG.log.warn("Tried to initialize Discord connection, but credentials are invalid!");
FlxG.log.warn('Tried to initialize Discord connection, but credentials are invalid!');
return;
}
@:nullSafety(Off)
{
Discord.Initialize(DISCORD_CLIENT_ID, cpp.RawPointer.addressOf(handlers), false, "");
Discord.Initialize(DISCORD_CLIENT_ID, cpp.RawPointer.addressOf(handlers), false, '');
}
createDaemon();
@@ -61,7 +72,7 @@ class DiscordClient
*/
static function hasValidCredentials():Bool
{
return !(DISCORD_CLIENT_ID == null || DISCORD_CLIENT_ID == "" || (DISCORD_CLIENT_ID != null && DISCORD_CLIENT_ID.contains(" ")));
return !(DISCORD_CLIENT_ID == null || DISCORD_CLIENT_ID == '' || (DISCORD_CLIENT_ID != null && DISCORD_CLIENT_ID.contains(' ')));
}
var daemon:Null<Thread> = null;
@@ -93,6 +104,8 @@ class DiscordClient
public function setPresence(params:DiscordClientPresenceParams):Void
{
presenceParamsCache = params;
var presence:DiscordRichPresence = new DiscordRichPresence();
// Presence should always be playing the game.
@@ -102,35 +115,33 @@ class DiscordClient
presence.largeImageText = "Friday Night Funkin'";
// State should be generally what the person is doing, like "In the Menus" or "Pico (Pico Mix) [Freeplay Hard]"
presence.state = cast(params.state, Null<String>) ?? "";
presence.state = cast(params.state, Null<String>) ?? '';
// Details should be what the person is specifically doing, including stuff like timestamps (maybe something like "03:24 elapsed").
presence.details = cast(params.details, Null<String>) ?? "";
presence.details = cast(params.details, Null<String>) ?? '';
// The large image displaying what the user is doing.
// This should probably be album art.
// IMPORTANT NOTE: This can be an asset key uploaded to Discord's developer panel OR any URL you like.
presence.largeImageKey = cast(params.largeImageKey, Null<String>) ?? "album-volume1";
presence.largeImageKey = cast(params.largeImageKey, Null<String>) ?? 'album-volume1';
// TODO: Make this use the song's album art.
// presence.largeImageKey = "icon";
// presence.largeImageKey = "https://f4.bcbits.com/img/a0746694746_16.jpg";
// The small inset image for what the user is doing.
// This can be the opponent's health icon?
// NOTE: Like largeImageKey, this can be a URL, or an asset key.
presence.smallImageKey = cast(params.smallImageKey, Null<String>) ?? "";
presence.smallImageKey = cast(params.smallImageKey, Null<String>) ?? '';
// NOTE: In previous versions, this showed as "Elapsed", but now shows as playtime and doesn't look good
// presence.startTimestamp = time - 10;
// presence.endTimestamp = time + 30;
final button1:DiscordButton = new DiscordButton();
button1.label = "Play on Web";
button1.label = 'Play on Web';
button1.url = Constants.URL_NEWGROUNDS;
presence.buttons[0] = button1;
final button2:DiscordButton = new DiscordButton();
button2.label = "Download";
button2.label = 'Download';
button2.url = Constants.URL_ITCH;
presence.buttons[1] = button2;
@@ -138,6 +149,7 @@ class DiscordClient
}
// TODO: WHAT THE FUCK get this pointer bullfuckery out of here
private static function onReady(request:cpp.RawConstPointer<DiscordUser>):Void
{
trace(' DISCORD '.bold().bg_blue() + ' Client has connected!');
@@ -166,17 +178,6 @@ class DiscordClient
trace(' DISCORD '.bold().bg_blue() + ' Client has received an error! ($errorCode) "${cast (message, String)}"');
}
// public var type(get, set):DiscordActivityType;
// public var state(get, set):String;
// public var details(get, set):String;
// public var startTimestamp(get, set):Int;
// public var endTimestamp(get, set):Int;
// public var largeImageKey(get, set):String;
// public var largeImageText(get, set):String;
// public var smallImageKey(get, set):String;
// public var smallImageText(get, set):String;
//
//
// public var partyId(get, set)
// public var partySize(get, set)
// public var partyMax(get, set)
+47 -3
View File
@@ -3,8 +3,7 @@ package funkin.api.newgrounds;
#if FEATURE_NEWGROUNDS_EVENTS
import io.newgrounds.Call.CallOutcome;
import io.newgrounds.NG;
import io.newgrounds.objects.events.Outcome;
import io.newgrounds.objects.events.Result;
import io.newgrounds.objects.events.Result.LogEventData;
#end
/**
@@ -15,7 +14,13 @@ class Events
{
// Only allow letters, numbers, spaces, dashes, and underscores.
static final EVENT_NAME_REGEX:EReg = ~/[^a-zA-Z0-9 -_]/g;
static final ERROR_CODE_INVALID_EVENT_NAME:Int = 103;
/**
* Log an analytics event to Newgrounds. Does nothing if the user is not logged in to Newgrounds.
*
* @param eventName The name of the event to log.
*/
public static function logEvent(eventName:String):Void
{
#if (FEATURE_NEWGROUNDS && FEATURE_NEWGROUNDS_EVENTS)
@@ -50,7 +55,7 @@ class Events
case RESULT(error):
switch (error.code)
{
case 103: // Invalid custom event name
case ERROR_CODE_INVALID_EVENT_NAME: // Invalid custom event name
trace(' NEWGROUNDS '.bold().bg_orange() + ' Invalid custom event name: ${eventName}');
default:
trace(' NEWGROUNDS '.bold().bg_orange() + ' Result error (${error.code}) while logging event: ${error.message}');
@@ -60,41 +65,80 @@ class Events
}
#end
/**
* Log an analytics events for the start of the game.
*/
public static inline function logStartGame():Void
{
logEvent('start-game');
}
/**
* Log an analytics events for the completion of a song.
*
* @param songId The ID of the song that was played.
* @param variation The variation of the song that was played (e.g. 'easy', 'normal', 'hard', 'expert').
*/
public static inline function logStartSong(songId:String, variation:String):Void
{
logEvent('start-song_${songId}-${variation}');
}
/**
* Log an analytics event for the failure of a song.
*
* @param songId The ID of the song that was failed.
* @param variation The variation of the song that was failed (e.g. 'easy', 'normal', 'hard', 'expert').
*/
public static inline function logFailSong(songId:String, variation:String):Void
{
logEvent('blueballs_${songId}-${variation}');
}
/**
* Log an analytics event for the completion of a song.
*
* @param songId The ID of the song that was completed.
* @param variation The variation of the song that was completed (e.g. 'easy', 'normal', 'hard', 'expert').
*/
public static inline function logCompleteSong(songId:String, variation:String):Void
{
logEvent('complete-song_${songId}-${variation}');
}
/**
* Log an analytics event for the start of a level.
*
* @param levelId The ID of the level that was started.
*/
public static inline function logStartLevel(levelId:String):Void
{
logEvent('start-level_${levelId}');
}
/**
* Log an analytics event for the completion of a level.
*
* @param levelId The ID of the level that was completed.
*/
public static inline function logCompleteLevel(levelId:String):Void
{
logEvent('complete-level_${levelId}');
}
/**
* Log an analytics event for earning a rank.
*
* @param rankName The name of the rank that was earned.
*/
public static inline function logEarnRank(rankName:String):Void
{
logEvent('earn-rank_${rankName}');
}
/**
* Log an analytics event for watching a cartoon.
*/
public static inline function logWatchCartoon():Void
{
logEvent('watch-cartoon');
+77 -86
View File
@@ -24,7 +24,7 @@ class Leaderboards
var leaderboardList:Null<ScoreBoardList> = NewgroundsClient.instance.leaderboards;
if (leaderboardList == null)
{
trace(' NEWGROUNDS '.bold().bg_orange() + ' Not logged in, cannot fetch medal data!');
trace(' NEWGROUNDS '.bold().bg_orange() + ' Not logged in, cannot fetch leaderboard data!');
return [];
}
@@ -161,7 +161,7 @@ class LeaderboardsSandboxed
* @param leaderboard The leaderboard to fetch scores from.
* @param params Additional parameters for fetching the score.
*/
public function requestScores(leaderboard:Leaderboard, params:RequestScoresParams)
public static function requestScores(leaderboard:Leaderboard, params:RequestScoresParams)
{
Leaderboards.requestScores(leaderboard, params);
}
@@ -217,6 +217,7 @@ typedef RequestScoresParams =
/**
* An enumeration of Newgrounds leaderboards for the game's levels and songs.
*/
@SuppressWarnings('checkstyle:FieldDocComment')
enum abstract Leaderboard(Int) from Int to Int
{
/**
@@ -236,14 +237,12 @@ enum abstract Leaderboard(Int) from Int to Int
public var StoryWeek6 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14244 #else 9957 #end;
public var StoryWeek7 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14245 #else 14682 #end;
public var StoryWeekend1 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14237 #else 14683 #end;
// Collab 1 only has one song.
//
// SONGS
//
// Tutorial
public var Tutorial = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14249 #else 14684 #end;
// Week 1
public var Bopeebo = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14246 #else 9603 #end;
public var BopeeboErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14685 #end;
@@ -254,7 +253,6 @@ enum abstract Leaderboard(Int) from Int to Int
public var DadBattle = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14248 #else 9605 #end;
public var DadBattleErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14689 #end;
public var DadBattlePicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14690 #end;
// Week 2
public var Spookeez = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9604 #end;
public var SpookeezErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14691 #end;
@@ -263,7 +261,6 @@ enum abstract Leaderboard(Int) from Int to Int
public var SouthErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14693 #end;
public var SouthPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14694 #end;
public var Monster = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14703 #end;
// Week 3
public var Pico = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9766 #end;
public var PicoErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14695 #end;
@@ -274,14 +271,12 @@ enum abstract Leaderboard(Int) from Int to Int
public var Blammed = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9768 #end;
public var BlammedErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14704 #end;
public var BlammedPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14705 #end;
// Week 4
public var SatinPanties = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9869 #end;
public var SatinPantiesErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14701 #end;
public var High = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9867 #end;
public var HighErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14699 #end;
public var MILF = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9868 #end;
// Week 5
public var Cocoa = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14706 #end;
public var CocoaErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14707 #end;
@@ -290,7 +285,6 @@ enum abstract Leaderboard(Int) from Int to Int
public var EggnogErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14711 #end;
public var EggnogPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14710 #end;
public var WinterHorrorland = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14712 #end;
// Week 6
public var Senpai = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9958 #end;
public var SenpaiErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14713 #end;
@@ -300,7 +294,6 @@ enum abstract Leaderboard(Int) from Int to Int
public var RosesPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14717 #end;
public var Thorns = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9960 #end;
public var ThornsErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14715 #end;
// Week 7
public var Ugh = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14718 #end;
public var UghErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14722 #end;
@@ -309,7 +302,6 @@ enum abstract Leaderboard(Int) from Int to Int
public var GunsPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14723 #end;
public var Stress = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14720 #end;
public var StressPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14724 #end;
// Weekend 1
public var Darnell = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14725 #end;
public var DarnellErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14727 #end;
@@ -318,7 +310,6 @@ enum abstract Leaderboard(Int) from Int to Int
public var LitUpBFMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14729 #end;
public var TwoHot = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14730 #end; // Variable names can't start with a number!
public var Blazin = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14731 #end;
// Collab 1
public var Spaghetti = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 15448 #else 15451 #end;
@@ -340,21 +331,21 @@ enum abstract Leaderboard(Int) from Int to Int
{
switch (levelId)
{
case "week1":
case 'week1':
return StoryWeek1;
case "week2":
case 'week2':
return StoryWeek2;
case "week3":
case 'week3':
return StoryWeek3;
case "week4":
case 'week4':
return StoryWeek4;
case "week5":
case 'week5':
return StoryWeek5;
case "week6":
case 'week6':
return StoryWeek6;
case "week7":
case 'week7':
return StoryWeek7;
case "weekend1":
case 'weekend1':
return StoryWeekend1;
// Collab 1 has only one song.
default:
@@ -380,153 +371,153 @@ enum abstract Leaderboard(Int) from Int to Int
}
else if (Constants.DEFAULT_DIFFICULTY_LIST_ERECT.contains(difficulty))
{
variation = "erect";
variation = 'erect';
}
switch (variation)
{
case "pico":
case 'pico':
switch (songId)
{
case "bopeebo":
case 'bopeebo':
return BopeeboPicoMix;
case "fresh":
case 'fresh':
return FreshPicoMix;
case "dadbattle":
case 'dadbattle':
return DadBattlePicoMix;
case "spookeez":
case 'spookeez':
return SpookeezPicoMix;
case "south":
case 'south':
return SouthPicoMix;
case "pico":
case 'pico':
return PicoPicoMix;
case "philly-nice":
case 'philly-nice':
return PhillyNicePicoMix;
case "blammed":
case 'blammed':
return BlammedPicoMix;
case "cocoa":
case 'cocoa':
return CocoaPicoMix;
case "eggnog":
case 'eggnog':
return EggnogPicoMix;
case "senpai":
case 'senpai':
return SenpaiPicoMix;
case "roses":
case 'roses':
return RosesPicoMix;
case "ugh":
case 'ugh':
return UghPicoMix;
case "guns":
case 'guns':
return GunsPicoMix;
case "stress":
case 'stress':
return StressPicoMix;
default:
return Unknown;
}
case "bf":
case 'bf':
switch (songId)
{
case "darnell":
case 'darnell':
return DarnellBFMix;
case "lit-up":
case 'lit-up':
return LitUpBFMix;
default:
return Unknown;
}
case "erect":
case 'erect':
switch (songId)
{
case "bopeebo":
case 'bopeebo':
return BopeeboErect;
case "fresh":
case 'fresh':
return FreshErect;
case "dadbattle":
case 'dadbattle':
return DadBattleErect;
case "spookeez":
case 'spookeez':
return SpookeezErect;
case "south":
case 'south':
return SouthErect;
case "pico":
case 'pico':
return PicoErect;
case "philly-nice":
case 'philly-nice':
return PhillyNiceErect;
case "blammed":
case 'blammed':
return BlammedErect;
case "satin-panties":
case 'satin-panties':
return SatinPantiesErect;
case "high":
case 'high':
return HighErect;
case "cocoa":
case 'cocoa':
return CocoaErect;
case "eggnog":
case 'eggnog':
return EggnogErect;
case "senpai":
case 'senpai':
return SenpaiErect;
case "roses":
case 'roses':
return RosesErect;
case "thorns":
case 'thorns':
return ThornsErect;
case "ugh":
case 'ugh':
return UghErect;
case "darnell":
case 'darnell':
return DarnellErect;
default:
return Unknown;
}
case "default":
case 'default':
switch (songId)
{
case "tutorial":
case 'tutorial':
return Tutorial;
case "bopeebo":
case 'bopeebo':
return Bopeebo;
case "fresh":
case 'fresh':
return Fresh;
case "dadbattle":
case 'dadbattle':
return DadBattle;
case "spookeez":
case 'spookeez':
return Spookeez;
case "south":
case 'south':
return South;
case "monster":
case 'monster':
return Monster;
case "pico":
case 'pico':
return Pico;
case "philly-nice":
case 'philly-nice':
return PhillyNice;
case "blammed":
case 'blammed':
return Blammed;
case "satin-panties":
case 'satin-panties':
return SatinPanties;
case "high":
case 'high':
return High;
case "milf":
case 'milf':
return MILF;
case "cocoa":
case 'cocoa':
return Cocoa;
case "eggnog":
case 'eggnog':
return Eggnog;
case "winter-horrorland":
case 'winter-horrorland':
return WinterHorrorland;
case "senpai":
case 'senpai':
return Senpai;
case "roses":
case 'roses':
return Roses;
case "thorns":
case 'thorns':
return Thorns;
case "ugh":
case 'ugh':
return Ugh;
case "guns":
case 'guns':
return Guns;
case "stress":
case 'stress':
return Stress;
case "darnell":
case 'darnell':
return Darnell;
case "lit-up":
case 'lit-up':
return LitUp;
case "2hot":
case '2hot':
return TwoHot;
case "blazin":
case 'blazin':
return Blazin;
case "spaghetti":
case 'spaghetti':
return Spaghetti;
default:
return Unknown;
+37 -18
View File
@@ -58,7 +58,7 @@ class Medals
// Play the medal unlock animation, but only if the user has not already unlocked it.
#if html5
// Web builds support parsing the bitmap data from the URL directly.
BitmapData.loadFromFile("https:" + medalData.icon).onComplete(function(bmp:BitmapData)
BitmapData.loadFromFile('https:' + medalData.icon).onComplete(function(bmp:BitmapData)
{
var medalGraphic = FlxGraphic.fromBitmapData(bmp);
medalGraphic.persist = true;
@@ -78,12 +78,12 @@ class Medals
#end
})[0];
if (localMedalData == null) throw "You forgot to encode a Base64 image for medal: " + medal;
if (localMedalData == null) throw 'You forgot to encode a Base64 image for medal: ' + medal;
var str:String = localMedalData.icon;
// Lime/OpenFL parses it without the included prefix stuff, so we remove it.
str = str.replace("data:image/png;base64,", "").trim();
var bitmapData = BitmapData.fromBase64(str, "image/png");
str = str.replace('data:image/png;base64,', '').trim();
var bitmapData = BitmapData.fromBase64(str, 'image/png');
var medalGraphic:Null<FlxGraphic> = null;
if (str != null)
{
@@ -122,8 +122,7 @@ class Medals
if (parser.errors.length > 0)
{
trace(' NEWGROUNDS '.bold().bg_orange() + ' Failed to parse local medal data!');
for (error in parser.errors)
funkin.data.DataError.printError(error);
for (error in parser.errors) funkin.data.DataError.printError(error);
medalJSON = [];
}
else
@@ -407,25 +406,25 @@ enum abstract Medal(Int) from Int to Int
{
switch (levelId)
{
case "tutorial":
case 'tutorial':
return StoryTutorial;
case "week1":
case 'week1':
return StoryWeek1;
case "week2":
case 'week2':
return StoryWeek2;
case "week3":
case 'week3':
return StoryWeek3;
case "week4":
case 'week4':
return StoryWeek4;
case "week5":
case 'week5':
return StoryWeek5;
case "week6":
case 'week6':
return StoryWeek6;
case "week7":
case 'week7':
return StoryWeek7;
case "weekend1":
case 'weekend1':
return StoryWeekend1;
case "sserafim":
case 'sserafim':
return StoryCollab1;
default:
return Unknown;
@@ -438,7 +437,27 @@ enum abstract Medal(Int) from Int to Int
*/
public static function getAllMedals():Array<Medal>
{
return
[StartGame, StoryTutorial, StoryWeek1, StoryWeek2, StoryWeek3, StoryWeek4, StoryWeek5, StoryWeek6, StoryWeek7, StoryWeekend1, CharSelect, FreeplayPicoMix, FreeplayStressPico, LossRating, PerfectRatingHard, GoldPerfectRatingHard, ErectDifficulty, GoldPerfectRatingNightmare, FridayNight, Nice];
return [
StartGame,
StoryTutorial,
StoryWeek1,
StoryWeek2,
StoryWeek3,
StoryWeek4,
StoryWeek5,
StoryWeek6,
StoryWeek7,
StoryWeekend1,
CharSelect,
FreeplayPicoMix,
FreeplayStressPico,
LossRating,
PerfectRatingHard,
GoldPerfectRatingHard,
ErectDifficulty,
GoldPerfectRatingNightmare,
FridayNight,
Nice
];
}
}
+2 -4
View File
@@ -1,14 +1,12 @@
package funkin.api.newgrounds;
#if FEATURE_NEWGROUNDS
import io.newgrounds.utils.SaveSlotList;
import io.newgrounds.objects.SaveSlot;
import io.newgrounds.Call.CallError;
import io.newgrounds.objects.events.Outcome;
import funkin.save.Save;
import funkin.save.Save.RawSaveData;
@:nullSafety
@:access(funkin.save.Save)
@:nullSafety @:access(funkin.save.Save)
class NGSaveSlot
{
public static var instance(get, never):NGSaveSlot;
@@ -1,8 +1,7 @@
package funkin.api.newgrounds;
import funkin.save.Save;
import funkin.api.newgrounds.Medals.Medal;
#if FEATURE_NEWGROUNDS
import funkin.save.Save;
import io.newgrounds.Call.CallError;
import io.newgrounds.NG;
import io.newgrounds.NGLite;
@@ -17,24 +16,20 @@ import io.newgrounds.objects.User;
import funkin.mobile.util.WebViewUtil;
#end
@:build(funkin.util.macro.EnvironmentMacro.build())
@:nullSafety
@:build(funkin.util.macro.EnvironmentMacro.build()) @:nullSafety
class NewgroundsClient
{
@:envField
static final API_NG_APP_ID:Null<String>;
@:envField
static final API_NG_ENC_KEY:Null<String>;
public static var instance(get, never):NewgroundsClient;
static var _instance:Null<NewgroundsClient> = null;
static function get_instance():NewgroundsClient
{
if (NewgroundsClient._instance == null) _instance = new NewgroundsClient();
if (NewgroundsClient._instance == null) throw "Could not initialize singleton NewgroundsClient!";
if (NewgroundsClient._instance == null) throw 'Could not initialize singleton NewgroundsClient!';
return NewgroundsClient._instance;
}
@@ -54,7 +49,7 @@ class NewgroundsClient
if (!hasValidCredentials())
{
FlxG.log.warn("Tried to initialize Newgrounds client, but credentials are invalid!");
FlxG.log.warn('Tried to initialize Newgrounds client, but credentials are invalid!');
return;
}
@@ -104,7 +99,7 @@ class NewgroundsClient
{
if (NG.core == null)
{
FlxG.log.warn("No Newgrounds client initialized! Are your credentials invalid?");
FlxG.log.warn('No Newgrounds client initialized! Are your credentials invalid?');
return;
}
if (NG.core.attemptingLogin)
@@ -129,7 +124,7 @@ class NewgroundsClient
NG.core.onPassportUrlOpen();
}
else
NG.core.logError("Cannot open passport");
NG.core.logError('Cannot open passport');
#else
NG.core.openPassportUrl();
#end
@@ -149,7 +144,7 @@ class NewgroundsClient
{
if (NG.core == null)
{
FlxG.log.warn("No Newgrounds client initialized! Are your credentials invalid?");
FlxG.log.warn('No Newgrounds client initialized! Are your credentials invalid?');
return;
}
@@ -211,11 +206,11 @@ class NewgroundsClient
static function hasValidCredentials():Bool
{
return !(API_NG_APP_ID == null
|| API_NG_APP_ID == ""
|| (API_NG_APP_ID != null && API_NG_APP_ID.contains(" "))
|| API_NG_APP_ID == ''
|| (API_NG_APP_ID != null && API_NG_APP_ID.contains(' '))
|| API_NG_ENC_KEY == null
|| API_NG_ENC_KEY == ""
|| (API_NG_ENC_KEY != null && API_NG_ENC_KEY.contains(" ")));
|| API_NG_ENC_KEY == ''
|| (API_NG_ENC_KEY != null && API_NG_ENC_KEY.contains(' ')));
}
function onLoginResolved(outcome:LoginOutcome):Void
@@ -349,8 +344,6 @@ class NewgroundsClient
function onFetchedLeaderboards(outcome:Outcome<CallError>):Void
{
trace(' NEWGROUNDS '.bold().bg_orange() + ' Fetched leaderboards!');
// trace(funkin.api.newgrounds.Leaderboards.listLeaderboardData());
}
function onFetchedSaveSlots(outcome:Outcome<CallError>):Void
+2 -3
View File
@@ -3,7 +3,6 @@ package funkin.api.newgrounds;
#if FEATURE_NEWGROUNDS
import io.newgrounds.NG;
#end
import funkin.api.newgrounds.NewgroundsClient;
import funkin.util.WindowUtil;
/**
@@ -22,7 +21,7 @@ class Referral
if (NewgroundsClient.instance.isLoggedIn())
{
NG.core?.calls.loader.loadReferral(false)
.addComponentParameter("referral_name", referralName)
.addComponentParameter('referral_name', referralName)
.addResponseHandler(response ->
{
trace(response);
@@ -51,6 +50,6 @@ class Referral
*/
public static function doMerchReferral():Void
{
doReferral("merch_link", Constants.URL_MERCH_FALLBACK);
doReferral('merch_link', Constants.URL_MERCH_FALLBACK);
}
}
+17 -19
View File
@@ -1,7 +1,6 @@
package funkin.audio;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxMath;
import flixel.sound.FlxSound;
import flixel.system.FlxAssets.FlxSoundAsset;
import flixel.tweens.FlxTween;
@@ -16,7 +15,6 @@ import funkin.Paths.PathsFunction;
import lime.app.Promise;
import lime.media.AudioSource;
import openfl.events.Event;
import openfl.media.Sound;
import openfl.media.SoundChannel;
import openfl.media.SoundMixer;
@@ -123,14 +121,14 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
/**
* For debug purposes.
*/
var _label:String = "unknown";
var _label:String = 'unknown';
public function new()
{
super();
}
public override function update(elapsedSec:Float)
override public function update(elapsedSec:Float)
{
if (!playing && !_shouldPlay) return;
@@ -171,7 +169,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
return this;
}
public override function play(forceRestart:Bool = false, startTime:Float = 0, ?endTime:Float):FunkinSound
override public function play(forceRestart:Bool = false, startTime:Float = 0, ?endTime:Float):FunkinSound
{
if (!exists) return this;
@@ -208,7 +206,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
}
}
public override function pause():FunkinSound
override public function pause():FunkinSound
{
if (_shouldPlay)
{
@@ -225,7 +223,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
return this;
}
public override function resume():FunkinSound
override public function resume():FunkinSound
{
if (this._time < 0)
{
@@ -329,9 +327,12 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
var suffix = params.suffix ?? '';
var pathToUse = switch (pathsFunction)
{
case MUSIC: Paths.music('$key/$key');
case INST: Paths.inst('$key', suffix);
default: Paths.music('$key/$key');
case MUSIC:
Paths.music('$key/$key');
case INST:
Paths.inst('$key', suffix);
default:
Paths.music('$key/$key');
}
var shouldLoadPartial = params.partialParams?.loadPartial ?? false;
@@ -401,7 +402,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
while (partialQueue.length > 0)
{
@:nullSafety(Off)
partialQueue.pop().error("Cancel loading partial sound");
partialQueue.pop().error('Cancel loading partial sound');
}
}
@@ -419,7 +420,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
* @param autoPlay Whether to play the sound immediately or wait for a `play()` call.
* @param persist Whether to keep this `FunkinSound` between states, or destroy it.
* @param onComplete Called when the sound finished playing.
* @param onLoad Called when the sound finished loading. Called immediately for succesfully loaded embedded sounds.
* @param onLoad Called when the sound finished loading. Called immediately for successfully loaded embedded sounds.
* @param important If `true`, the sound channel will forcefully be added onto the channel array, even if full. Use sparingly!
* @return A `FunkinSound` object, or `null` if the sound could not be loaded.
*/
@@ -500,7 +501,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
{
promise.future.onError(function(e)
{
soundRequest.error("Sound loading was errored or cancelled");
soundRequest.error('Sound loading was errored or cancelled');
});
soundRequest.future.onComplete(function(partialSound)
@@ -514,9 +515,8 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
}
@:nullSafety(Off)
public override function destroy():Void
override public function destroy():Void
{
// trace('[FunkinSound] Destroying sound "${this._label}"');
super.destroy();
if (fadeTween != null)
{
@@ -528,9 +528,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
this._waveformData = null;
}
@:access(openfl.media.Sound)
@:access(openfl.media.SoundChannel)
@:access(openfl.media.SoundMixer)
@:access(openfl.media.Sound) @:access(openfl.media.SoundChannel) @:access(openfl.media.SoundMixer)
override function startSound(startTime:Float)
{
if (!important)
@@ -602,7 +600,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
/**
* Produces a string representation suitable for debugging.
*/
public override function toString():String
override public function toString():String
{
return 'FunkinSound(${this._label})';
}
+7 -11
View File
@@ -11,13 +11,9 @@ import flixel.tweens.FlxTween;
class SoundGroup extends FlxTypedGroup<FunkinSound>
{
public var time(get, set):Float;
public var volume(get, set):Float;
public var muted(get, set):Bool;
public var pitch(get, set):Float;
public var playing(get, never):Bool;
public function new()
@@ -25,8 +21,8 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
super();
}
@:deprecated("Create sound files and call add() instead")
public static function build(song:String, ?files:Array<String> = null):SoundGroup
@:deprecated('Create sound files and call add() instead')
public static function build(song:String, ?files:Array<String>):SoundGroup
{
var result = new SoundGroup();
@@ -73,7 +69,7 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
/**
* Add a sound to the group.
*/
public override function add(sound:FunkinSound):Null<FunkinSound>
override public function add(sound:FunkinSound):Null<FunkinSound>
{
var result:FunkinSound = super.add(sound);
@@ -83,7 +79,7 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
// else the sound will restart immediately when played.
// TODO: Past me experienced that issue but present me didn't? Investigate.
// result.play(true, 0.0);
// result.pause();
result.time = this.time;
result.onComplete = function()
@@ -122,7 +118,6 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
{
if (sound.length < startTime)
{
// trace('Queuing sound (${sound.toString()} past its length! Skipping...)');
return;
}
sound.play(forceRestart, startTime, endTime);
@@ -178,7 +173,7 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
}
}
public override function destroy():Void
override public function destroy():Void
{
stop();
super.destroy();
@@ -187,7 +182,7 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
/**
* Remove all sounds from the group.
*/
public override function clear():Void
override public function clear():Void
{
this.stop();
@@ -242,6 +237,7 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
}
// in PlayState, adjust the code so that it only mutes the player1 vocal tracks?
function set_volume(volume:Float):Float
{
forEachAlive(function(snd:FunkinSound)
+9 -2
View File
@@ -6,6 +6,13 @@ import funkin.audio.waveform.WaveformData;
@:nullSafety
class VoicesGroup extends SoundGroup
{
/**
* Whenever or not the game is using the legacy vocals system (shared Voices.ogg)
*/
public var legacyVoiceSystem:Bool = false;
public var legacyVoiceUsesPlayer:Bool = false;
var playerVoices:Null<FlxTypedGroup<FunkinSound>>;
var opponentVoices:Null<FlxTypedGroup<FunkinSound>>;
@@ -156,14 +163,14 @@ class VoicesGroup extends SoundGroup
return opponentVoices?.members[0]?.length ?? 0.0;
}
public override function clear():Void
override public function clear():Void
{
playerVoices?.clear();
opponentVoices?.clear();
super.clear();
}
public override function destroy():Void
override public function destroy():Void
{
if (playerVoices != null)
{
+35 -6
View File
@@ -15,7 +15,6 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
// public var vis:VisShit;
var analyzer:Null<SpectralAnalyzer> = null;
var analyzerLevelsCache:Array<Bar> = new Array<Bar>();
var volumes:Array<Float> = [];
public var snd:Null<FlxSound> = null;
@@ -23,6 +22,7 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
static final BAR_COUNT:Int = 7;
// TODO: Make the sprites easier to soft code.
public function new(snd:FlxSound, pixel:Bool)
{
super();
@@ -35,8 +35,40 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
var visFrms:FlxAtlasFrames = Paths.getSparrowAtlas(pixel ? 'characters/abotPixel/aBotVizPixel' : 'characters/abot/aBotViz');
// these are the differences in X position, from left to right
var positionX:Array<Float> = pixel ? [0, 7 * 6, 8 * 6, 9 * 6, 10 * 6, 6 * 6, 7 * 6] : [0, 59, 56, 66, 54, 52, 51];
var positionY:Array<Float> = pixel ? [0, -2 * 6, -1 * 6, 0, 0, 1 * 6, 2 * 6] : [0, -8, -3.5, -0.4, 0.5, 4.7, 7];
var positionX:Array<Float> = pixel ? [
0,
7 * 6,
8 * 6,
9 * 6,
10 * 6,
6 * 6,
7 * 6
] : [
0,
59,
56,
66,
54,
52,
51
];
var positionY:Array<Float> = pixel ? [
0,
-2 * 6,
-1 * 6,
0,
0,
1 * 6,
2 * 6
] : [
0,
-8,
-3.5,
-0.4,
0.5,
4.7,
7
];
for (index in 1...visCount)
{
@@ -89,9 +121,6 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
analyzer = null;
}
var visTimer:Float = -1;
var visTimeMax:Float = 1 / 30;
override function update(elapsed:Float)
{
super.update(elapsed);
@@ -23,7 +23,6 @@ class PolygonSpectogram extends MeshRender
public var audioData:Int16Array;
public var detail:Float = 1;
public var thickness:Float = 2;
public var waveAmplitude:Int = 100;
@@ -89,7 +88,7 @@ class PolygonSpectogram extends MeshRender
var funnyPixels:Int = Std.int(daHeight * detail); // sorta redundant but just need it for different var...
if (prevAudioData == audioData.subarray(startSample, startSample + samplesToGen)) return; // optimize / finish funciton here, no need to re-render
if (prevAudioData == audioData.subarray(startSample, startSample + samplesToGen)) return; // optimize / finish function here, no need to re-render
prevAudioData = audioData.subarray(startSample, samplesToGen);
@@ -92,13 +92,13 @@ class PolygonVisGroup extends FlxTypedGroup<PolygonSpectogram>
* @param vis The visualizer to add.
* @return The added visualizer.
*/
public override function add(vis:PolygonSpectogram):PolygonSpectogram
override public function add(vis:PolygonSpectogram):PolygonSpectogram
{
var result:PolygonSpectogram = super.add(vis);
return result;
}
public override function destroy():Void
override public function destroy():Void
{
if (playerVis != null)
{
@@ -16,14 +16,11 @@ using flixel.util.FlxSpriteUtil;
class SpectogramSprite extends FlxTypedSpriteGroup<FlxSprite>
{
var sampleRate:Int;
var lengthOfShit:Int = 500;
public var visType:VISTYPE = UPDATED;
public var col:Int = FlxColor.WHITE;
public var daHeight:Float = FlxG.height;
public var vis:VisShit;
public function new(daSound:FlxSound, ?col:FlxColor = FlxColor.WHITE, ?height:Float = 720, ?amnt:Int = 500)
@@ -193,8 +190,7 @@ class SpectogramSprite extends FlxTypedSpriteGroup<FlxSprite>
var freqPower:Float = 0;
for (pow in 0...freqShit.length)
freqPower += freqShit[pow][remappedFreq];
for (pow in 0...freqShit.length) freqPower += freqShit[pow][remappedFreq];
freqPower /= freqShit.length;
var freqIDK:Float = FlxMath.remapToRange(freqPower, 0, 0.000005, 0, 50);
+3 -1
View File
@@ -64,7 +64,9 @@ class VisShit
while (c < samples.length)
{
// take a chunk (zero-padded if needed) and apply the window
final chunk = [for (n in 0...fftN) (c + n < samples.length ? samples[c + n] : 0.0) * window(n)];
final chunk = [
for (n in 0...fftN) (c + n < samples.length ? samples[c + n] : 0.0) * window(n)
];
// compute positive spectrum with sampling correction and BP filter
final freqs = FFT.rfft(chunk).map(z -> z.scale(1 / fftN).magnitude).mapi(melodicBandPass);
+19 -20
View File
@@ -1,10 +1,9 @@
package funkin.audio.visualize.dsp;
/**
Complex number representation.
**/
@:forward(real, imag) @:notNull @:pure
@:nullSafety
* Complex number representation.
*/
@:forward(real, imag) @:notNull @:pure @:nullSafety
abstract Complex({
final real:Float;
final imag:Float;
@@ -13,21 +12,21 @@ abstract Complex({
public inline function new(real:Float, imag:Float) this = {real: real, imag: imag};
/**
Makes a Complex number with the given Float as its real part and a zero imag part.
**/
* Makes a Complex number with the given Float as its real part and a zero imag part.
*/
@:from
public static inline function fromReal(r:Float) return new Complex(r, 0);
/**
Complex argument, in radians.
**/
* Complex argument, in radians.
*/
public var angle(get, never):Float;
inline function get_angle() return Math.atan2(this.imag, this.real);
/**
Complex module.
**/
* Complex module.
*/
public var magnitude(get, never):Float;
inline function get_magnitude() return Math.sqrt(this.real * this.real + this.imag * this.imag);
@@ -42,29 +41,29 @@ abstract Complex({
public inline function mult(rhs:Complex):Complex return new Complex(this.real * rhs.real - this.imag * rhs.imag, this.real * rhs.imag + this.imag * rhs.real);
/**
Returns the complex conjugate, does not modify this object.
**/
* Returns the complex conjugate, does not modify this object.
*/
public inline function conj():Complex return new Complex(this.real, -this.imag);
/**
Multiplication by a real factor, does not modify this object.
**/
* Multiplication by a real factor, does not modify this object.
*/
public inline function scale(k:Float):Complex return new Complex(this.real * k, this.imag * k);
public inline function copy():Complex return new Complex(this.real, this.imag);
/**
The imaginary unit.
**/
* The imaginary unit.
*/
public static final im = new Complex(0, 1);
/**
The complex zero.
**/
* The complex zero.
*/
public static final zero = new Complex(0, 0);
/**
Computes the complex exponential `e^(iw)`.
**/
* Computes the complex exponential `e^(iw)`.
*/
public static inline function exp(w:Float) return new Complex(Math.cos(w), Math.sin(w));
}
+44 -28
View File
@@ -6,27 +6,27 @@ using funkin.audio.visualize.dsp.Signal;
// these are only used for testing, down in FFT.main()
/**
Fast/Finite Fourier Transforms.
**/
* Fast/Finite Fourier Transforms.
*/
@:nullSafety
class FFT
{
/**
Computes the Discrete Fourier Transform (DFT) of a `Complex` sequence.
If the input has N data points (N should be a power of 2 or padding will be added)
from a signal sampled at intervals of 1/Fs, the result will be a sequence of N
samples from the Discrete-Time Fourier Transform (DTFT) - which is Fs-periodic -
with a spacing of Fs/N Hz between them and a scaling factor of Fs.
**/
* Computes the Discrete Fourier Transform (DFT) of a `Complex` sequence.
*
* If the input has N data points (N should be a power of 2 or padding will be added)
* from a signal sampled at intervals of 1/Fs, the result will be a sequence of N
* samples from the Discrete-Time Fourier Transform (DTFT) - which is Fs-periodic -
* with a spacing of Fs/N Hz between them and a scaling factor of Fs.
*/
public static function fft(input:Array<Complex>):Array<Complex> return do_fft(input, false);
/**
Like `fft`, but for a real (Float) sequence input.
Since the input time signal is real, its frequency representation is
Hermitian-symmetric so we only return the positive frequencies.
**/
* Like `fft`, but for a real (Float) sequence input.
*
* Since the input time signal is real, its frequency representation is
* Hermitian-symmetric so we only return the positive frequencies.
*/
public static function rfft(input:Array<Float>):Array<Complex>
{
final s = fft(input.map(Complex.fromReal));
@@ -34,19 +34,22 @@ class FFT
}
/**
Computes the Inverse DFT of a periodic input sequence.
If the input contains N (a power of 2) DTFT samples, each spaced Fs/N Hz
from each other, the result will consist of N data points as sampled
from a time signal at intervals of 1/Fs with a scaling factor of 1/Fs.
**/
* Computes the Inverse DFT of a periodic input sequence.
*
* If the input contains N (a power of 2) DTFT samples, each spaced Fs/N Hz
* from each other, the result will consist of N data points as sampled
* from a time signal at intervals of 1/Fs with a scaling factor of 1/Fs.
*/
public static function ifft(input:Array<Complex>):Array<Complex> return do_fft(input, true);
// Handles padding and scaling for forwards and inverse FFTs.
static function do_fft(input:Array<Complex>, inverse:Bool):Array<Complex>
{
final n = nextPow2(input.length);
var ts = [for (i in 0...n) if (i < input.length) input[i] else Complex.zero];
var ts = [
for (i in 0...n) if (i < input.length) input[i] else Complex.zero
];
var fs = [for (_ in 0...n) Complex.zero];
ditfft2(ts, 0, fs, 0, n, 1, inverse);
return inverse ? fs.map(z -> z.scale(1 / n)) : fs;
@@ -54,6 +57,7 @@ class FFT
}
// Radix-2 Decimation-In-Time variant of Cooley–Tukey's FFT, recursive.
static function ditfft2(time:Array<Complex>, t:Int, freq:Array<Complex>, f:Int, n:Int, step:Int, inverse:Bool):Void
{
if (n == 1)
@@ -77,6 +81,7 @@ class FFT
}
// Naive O(n^2) DFT, used for testing purposes.
static function dft(ts:Array<Complex>, ?inverse:Bool):Array<Complex>
{
if (inverse == null) inverse = false;
@@ -96,8 +101,8 @@ class FFT
}
/**
Finds the power of 2 that is equal to or greater than the given natural.
**/
* Finds the power of 2 that is equal to or greater than the given natural.
*/
static function nextPow2(x:Int):Int
{
if (x < 2) return 1;
@@ -110,6 +115,7 @@ class FFT
}
// testing, but also acts like an example
static function main()
{
// sampling and buffer parameters
@@ -119,15 +125,21 @@ class FFT
// build a time signal as a sum of sinusoids
final freqs = [5919.911];
final ts = [for (n in 0...N) freqs.map(f -> Math.sin(2 * Math.PI * f * n / Fs)).sum()];
final ts = [
for (n in 0...N) freqs.map(f -> Math.sin(2 * Math.PI * f * n / Fs)).sum()
];
// get positive spectrum and use its symmetry to reconstruct negative domain
final fs_pos = rfft(ts);
final fs_fft = new OffsetArray([for (k in -(halfN - 1)...0) fs_pos[-k].conj()].concat(fs_pos), -(halfN - 1));
final fs_fft = new OffsetArray([
for (k in -(halfN - 1)...0) fs_pos[-k].conj()
].concat(fs_pos), -(halfN - 1));
// double-check with naive DFT
final fs_dft = new OffsetArray(dft(ts.map(Complex.fromReal)).circShift(halfN - 1), -(halfN - 1));
final fs_err = [for (k in -(halfN - 1)...halfN) fs_fft[k] - fs_dft[k]];
final fs_err = [
for (k in -(halfN - 1)...halfN) fs_fft[k] - fs_dft[k]
];
final max_fs_err = fs_err.map(z -> z.magnitude).max();
if (max_fs_err > 1e-6) haxe.Log.trace('FT Error: ${max_fs_err}', null);
// else for (k => s in fs_fft) haxe.Log.trace('${k * Fs / N};${s.scale(1 / Fs).magnitude}', null);
@@ -143,14 +155,18 @@ class FFT
}
else
{
final freqs_err = [for (i in 0...freqs.length) freqis[i] - freqs[i]];
final freqs_err = [
for (i in 0...freqs.length) freqis[i] - freqs[i]
];
final max_freqs_err = freqs_err.map(Math.abs).max();
if (max_freqs_err > Fs / N) trace('Frequency Errors: ${freqs_err}');
}
// recover time signal from the frequency domain
final ts_ifft = ifft(fs_fft.array.circShift(-(halfN - 1)).map(z -> z.scale(1 / Fs)));
final ts_err = [for (n in 0...N) ts_ifft[n].scale(Fs).real - ts[n]];
final ts_err = [
for (n in 0...N) ts_ifft[n].scale(Fs).real - ts[n]
];
final max_ts_err = ts_err.map(Math.abs).max();
if (max_ts_err > 1e-6) haxe.Log.trace('IFT Error: ${max_ts_err}', null);
// else for (n in 0...ts_ifft.length) haxe.Log.trace('${n / Fs};${ts_ifft[n].scale(Fs).real}', null);
@@ -1,12 +1,11 @@
package funkin.audio.visualize.dsp;
/**
A view into an Array with an indexing offset.
Usages include 1-indexed sequences or zero-centered buffers with negative indexing.
**/
@:forward(array, offset)
@:nullSafety
* A view into an Array with an indexing offset.
*
* Usages include 1-indexed sequences or zero-centered buffers with negative indexing.
*/
@:forward(array, offset) @:nullSafety
abstract OffsetArray<T>({
final array:Array<T>;
final offset:Int;
@@ -25,32 +24,46 @@ abstract OffsetArray<T>({
public inline function set(index:Int, value:T):Void this.array[index - this.offset] = value;
/**
Iterates through items in their original order while providing the altered indexes as keys.
**/
* Iterates through items in their original order while providing the altered indexes as keys.
*/
public inline function keyValueIterator():KeyValueIterator<Int, T> return new OffsetArrayIterator(this.array, this.offset);
@:from
static inline function fromArray<T>(array:Array<T>) return new OffsetArray(array, 0);
static inline function fromArray<T>(array:Array<T>):OffsetArray<T>
{
return new OffsetArray(array, 0);
}
@:to
inline function toArray() return this.array;
inline function toArray():Array<T>
{
return this.array;
}
/**
Makes a shifted version of the given `array`, where elements are in the
same order but shifted by `n` positions (to the right if positive and to
the left if negative) in **circular** fashion (no elements discarded).
**/
* Makes a shifted version of the given `array`, where elements are in the
* same order but shifted by `n` positions (to the right if positive and to
* the left if negative) in **circular** fashion (no elements discarded).
*
* @param array The array to shift
* @param n The number of positions to shift
* @return The resulting offset array
*/
public static function circShift<T>(array:Array<T>, n:Int):Array<T>
{
if (n < 0) return circShift(array, array.length + n);
var shifted = new Array<T>();
var shifted = [];
n = n % array.length;
for (i in array.length - n...array.length)
{
shifted.push(array[i]);
}
for (i in 0...array.length - n)
{
shifted.push(array[i]);
}
return shifted;
}
@@ -72,9 +85,12 @@ private class OffsetArrayIterator<T>
public inline function next():
{key:Int, value:T}
{
final i = this.enumeration++;
var i = this.enumeration++;
return {key: i + this.offset, value: this.array[i]};
}
public inline function hasNext():Bool return this.enumeration < this.array.length;
public inline function hasNext():Bool
{
return this.enumeration < this.array.length;
}
}
+27 -25
View File
@@ -3,14 +3,14 @@ package funkin.audio.visualize.dsp;
using Lambda;
/**
Signal processing miscellaneous utilities.
**/
* Signal processing miscellaneous utilities.
*/
@:nullSafety
class Signal
{
/**
Returns a smoothed version of the input array using a moving average.
**/
* Returns a smoothed version of the input array using a moving average.
*/
public static function smooth(y:Array<Float>, n:Int):Null<Array<Float>>
{
if (n <= 0)
@@ -35,11 +35,11 @@ class Signal
}
/**
Finds indexes of peaks in the order they appear in the input sequence.
@param threshold Minimal peak height wrt. its neighbours, defaults to 0.
@param minHeight Minimal peak height wrt. the whole input, defaults to global minimum.
**/
* Finds indexes of peaks in the order they appear in the input sequence.
*
* @param threshold Minimal peak height wrt. its neighbours, defaults to 0.
* @param minHeight Minimal peak height wrt. the whole input, defaults to global minimum.
*/
public static function findPeaks(y:Array<Float>, ?threshold:Float, ?minHeight:Float):Array<Int>
{
threshold = threshold == null ? 0.0 : Math.abs(threshold);
@@ -47,7 +47,9 @@ class Signal
var peaks = new Array<Int>();
final dy = [for (i in 1...y.length) y[i] - y[i - 1]];
final dy = [
for (i in 1...y.length) y[i] - y[i - 1]
];
for (i in 1...dy.length)
{
// peak: function growth positive to its left and negative to its right
@@ -60,11 +62,11 @@ class Signal
return peaks;
}
/**
Returns the sum of all the elements of a given array.
This function tries to minimize floating-point precision errors.
**/
/***
* Returns the sum of all the elements of a given array.
*
* This function tries to minimize floating-point precision errors.
*/
public static function sum(array:Array<Float>):Float
{
// Neumaier's "improved Kahan-Babuska algorithm":
@@ -84,27 +86,27 @@ class Signal
}
/**
Returns the average value of an array.
**/
* Returns the average value of an array.
*/
public static function mean(y:Array<Float>):Float return sum(y) / y.length;
/**
Returns the global maximum.
**/
* Returns the global maximum.
*/
public static function max(y:Array<Float>):Float return y.fold(Math.max, y[0]);
/**
Returns the global maximum's index.
**/
* Returns the global maximum's index.
*/
public static function maxi(y:Array<Float>):Int return y.foldi((yi, m, i) -> yi > y[m] ? i : m, 0);
/**
Returns the global minimum.
**/
* Returns the global minimum.
*/
public static function min(y:Array<Float>):Float return y.fold(Math.min, y[0]);
/**
Returns the global minimum's index.
**/
* Returns the global minimum's index.
*/
public static function mini(y:Array<Float>):Int return y.foldi((yi, m, i) -> yi < y[m] ? i : m, 0);
}
+2 -2
View File
@@ -181,7 +181,7 @@ class WaveformData
}
/**
* Create a new WaveformData whose data represents the two waveforms overlayed.
* Create a new WaveformData whose data represents the two waveforms overlaid.
*/
public function merge(that:WaveformData):WaveformData
{
@@ -217,7 +217,7 @@ class WaveformData
/**
* Create a new WaveformData whose parameters match the current object.
*/
public function clone(?newData:Array<Int> = null):WaveformData
public function clone(?newData:Array<Int>):WaveformData
{
if (newData == null)
{
@@ -3,10 +3,13 @@ package funkin.audio.waveform;
@:nullSafety
class WaveformDataParser
{
@:native('int16_max')
static final INT16_MAX:Int = 32767;
@:native('int16_min')
static final INT16_MIN:Int = -32768;
@:native('int8_max')
static final INT8_MAX:Int = 127;
@:native('int8_min')
static final INT8_MIN:Int = -128;
public static function interpretFlxSound(sound:Null<flixel.sound.FlxSound>):Null<WaveformData>
@@ -78,7 +81,9 @@ class WaveformDataParser
{
for (channelIndex in 0...channels)
{
var sampleValue:Int = soundData[sampleIndex * channels + channelIndex];
var sampleValue:Int = soundData[
sampleIndex * channels + channelIndex
];
if (sampleValue < minValues[channelIndex]) minValues[channelIndex] = sampleValue;
if (sampleValue > maxValues[channelIndex]) maxValues[channelIndex] = sampleValue;
@@ -90,7 +95,9 @@ class WaveformDataParser
for (channelIndex in 0...channels)
{
outputData[baseIndex + channelIndex * 2] = minValues[channelIndex];
outputData[baseIndex + channelIndex * 2 + 1] = maxValues[channelIndex];
outputData[
baseIndex + channelIndex * 2 + 1
] = maxValues[channelIndex];
}
}
@@ -125,6 +132,8 @@ class WaveformDataParser
trace('[WAVEFORM] Failed to parse waveform data: ${id}');
for (error in errors)
{
funkin.data.DataError.printError(error);
}
}
}

Some files were not shown because too many files have changed in this diff Show More