From ce97a002cb01fee2e86a9a96075665d499e671aa Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Tue, 7 Nov 2023 04:04:22 -0500
Subject: [PATCH 1/4] Reorganize a whole bunch of classes and perform syntax
 cleanup.

---
 assets                                        |   2 +-
 source/Main.hx                                |   2 +-
 source/funkin/Controls.hx                     | 177 ++++++------
 source/funkin/CoolUtil.hx                     | 129 ---------
 source/funkin/DialogueBox.hx                  | 265 ------------------
 source/funkin/FlxSwf.hx                       |  43 ---
 source/funkin/Highscore.hx                    |   3 +
 source/funkin/InitState.hx                    |  11 +-
 source/funkin/MenuCharacter.hx                |  42 ---
 source/funkin/NoteSplash.hx                   |  65 -----
 source/funkin/Options.hx                      |   6 -
 source/funkin/Paths.hx                        |   3 +
 source/funkin/PlayerSettings.hx               |   5 +-
 source/funkin/Preferences.hx                  |   2 +-
 source/funkin/TankCutscene.hx                 |  27 --
 source/funkin/{ => api/discord}/Discord.hx    |   2 +-
 source/funkin/api/newgrounds/NGUtil.hx        |  12 -
 source/funkin/{ => api/newgrounds}/NGio.hx    |   2 +-
 source/funkin/api/newgrounds/README.md        |   2 +-
 .../{audiovis => audio/visualize}/ABot.hx     |   2 +-
 .../{audiovis => audio/visualize}/ABotVis.hx  |   7 +-
 .../audio/visualize/PolygonSpectogram.hx      |   2 +-
 .../visualize}/SpectogramSprite.hx            |   6 +-
 .../{audiovis => audio/visualize}/VisShit.hx  |   7 +-
 .../visualize}/dsp/Complex.hx                 |   2 +-
 .../{audiovis => audio/visualize}/dsp/FFT.hx  |   8 +-
 .../visualize}/dsp/OffsetArray.hx             |   2 +-
 .../visualize}/dsp/Signal.hx                  |   2 +-
 .../shaders}/AngleMask.hx                     |   2 +-
 .../shaders}/BlendModeEffect.hx               |   2 +-
 .../shaders}/BlendModesShader.hx              |   2 +-
 .../shaders}/ColorSwap.hx                     |   2 +-
 .../shaders}/GaussianBlurShader.hx            |   2 +-
 .../shaders}/Grayscale.hx                     |   2 +-
 .../shaders}/HSVShader.hx                     |   2 +-
 .../shaders}/LeftMaskShader.hx                |   2 +-
 .../shaders}/MultiplyShader.hx                |   2 +-
 .../shaders}/OverlayBlend.hx                  |   2 +-
 .../shaders}/PureColor.hx                     |   2 +-
 .../shaders}/ScreenWipeShader.hx              |   2 +-
 .../shaders}/StrokeShader.hx                  |   2 +-
 .../shaders}/TitleOutline.hx                  |   2 +-
 .../shaders}/WaveShader.hx                    |   2 +-
 .../shaders}/WiggleEffectRuntime.hx           |   2 +-
 source/funkin/input/TurboKeyHandler.hx        |   3 +-
 .../modding/base/ScriptedMusicBeatState.hx    |   2 +-
 .../modding/base/ScriptedMusicBeatSubState.hx |   2 +-
 source/funkin/play/Fighter.hx                 |  68 -----
 source/funkin/play/GameOverSubState.hx        |   2 +
 source/funkin/{ => play}/GitarooPause.hx      |   4 +-
 source/funkin/{ => play}/PauseSubState.hx     |   8 +-
 source/funkin/play/PlayState.hx               |  16 +-
 source/funkin/play/ResultState.hx             |   6 +-
 source/funkin/play/character/BaseCharacter.hx |   2 +-
 .../{ => play/components}/ComboMilestone.hx   |   2 +-
 .../play/{ => components}/HealthIcon.hx       |   9 +-
 .../{ui => play/components}/PopUpStuff.hx     |   2 +-
 .../{ui => play/components}/TallyCounter.hx   |   4 +-
 .../dialogue/ConversationDebugState.hx        |   1 +
 source/funkin/play/notes/Strumline.hx         |   2 +-
 source/funkin/play/notes/SustainTrail.hx      |   2 +-
 source/funkin/play/stage/Bopper.hx            |   2 +-
 source/funkin/{ => ui}/Alphabet.hx            |   8 +-
 source/funkin/ui/AtlasMenuList.hx             |   2 +-
 source/funkin/{ => ui}/MenuItem.hx            |   5 +-
 source/funkin/ui/MenuList.hx                  |   6 +-
 source/funkin/{ => ui}/MusicBeatState.hx      |   3 +-
 source/funkin/{ => ui}/MusicBeatSubState.hx   |   3 +-
 source/funkin/{ => ui}/SwagCamera.hx          |  11 +-
 source/funkin/ui/debug/DebugMenuSubState.hx   |   7 +-
 source/funkin/{ => ui/debug}/MemoryCounter.hx |   2 +-
 .../anim}/DebugBoundingState.hx               |   9 +-
 .../anim}/FlxAnimateTest.hx                   |   3 +-
 .../ui/debug/charting/ChartEditorState.hx     |   3 +-
 .../ui/{ => debug/latency}/CoolStatsGraph.hx  |   2 +-
 .../{ => ui/debug/latency}/LatencyState.hx    |   5 +-
 .../stage}/CharStage.hx                       |   2 +-
 .../stage}/SprStage.hx                        |   2 +-
 .../stage}/StageBuilderState.hx               |   8 +-
 .../stage}/StageEditorCommand.hx              |   4 +-
 .../stage}/StageOffsetSubState.hx             |  13 +-
 .../stage}/StagetoolBar.hx                    |  10 +-
 .../freeplay}/BGScrollingText.hx              |   2 +-
 .../freeplay}/CapsuleText.hx                  |   4 +-
 .../freeplay}/DJBoyfriend.hx                  |   2 +-
 .../freeplay}/DifficultyStars.hx              |   4 +-
 .../freeplay}/FreeplayFlames.hx               |   2 +-
 .../freeplay}/FreeplayScore.hx                |   2 +-
 .../funkin/{ => ui/freeplay}/FreeplayState.hx |  38 +--
 .../freeplay}/LetterSort.hx                   |   2 +-
 .../freeplay}/SongMenuItem.hx                 |  15 +-
 source/funkin/ui/haxeui/HaxeUIState.hx        |   1 +
 source/funkin/ui/haxeui/HaxeUISubState.hx     |   3 +
 source/funkin/ui/haxeui/components/README.md  |   2 +-
 .../funkin/{ => ui/mainmenu}/MainMenuState.hx |   8 +-
 .../{ => ui/options}/ButtonRemapSubstate.hx   |   2 +-
 source/funkin/ui/{ => options}/ColorsMenu.hx  |   4 +-
 .../funkin/ui/{ => options}/ControlsMenu.hx   |   7 +-
 source/funkin/ui/{ => options}/ModMenu.hx     |   4 +-
 .../funkin/ui/{ => options}/OptionsState.hx   |   4 +-
 .../ui/{ => options}/PreferencesMenu.hx       |   4 +-
 source/funkin/ui/story/LevelTitle.hx          |   4 +-
 source/funkin/ui/story/StoryMenuState.hx      |   8 +-
 source/funkin/ui/title/AttractState.hx        |   1 +
 source/funkin/ui/title/FlxSpriteOverlay.hx    |   2 +-
 .../funkin/{ => ui/title}/OutdatedSubState.hx |   3 +-
 source/funkin/ui/title/TitleState.hx          |  17 +-
 .../{ => ui/transition}/LoadingState.hx       |  25 +-
 .../ui/{ => transition}/StickerSubState.hx    |   5 +-
 source/funkin/util/BezierUtil.hx              |   3 +
 source/funkin/util/DateUtil.hx                |   3 +
 source/funkin/util/FlxGamepadUtil.hx          |   3 +
 .../{InputFormatter.hx => util/InputUtil.hx}  |  11 +-
 source/funkin/util/MathUtil.hx                |  31 ++
 source/funkin/util/MouseUtil.hx               |  45 +++
 source/funkin/util/PlatformUtil.hx            |   3 +
 source/funkin/util/SerializerUtil.hx          |   4 +-
 source/funkin/util/SortUtil.hx                |   2 +-
 source/funkin/util/VersionUtil.hx             |   2 +
 source/funkin/util/WindowUtil.hx              |   3 +
 120 files changed, 462 insertions(+), 938 deletions(-)
 delete mode 100644 source/funkin/CoolUtil.hx
 delete mode 100644 source/funkin/DialogueBox.hx
 delete mode 100644 source/funkin/FlxSwf.hx
 delete mode 100644 source/funkin/MenuCharacter.hx
 delete mode 100644 source/funkin/NoteSplash.hx
 delete mode 100644 source/funkin/Options.hx
 delete mode 100644 source/funkin/TankCutscene.hx
 rename source/funkin/{ => api/discord}/Discord.hx (98%)
 rename source/funkin/{ => api/newgrounds}/NGio.hx (99%)
 rename source/funkin/{audiovis => audio/visualize}/ABot.hx (85%)
 rename source/funkin/{audiovis => audio/visualize}/ABotVis.hx (96%)
 rename source/funkin/{audiovis => audio/visualize}/SpectogramSprite.hx (98%)
 rename source/funkin/{audiovis => audio/visualize}/VisShit.hx (93%)
 rename source/funkin/{audiovis => audio/visualize}/dsp/Complex.hx (98%)
 rename source/funkin/{audiovis => audio/visualize}/dsp/FFT.hx (97%)
 rename source/funkin/{audiovis => audio/visualize}/dsp/OffsetArray.hx (98%)
 rename source/funkin/{audiovis => audio/visualize}/dsp/Signal.hx (98%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/AngleMask.hx (96%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/BlendModeEffect.hx (95%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/BlendModesShader.hx (92%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/ColorSwap.hx (99%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/GaussianBlurShader.hx (93%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/Grayscale.hx (92%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/HSVShader.hx (96%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/LeftMaskShader.hx (97%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/MultiplyShader.hx (94%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/OverlayBlend.hx (97%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/PureColor.hx (96%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/ScreenWipeShader.hx (98%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/StrokeShader.hx (98%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/TitleOutline.hx (98%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/WaveShader.hx (90%)
 rename source/funkin/{shaderslmfao => graphics/shaders}/WiggleEffectRuntime.hx (98%)
 delete mode 100644 source/funkin/play/Fighter.hx
 rename source/funkin/{ => play}/GitarooPause.hx (96%)
 rename source/funkin/{ => play}/PauseSubState.hx (97%)
 rename source/funkin/{ => play/components}/ComboMilestone.hx (98%)
 rename source/funkin/play/{ => components}/HealthIcon.hx (98%)
 rename source/funkin/{ui => play/components}/PopUpStuff.hx (99%)
 rename source/funkin/{ui => play/components}/TallyCounter.hx (94%)
 rename source/funkin/{ => ui}/Alphabet.hx (97%)
 rename source/funkin/{ => ui}/MenuItem.hx (93%)
 rename source/funkin/{ => ui}/MusicBeatState.hx (98%)
 rename source/funkin/{ => ui}/MusicBeatSubState.hx (98%)
 rename source/funkin/{ => ui}/SwagCamera.hx (87%)
 rename source/funkin/{ => ui/debug}/MemoryCounter.hx (97%)
 rename source/funkin/ui/{animDebugShit => debug/anim}/DebugBoundingState.hx (98%)
 rename source/funkin/ui/{animDebugShit => debug/anim}/FlxAnimateTest.hx (94%)
 rename source/funkin/ui/{ => debug/latency}/CoolStatsGraph.hx (99%)
 rename source/funkin/{ => ui/debug/latency}/LatencyState.hx (98%)
 rename source/funkin/ui/{stageBuildShit => debug/stage}/CharStage.hx (81%)
 rename source/funkin/ui/{stageBuildShit => debug/stage}/SprStage.hx (97%)
 rename source/funkin/ui/{stageBuildShit => debug/stage}/StageBuilderState.hx (98%)
 rename source/funkin/ui/{stageBuildShit => debug/stage}/StageEditorCommand.hx (95%)
 rename source/funkin/ui/{stageBuildShit => debug/stage}/StageOffsetSubState.hx (97%)
 rename source/funkin/ui/{stageBuildShit => debug/stage}/StagetoolBar.hx (67%)
 rename source/funkin/{freeplayStuff => ui/freeplay}/BGScrollingText.hx (98%)
 rename source/funkin/{freeplayStuff => ui/freeplay}/CapsuleText.hx (93%)
 rename source/funkin/{freeplayStuff => ui/freeplay}/DJBoyfriend.hx (99%)
 rename source/funkin/{freeplayStuff => ui/freeplay}/DifficultyStars.hx (96%)
 rename source/funkin/{freeplayStuff => ui/freeplay}/FreeplayFlames.hx (98%)
 rename source/funkin/{freeplayStuff => ui/freeplay}/FreeplayScore.hx (98%)
 rename source/funkin/{ => ui/freeplay}/FreeplayState.hx (97%)
 rename source/funkin/{freeplayStuff => ui/freeplay}/LetterSort.hx (99%)
 rename source/funkin/{freeplayStuff => ui/freeplay}/SongMenuItem.hx (96%)
 rename source/funkin/{ => ui/mainmenu}/MainMenuState.hx (97%)
 rename source/funkin/{ => ui/options}/ButtonRemapSubstate.hx (82%)
 rename source/funkin/ui/{ => options}/ColorsMenu.hx (96%)
 rename source/funkin/ui/{ => options}/ControlsMenu.hx (98%)
 rename source/funkin/ui/{ => options}/ModMenu.hx (97%)
 rename source/funkin/ui/{ => options}/OptionsState.hx (98%)
 rename source/funkin/ui/{ => options}/PreferencesMenu.hx (98%)
 rename source/funkin/{ => ui/title}/OutdatedSubState.hx (95%)
 rename source/funkin/{ => ui/transition}/LoadingState.hx (89%)
 rename source/funkin/ui/{ => transition}/StickerSubState.hx (98%)
 rename source/funkin/{InputFormatter.hx => util/InputUtil.hx} (96%)
 create mode 100644 source/funkin/util/MathUtil.hx
 create mode 100644 source/funkin/util/MouseUtil.hx

diff --git a/assets b/assets
index e634c8f50..53f63f549 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit e634c8f50c34845097283e0f411e1f89409e1498
+Subproject commit 53f63f549f34b9c03d0e2d7149dde551a61acb26
diff --git a/source/Main.hx b/source/Main.hx
index dffe666b7..ffc3edd76 100644
--- a/source/Main.hx
+++ b/source/Main.hx
@@ -3,7 +3,7 @@ package;
 import flixel.FlxGame;
 import flixel.FlxState;
 import funkin.util.logging.CrashHandler;
-import funkin.MemoryCounter;
+import funkin.ui.debug.MemoryCounter;
 import funkin.save.Save;
 import haxe.ui.Toolkit;
 import openfl.display.FPS;
diff --git a/source/funkin/Controls.hx b/source/funkin/Controls.hx
index 9372c4dc6..9f2dcff49 100644
--- a/source/funkin/Controls.hx
+++ b/source/funkin/Controls.hx
@@ -23,96 +23,14 @@ import flixel.util.FlxTimer;
 import lime.ui.Haptic;
 
 /**
- * Since, in many cases multiple actions should use similar keys, we don't want the
- * rebinding UI to list every action. ActionBinders are what the user percieves as
- * an input so, for instance, they can't set jump-press and jump-release to different keys.
- */
-enum Control
-{
-  // List notes in order from left to right on gameplay screen.
-  NOTE_LEFT;
-  NOTE_DOWN;
-  NOTE_UP;
-  NOTE_RIGHT;
-  UI_UP;
-  UI_LEFT;
-  UI_RIGHT;
-  UI_DOWN;
-  RESET;
-  ACCEPT;
-  BACK;
-  PAUSE;
-  CUTSCENE_ADVANCE;
-  CUTSCENE_SKIP;
-  VOLUME_UP;
-  VOLUME_DOWN;
-  VOLUME_MUTE;
-  #if CAN_CHEAT
-  CHEAT;
-  #end
-}
-
-enum
-abstract Action(String) to String from String
-{
-  var UI_UP = "ui_up";
-  var UI_LEFT = "ui_left";
-  var UI_RIGHT = "ui_right";
-  var UI_DOWN = "ui_down";
-  var UI_UP_P = "ui_up-press";
-  var UI_LEFT_P = "ui_left-press";
-  var UI_RIGHT_P = "ui_right-press";
-  var UI_DOWN_P = "ui_down-press";
-  var UI_UP_R = "ui_up-release";
-  var UI_LEFT_R = "ui_left-release";
-  var UI_RIGHT_R = "ui_right-release";
-  var UI_DOWN_R = "ui_down-release";
-  var NOTE_UP = "note_up";
-  var NOTE_LEFT = "note_left";
-  var NOTE_RIGHT = "note_right";
-  var NOTE_DOWN = "note_down";
-  var NOTE_UP_P = "note_up-press";
-  var NOTE_LEFT_P = "note_left-press";
-  var NOTE_RIGHT_P = "note_right-press";
-  var NOTE_DOWN_P = "note_down-press";
-  var NOTE_UP_R = "note_up-release";
-  var NOTE_LEFT_R = "note_left-release";
-  var NOTE_RIGHT_R = "note_right-release";
-  var NOTE_DOWN_R = "note_down-release";
-  var ACCEPT = "accept";
-  var BACK = "back";
-  var PAUSE = "pause";
-  var CUTSCENE_ADVANCE = "cutscene_advance";
-  var CUTSCENE_SKIP = "cutscene_skip";
-  var VOLUME_UP = "volume_up";
-  var VOLUME_DOWN = "volume_down";
-  var VOLUME_MUTE = "volume_mute";
-  var RESET = "reset";
-  #if CAN_CHEAT
-  var CHEAT = "cheat";
-  #end
-}
-
-enum Device
-{
-  Keys;
-  Gamepad(id:Int);
-}
-
-enum KeyboardScheme
-{
-  Solo;
-  Duo(first:Bool);
-  None;
-  Custom;
-}
-
-/**
- * A list of actions that a player would invoke via some input device.
- * Uses FlxActions to funnel various inputs to a single action.
+ * A core class which handles receiving player input and interpreting it into game actions.
  */
 class Controls extends FlxActionSet
 {
+  /**
+   * A list of actions that a player would invoke via some input device.
+   * Uses FlxActions to funnel various inputs to a single action.
+   */
   var _ui_up = new FlxActionDigital(Action.UI_UP);
   var _ui_left = new FlxActionDigital(Action.UI_LEFT);
   var _ui_right = new FlxActionDigital(Action.UI_RIGHT);
@@ -1241,3 +1159,88 @@ class FlxActionInputDigitalAndroid extends FlxActionInputDigital
   }
 }
 #end
+
+/**
+ * Since, in many cases multiple actions should use similar keys, we don't want the
+ * rebinding UI to list every action. ActionBinders are what the user percieves as
+ * an input so, for instance, they can't set jump-press and jump-release to different keys.
+ */
+enum Control
+{
+  // List notes in order from left to right on gameplay screen.
+  NOTE_LEFT;
+  NOTE_DOWN;
+  NOTE_UP;
+  NOTE_RIGHT;
+  UI_UP;
+  UI_LEFT;
+  UI_RIGHT;
+  UI_DOWN;
+  RESET;
+  ACCEPT;
+  BACK;
+  PAUSE;
+  CUTSCENE_ADVANCE;
+  CUTSCENE_SKIP;
+  VOLUME_UP;
+  VOLUME_DOWN;
+  VOLUME_MUTE;
+  #if CAN_CHEAT
+  CHEAT;
+  #end
+}
+
+enum
+abstract Action(String) to String from String
+{
+  var UI_UP = "ui_up";
+  var UI_LEFT = "ui_left";
+  var UI_RIGHT = "ui_right";
+  var UI_DOWN = "ui_down";
+  var UI_UP_P = "ui_up-press";
+  var UI_LEFT_P = "ui_left-press";
+  var UI_RIGHT_P = "ui_right-press";
+  var UI_DOWN_P = "ui_down-press";
+  var UI_UP_R = "ui_up-release";
+  var UI_LEFT_R = "ui_left-release";
+  var UI_RIGHT_R = "ui_right-release";
+  var UI_DOWN_R = "ui_down-release";
+  var NOTE_UP = "note_up";
+  var NOTE_LEFT = "note_left";
+  var NOTE_RIGHT = "note_right";
+  var NOTE_DOWN = "note_down";
+  var NOTE_UP_P = "note_up-press";
+  var NOTE_LEFT_P = "note_left-press";
+  var NOTE_RIGHT_P = "note_right-press";
+  var NOTE_DOWN_P = "note_down-press";
+  var NOTE_UP_R = "note_up-release";
+  var NOTE_LEFT_R = "note_left-release";
+  var NOTE_RIGHT_R = "note_right-release";
+  var NOTE_DOWN_R = "note_down-release";
+  var ACCEPT = "accept";
+  var BACK = "back";
+  var PAUSE = "pause";
+  var CUTSCENE_ADVANCE = "cutscene_advance";
+  var CUTSCENE_SKIP = "cutscene_skip";
+  var VOLUME_UP = "volume_up";
+  var VOLUME_DOWN = "volume_down";
+  var VOLUME_MUTE = "volume_mute";
+  var RESET = "reset";
+  #if CAN_CHEAT
+  var CHEAT = "cheat";
+  #end
+}
+
+enum Device
+{
+  Keys;
+  Gamepad(id:Int);
+}
+
+enum KeyboardScheme
+{
+  Solo;
+  Duo(first:Bool);
+  None;
+  Custom;
+}
diff --git a/source/funkin/CoolUtil.hx b/source/funkin/CoolUtil.hx
deleted file mode 100644
index d07bb4e22..000000000
--- a/source/funkin/CoolUtil.hx
+++ /dev/null
@@ -1,129 +0,0 @@
-package funkin;
-
-import flixel.FlxSprite;
-import flixel.FlxState;
-import flixel.graphics.FlxGraphic;
-import flixel.graphics.frames.FlxAtlasFrames;
-import flixel.math.FlxMath;
-import flixel.math.FlxPoint;
-import flixel.math.FlxRect;
-import flixel.system.FlxAssets.FlxGraphicAsset;
-import flixel.tweens.FlxEase;
-import flixel.tweens.FlxTween;
-import funkin.play.PlayState;
-import funkin.shaderslmfao.ScreenWipeShader;
-import haxe.format.JsonParser;
-import lime.math.Rectangle;
-import lime.utils.Assets;
-import openfl.filters.ShaderFilter;
-
-class CoolUtil
-{
-  public static function coolBaseLog(base:Float, fin:Float):Float
-  {
-    return Math.log(fin) / Math.log(base);
-  }
-
-  public static function coolTextFile(path:String):Array<String>
-  {
-    var daList:Array<String> = [];
-
-    var swagArray:Array<String> = Assets.getText(path).trim().split('\n');
-
-    for (item in swagArray)
-    {
-      // comment support in the quick lil text formats??? using //
-      if (!item.trim().startsWith('//')) daList.push(item);
-    }
-
-    for (i in 0...daList.length)
-    {
-      daList[i] = daList[i].trim();
-    }
-
-    return daList;
-  }
-
-  public static function numberArray(max:Int, ?min = 0):Array<Int>
-  {
-    var dumbArray:Array<Int> = [];
-    for (i in min...max)
-    {
-      dumbArray.push(i);
-    }
-    return dumbArray;
-  }
-
-  static var oldCamPos:FlxPoint = new FlxPoint();
-  static var oldMousePos:FlxPoint = new FlxPoint();
-
-  /**
-   * Used to be for general camera middle click dragging, now generalized for any click and drag type shit!
-   * Listen I don't make the rules here
-   * @param target what you want to be dragged, defaults to CAMERA SCROLL
-   * @param jusPres the "justPressed", should be a button of some sort
-   * @param pressed the "pressed", which should be the same button as `jusPres`
-   */
-  public static function mouseCamDrag(?target:FlxPoint, ?jusPres:Bool, ?pressed:Bool):Void
-  {
-    if (target == null) target = FlxG.camera.scroll;
-
-    if (jusPres == null) jusPres = FlxG.mouse.justPressedMiddle;
-
-    if (pressed == null) pressed = FlxG.mouse.pressedMiddle;
-
-    if (jusPres)
-    {
-      oldCamPos.set(target.x, target.y);
-      oldMousePos.set(FlxG.mouse.screenX, FlxG.mouse.screenY);
-    }
-
-    if (pressed)
-    {
-      target.x = oldCamPos.x - (FlxG.mouse.screenX - oldMousePos.x);
-      target.y = oldCamPos.y - (FlxG.mouse.screenY - oldMousePos.y);
-    }
-  }
-
-  public static function mouseWheelZoom():Void
-  {
-    if (FlxG.mouse.wheel != 0) FlxG.camera.zoom += FlxG.mouse.wheel * (0.1 * FlxG.camera.zoom);
-  }
-
-  /**
-    Lerps camera, but accountsfor framerate shit?
-    Right now it's simply for use to change the followLerp variable of a camera during update
-    TODO LATER MAYBE:
-      Actually make and modify the scroll and lerp shit in it's own function
-      instead of solely relying on changing the lerp on the fly
-   */
-  public static function camLerpShit(lerp:Float):Float
-  {
-    return lerp * (FlxG.elapsed / (1 / 60));
-  }
-
-  public static function coolSwitchState(state:FlxState, transitionTex:String = "shaderTransitionStuff/coolDots", time:Float = 2)
-  {
-    var screenShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("shaderTransitionStuff/coolDots"));
-    var screenWipeShit:ScreenWipeShader = new ScreenWipeShader();
-
-    screenWipeShit.funnyShit.input = screenShit.pixels;
-    FlxTween.tween(screenWipeShit, {daAlphaShit: 1}, time,
-      {
-        ease: FlxEase.quadInOut,
-        onComplete: function(twn) {
-          screenShit.destroy();
-          FlxG.switchState(new MainMenuState());
-        }
-      });
-    FlxG.camera.setFilters([new ShaderFilter(screenWipeShit)]);
-  }
-
-  /*
-   * frame dependant lerp kinda lol
-   */
-  public static function coolLerp(base:Float, target:Float, ratio:Float):Float
-  {
-    return base + camLerpShit(ratio) * (target - base);
-  }
-}
diff --git a/source/funkin/DialogueBox.hx b/source/funkin/DialogueBox.hx
deleted file mode 100644
index 68d330dbe..000000000
--- a/source/funkin/DialogueBox.hx
+++ /dev/null
@@ -1,265 +0,0 @@
-package funkin;
-
-import flixel.FlxSprite;
-import flixel.addons.text.FlxTypeText;
-import flixel.group.FlxSpriteGroup;
-import flixel.text.FlxText;
-import flixel.util.FlxColor;
-import flixel.util.FlxTimer;
-import funkin.play.PlayState;
-
-/**
- * Handles dialog boxes and text, like the ones in Week 6.
- */
-class DialogueBox extends FlxSpriteGroup
-{
-  var box:FlxSprite;
-
-  var curCharacter:String = '';
-
-  var dialogue:Alphabet;
-  var dialogueList:Array<String> = [];
-
-  // SECOND DIALOGUE FOR THE PIXEL SHIT INSTEAD???
-  var swagDialogue:FlxTypeText;
-
-  var dropText:FlxText;
-
-  public var finishThing:Void->Void;
-
-  var portraitLeft:FlxSprite;
-  var portraitRight:FlxSprite;
-
-  var handSelect:FlxSprite;
-  var bgFade:FlxSprite;
-
-  public function new(talkingRight:Bool = true, ?dialogueList:Array<String>)
-  {
-    super();
-
-    switch (PlayState.instance.currentSong.id.toLowerCase())
-    {
-      case 'senpai':
-        FlxG.sound.playMusic(Paths.music('Lunchbox'), 0);
-        FlxG.sound.music.fadeIn(1, 0, 0.8);
-      case 'thorns':
-        FlxG.sound.playMusic(Paths.music('LunchboxScary'), 0);
-        FlxG.sound.music.fadeIn(1, 0, 0.8);
-    }
-
-    bgFade = new FlxSprite(-200, -200).makeGraphic(Std.int(FlxG.width * 1.3), Std.int(FlxG.height * 1.3), 0xFFB3DFD8);
-    bgFade.scrollFactor.set();
-    bgFade.alpha = 0;
-    add(bgFade);
-
-    new FlxTimer().start(0.83, function(tmr:FlxTimer) {
-      bgFade.alpha += (1 / 5) * 0.7;
-      if (bgFade.alpha > 0.7) bgFade.alpha = 0.7;
-    }, 5);
-
-    portraitLeft = new FlxSprite(-20, 40);
-    portraitLeft.frames = Paths.getSparrowAtlas('weeb/senpaiPortrait');
-    portraitLeft.animation.addByPrefix('enter', 'Senpai Portrait Enter', 24, false);
-    portraitLeft.setGraphicSize(Std.int(portraitLeft.width * Constants.PIXEL_ART_SCALE * 0.9));
-    portraitLeft.updateHitbox();
-    portraitLeft.scrollFactor.set();
-    add(portraitLeft);
-    portraitLeft.visible = false;
-
-    portraitRight = new FlxSprite(0, 40);
-    portraitRight.frames = Paths.getSparrowAtlas('weeb/bfPortrait');
-    portraitRight.animation.addByPrefix('enter', 'Boyfriend portrait enter', 24, false);
-    portraitRight.setGraphicSize(Std.int(portraitRight.width * Constants.PIXEL_ART_SCALE * 0.9));
-    portraitRight.updateHitbox();
-    portraitRight.scrollFactor.set();
-    add(portraitRight);
-    portraitRight.visible = false;
-
-    box = new FlxSprite(-20, 45);
-
-    var hasDialog:Bool = false;
-    switch (PlayState.instance.currentSong.id.toLowerCase())
-    {
-      case 'senpai':
-        hasDialog = true;
-        box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-pixel');
-        box.animation.addByPrefix('normalOpen', 'Text Box Appear', 24, false);
-        box.animation.addByIndices('normal', 'Text Box Appear', [4], '', 24);
-      case 'roses':
-        hasDialog = true;
-        FlxG.sound.play(Paths.sound('ANGRY_TEXT_BOX'));
-
-        box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-senpaiMad');
-        box.animation.addByPrefix('normalOpen', 'SENPAI ANGRY IMPACT SPEECH', 24, false);
-        box.animation.addByIndices('normal', 'SENPAI ANGRY IMPACT SPEECH', [4], '', 24);
-
-      case 'thorns':
-        hasDialog = true;
-        box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-evil');
-        box.animation.addByPrefix('normalOpen', 'Spirit Textbox spawn', 24, false);
-        box.animation.addByIndices('normal', 'Spirit Textbox spawn', [11], '', 24);
-
-        var face:FlxSprite = new FlxSprite(320, 170).loadGraphic(Paths.image('weeb/spiritFaceForward'));
-        face.setGraphicSize(Std.int(face.width * 6));
-        add(face);
-    }
-
-    this.dialogueList = dialogueList;
-
-    if (!hasDialog) return;
-
-    box.animation.play('normalOpen');
-    box.setGraphicSize(Std.int(box.width * Constants.PIXEL_ART_SCALE * 0.9));
-    box.updateHitbox();
-    add(box);
-
-    box.screenCenter(X);
-    portraitLeft.screenCenter(X);
-
-    handSelect = new FlxSprite(1042, 590).loadGraphic(Paths.image('weeb/pixelUI/hand_textbox'));
-    handSelect.setGraphicSize(Std.int(handSelect.width * Constants.PIXEL_ART_SCALE * 0.9));
-    handSelect.updateHitbox();
-    handSelect.visible = false;
-    add(handSelect);
-
-    if (!talkingRight)
-    {
-      // box.flipX = true;
-    }
-
-    dropText = new FlxText(242, 502, Std.int(FlxG.width * 0.6), '', 32);
-    dropText.font = 'Pixel Arial 11 Bold';
-    dropText.color = 0xFFD89494;
-    add(dropText);
-
-    swagDialogue = new FlxTypeText(240, 500, Std.int(FlxG.width * 0.6), '', 32);
-    swagDialogue.font = 'Pixel Arial 11 Bold';
-    swagDialogue.color = 0xFF3F2021;
-    swagDialogue.sounds = [FlxG.sound.load(Paths.sound('pixelText'), 0.6)];
-    add(swagDialogue);
-
-    dialogue = new Alphabet(0, 80, '', false, true);
-    // dialogue.x = 90;
-    // add(dialogue);
-  }
-
-  var dialogueOpened:Bool = false;
-  var dialogueStarted:Bool = false;
-  var dialogueEnded:Bool = false;
-
-  override function update(elapsed:Float):Void
-  {
-    // HARD CODING CUZ IM STUPDI
-    if (PlayState.instance.currentSong.id.toLowerCase() == 'roses') portraitLeft.visible = false;
-    if (PlayState.instance.currentSong.id.toLowerCase() == 'thorns')
-    {
-      portraitLeft.color = FlxColor.BLACK;
-      swagDialogue.color = FlxColor.WHITE;
-      dropText.color = FlxColor.BLACK;
-    }
-
-    dropText.text = swagDialogue.text;
-
-    if (box.animation.curAnim != null)
-    {
-      if (box.animation.curAnim.name == 'normalOpen' && box.animation.curAnim.finished)
-      {
-        box.animation.play('normal');
-        dialogueOpened = true;
-      }
-    }
-
-    if (dialogueOpened && !dialogueStarted)
-    {
-      startDialogue();
-      dialogueStarted = true;
-    }
-
-    if (FlxG.keys.justPressed.ANY && dialogueEnded)
-    {
-      remove(dialogue);
-
-      FlxG.sound.play(Paths.sound('clickText'), 0.8);
-
-      if (dialogueList[1] == null && dialogueList[0] != null)
-      {
-        if (!isEnding)
-        {
-          isEnding = true;
-
-          if (PlayState.instance.currentSong.id.toLowerCase() == 'senpai'
-            || PlayState.instance.currentSong.id.toLowerCase() == 'thorns') FlxG.sound.music.fadeOut(2.2, 0);
-
-          new FlxTimer().start(0.2, function(tmr:FlxTimer) {
-            box.alpha -= 1 / 5;
-            bgFade.alpha -= 1 / 5 * 0.7;
-            portraitLeft.visible = false;
-            portraitRight.visible = false;
-            swagDialogue.alpha -= 1 / 5;
-            handSelect.alpha -= 1 / 5;
-            dropText.alpha = swagDialogue.alpha;
-          }, 5);
-
-          new FlxTimer().start(1.2, function(tmr:FlxTimer) {
-            finishThing();
-            kill();
-          });
-        }
-      }
-      else
-      {
-        dialogueList.remove(dialogueList[0]);
-        startDialogue();
-      }
-    }
-    else if (FlxG.keys.justPressed.ANY && dialogueStarted) swagDialogue.skip();
-
-    super.update(elapsed);
-  }
-
-  var isEnding:Bool = false;
-
-  function startDialogue():Void
-  {
-    cleanDialog();
-    // var theDialog:Alphabet = new Alphabet(0, 70, dialogueList[0], false, true);
-    // dialogue = theDialog;
-    // add(theDialog);
-
-    // swagDialogue.text = ;
-    swagDialogue.resetText(dialogueList[0]);
-    swagDialogue.start(0.04);
-    swagDialogue.completeCallback = function() {
-      trace('dialogue finish');
-      handSelect.visible = true;
-      dialogueEnded = true;
-    };
-    handSelect.visible = false;
-    dialogueEnded = false;
-
-    switch (curCharacter)
-    {
-      case 'dad':
-        portraitRight.visible = false;
-        if (!portraitLeft.visible)
-        {
-          portraitLeft.visible = true;
-          portraitLeft.animation.play('enter');
-        }
-      case 'bf':
-        portraitLeft.visible = false;
-        if (!portraitRight.visible)
-        {
-          portraitRight.visible = true;
-          portraitRight.animation.play('enter');
-        }
-    }
-  }
-
-  function cleanDialog():Void
-  {
-    var splitName:Array<String> = dialogueList[0].split(':');
-    curCharacter = splitName[1];
-    dialogueList[0] = dialogueList[0].substr(splitName[1].length + 2).trim();
-  }
-}
diff --git a/source/funkin/FlxSwf.hx b/source/funkin/FlxSwf.hx
deleted file mode 100644
index d37343894..000000000
--- a/source/funkin/FlxSwf.hx
+++ /dev/null
@@ -1,43 +0,0 @@
-package funkin;
-
-import flixel.FlxCamera;
-import flixel.FlxSprite;
-import flixel.graphics.tile.FlxDrawBaseItem;
-import openfl.display.MovieClip;
-
-class FlxSwf extends FlxSprite
-{
-  public var swf:MovieClip;
-
-  public function new()
-  {
-    super();
-  }
-
-  override function draw()
-  {
-    for (camera in cameras)
-    {
-      if (!camera.visible || !camera.exists) continue;
-
-      getScreenPosition(_point, camera).subtractPoint(offset);
-      // assume no render blit for now
-      // use camera.canvas
-      // camera.canvas.graphics.
-    }
-  }
-}
-
-class FlxDrawSwfItem extends FlxDrawBaseItem<FlxDrawSwfItem>
-{
-  public function new()
-  {
-    super();
-    type = FlxDrawItemType.TILES;
-  }
-
-  override function render(camera:FlxCamera)
-  {
-    super.render(camera);
-  }
-}
diff --git a/source/funkin/Highscore.hx b/source/funkin/Highscore.hx
index 3c9fd82e4..2c18ffa2d 100644
--- a/source/funkin/Highscore.hx
+++ b/source/funkin/Highscore.hx
@@ -1,5 +1,8 @@
 package funkin;
 
+/**
+ * A core class which handles tracking score and combo for the current song.
+ */
 class Highscore
 {
   public static var tallies:Tallies = new Tallies();
diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx
index 5299a3aa0..d74b5f639 100644
--- a/source/funkin/InitState.hx
+++ b/source/funkin/InitState.hx
@@ -1,5 +1,6 @@
 package funkin;
 
+import funkin.ui.transition.LoadingState;
 import flixel.FlxState;
 import flixel.addons.transition.FlxTransitionableState;
 import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
@@ -10,7 +11,7 @@ import flixel.math.FlxRect;
 import flixel.FlxSprite;
 import flixel.system.debug.log.LogStyle;
 import flixel.util.FlxColor;
-import funkin.ui.PreferencesMenu;
+import funkin.ui.options.PreferencesMenu;
 import funkin.util.macro.MacroUtil;
 import funkin.util.WindowUtil;
 import funkin.play.PlayStatePlaylist;
@@ -26,11 +27,13 @@ import funkin.play.stage.StageData.StageDataParser;
 import funkin.play.character.CharacterData.CharacterDataParser;
 import funkin.modding.module.ModuleHandler;
 import funkin.ui.title.TitleState;
+import funkin.ui.transition.LoadingState;
 #if discord_rpc
 import Discord.DiscordClient;
 #end
 
 /**
+ * A core class which performs initialization of the game.
  * The initialization state has several functions:
  * - Calls code to set up the game, including loading saves and parsing game data.
  * - Chooses whether to start via debug or via launching normally.
@@ -228,13 +231,13 @@ class InitState extends FlxState
     #elseif FREEPLAY // -DFREEPLAY
     FlxG.switchState(new FreeplayState());
     #elseif ANIMATE // -DANIMATE
-    FlxG.switchState(new funkin.ui.animDebugShit.FlxAnimateTest());
+    FlxG.switchState(new funkin.ui.debug.anim.FlxAnimateTest());
     #elseif CHARTING // -DCHARTING
     FlxG.switchState(new funkin.ui.debug.charting.ChartEditorState());
     #elseif STAGEBUILD // -DSTAGEBUILD
-    FlxG.switchState(new funkin.ui.stageBullshit.StageBuilderState());
+    FlxG.switchState(new funkin.ui.debug.stage.StageBuilderState());
     #elseif ANIMDEBUG // -DANIMDEBUG
-    FlxG.switchState(new funkin.ui.animDebugShit.DebugBoundingState());
+    FlxG.switchState(new funkin.ui.debug.anim.DebugBoundingState());
     #elseif LATENCY // -DLATENCY
     FlxG.switchState(new funkin.LatencyState());
     #else
diff --git a/source/funkin/MenuCharacter.hx b/source/funkin/MenuCharacter.hx
deleted file mode 100644
index 3e05b9e9f..000000000
--- a/source/funkin/MenuCharacter.hx
+++ /dev/null
@@ -1,42 +0,0 @@
-package funkin;
-
-import flixel.FlxSprite;
-import flixel.graphics.frames.FlxAtlasFrames;
-
-class MenuCharacter extends FlxSprite
-{
-  public var character:String;
-
-  public function new(x:Float, character:String = 'bf')
-  {
-    super(x);
-
-    this.character = character;
-
-    var suffix:String = character;
-
-    if (character != "darnell" && character != "nene") suffix = "characters";
-
-    var tex = Paths.getSparrowAtlas('campaign_menu_UI_' + suffix);
-    frames = tex;
-
-    trace(character);
-
-    animation.addByPrefix('bf', "BF idle dance white", 24);
-    animation.addByPrefix('bfConfirm', 'BF HEY!!', 24, false);
-    animation.addByPrefix('gf', "GF Dancing Beat WHITE", 24);
-    animation.addByPrefix('dad', "Dad idle dance BLACK LINE", 24);
-    animation.addByPrefix('spooky', "spooky dance idle BLACK LINES", 24);
-    animation.addByPrefix('pico', "Pico Idle Dance", 24);
-    animation.addByPrefix('mom', "Mom Idle BLACK LINES", 24);
-    animation.addByPrefix('parents-christmas', "Parent Christmas Idle", 24);
-    animation.addByPrefix('senpai', "SENPAI idle Black Lines", 24);
-    animation.addByPrefix('tankman', "Tankman Menu BLACK", 24);
-    animation.addByPrefix('darnell', "Darnell Black Lines To Scale", 24);
-    animation.addByPrefix('nene', "Nene Black Lines To Scale", 24);
-    // Parent Christmas Idle
-
-    animation.play(character);
-    updateHitbox();
-  }
-}
diff --git a/source/funkin/NoteSplash.hx b/source/funkin/NoteSplash.hx
deleted file mode 100644
index 81b35b36d..000000000
--- a/source/funkin/NoteSplash.hx
+++ /dev/null
@@ -1,65 +0,0 @@
-package funkin;
-
-import flixel.FlxSprite;
-import haxe.io.Path;
-import flixel.graphics.frames.FlxAtlasFrames;
-
-class NoteSplash extends FlxSprite
-{
-  public function new(x:Float, y:Float, noteData:Int = 0):Void
-  {
-    super(x, y);
-
-    animation.addByPrefix('note0-0', 'note impact 1 purple', 24, false);
-    animation.addByPrefix('note1-0', 'note impact 1  blue', 24, false);
-    animation.addByPrefix('note2-0', 'note impact 1 green', 24, false);
-    animation.addByPrefix('note3-0', 'note impact 1 red', 24, false);
-    animation.addByPrefix('note0-1', 'note impact 2 purple', 24, false);
-    animation.addByPrefix('note1-1', 'note impact 2 blue', 24, false);
-    animation.addByPrefix('note2-1', 'note impact 2 green', 24, false);
-    animation.addByPrefix('note3-1', 'note impact 2 red', 24, false);
-
-    setupNoteSplash(x, y, noteData);
-
-    // alpha = 0.75;
-  }
-
-  public override function update(elapsed:Float):Void
-  {
-    super.update(elapsed);
-
-    if (animation.finished)
-    {
-      kill();
-    }
-  }
-
-  public static function buildSplashFrames(force:Bool = false):FlxAtlasFrames
-  {
-    // static variables inside functions are a cool of Haxe 4.3.0.
-    static var splashFrames:FlxAtlasFrames = null;
-
-    if (splashFrames != null && !force) return splashFrames;
-
-    splashFrames = Paths.getSparrowAtlas('noteSplashes');
-
-    splashFrames.parent.persist = true;
-
-    return splashFrames;
-  }
-
-  public function setupNoteSplash(x:Float, y:Float, noteData:Int = 0)
-  {
-    setPosition(x, y);
-    alpha = 0.6;
-
-    animation.play('note' + noteData + '-' + FlxG.random.int(0, 1), true);
-    animation.curAnim.frameRate = 24 + FlxG.random.int(-2, 2);
-    animation.finishCallback = function(name) {
-      kill();
-    };
-    updateHitbox();
-
-    offset.set(width * 0.3, height * 0.3);
-  }
-}
diff --git a/source/funkin/Options.hx b/source/funkin/Options.hx
deleted file mode 100644
index bc8a98570..000000000
--- a/source/funkin/Options.hx
+++ /dev/null
@@ -1,6 +0,0 @@
-package funkin;
-
-class Options
-{
-  public static var masterVolume:Float = 1;
-}
diff --git a/source/funkin/Paths.hx b/source/funkin/Paths.hx
index 07a15dae1..e0212e573 100644
--- a/source/funkin/Paths.hx
+++ b/source/funkin/Paths.hx
@@ -4,6 +4,9 @@ import flixel.graphics.frames.FlxAtlasFrames;
 import openfl.utils.AssetType;
 import openfl.utils.Assets as OpenFlAssets;
 
+/**
+ * A core class which handles determining asset paths.
+ */
 class Paths
 {
   static var currentLevel:String;
diff --git a/source/funkin/PlayerSettings.hx b/source/funkin/PlayerSettings.hx
index e97cfe384..0e728f57e 100644
--- a/source/funkin/PlayerSettings.hx
+++ b/source/funkin/PlayerSettings.hx
@@ -8,8 +8,9 @@ import flixel.input.actions.FlxActionInput;
 import flixel.input.gamepad.FlxGamepad;
 import flixel.util.FlxSignal;
 
-// import ui.DeviceManager;
-// import props.Player;
+/**
+ * A core class which represents the current player(s) and their controls and other configuration.
+ */
 class PlayerSettings
 {
   public static var numPlayers(default, null) = 0;
diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx
index 7e3c3c6d7..6b0911ede 100644
--- a/source/funkin/Preferences.hx
+++ b/source/funkin/Preferences.hx
@@ -3,7 +3,7 @@ package funkin;
 import funkin.save.Save;
 
 /**
- * A store of user-configurable, globally relevant values.
+ * A core class which provides a store of user-configurable, globally relevant values.
  */
 class Preferences
 {
diff --git a/source/funkin/TankCutscene.hx b/source/funkin/TankCutscene.hx
deleted file mode 100644
index 4bc7349ad..000000000
--- a/source/funkin/TankCutscene.hx
+++ /dev/null
@@ -1,27 +0,0 @@
-package funkin;
-
-import flixel.FlxSprite;
-import flixel.sound.FlxSound;
-
-class TankCutscene extends FlxSprite
-{
-  public var startSyncAudio:FlxSound;
-
-  public function new(x:Float, y:Float)
-  {
-    super(x, y);
-  }
-
-  var startedPlayingSound:Bool = false;
-
-  override function update(elapsed:Float)
-  {
-    if (animation.curAnim.curFrame >= 1 && !startedPlayingSound)
-    {
-      startSyncAudio.play();
-      startedPlayingSound = true;
-    }
-
-    super.update(elapsed);
-  }
-}
diff --git a/source/funkin/Discord.hx b/source/funkin/api/discord/Discord.hx
similarity index 98%
rename from source/funkin/Discord.hx
rename to source/funkin/api/discord/Discord.hx
index d2cf12535..a4d65684e 100644
--- a/source/funkin/Discord.hx
+++ b/source/funkin/api/discord/Discord.hx
@@ -1,4 +1,4 @@
-package funkin;
+package funkin.api.discord;
 
 import Sys.sleep;
 #if discord_rpc
diff --git a/source/funkin/api/newgrounds/NGUtil.hx b/source/funkin/api/newgrounds/NGUtil.hx
index ba7d5f916..c8289fc46 100644
--- a/source/funkin/api/newgrounds/NGUtil.hx
+++ b/source/funkin/api/newgrounds/NGUtil.hx
@@ -241,15 +241,3 @@ class NGUtil
   }
   #end
 }
-
-enum ConnectionResult
-{
-  /** Log in successful */
-  Success;
-
-  /** Could not login */
-  Fail(msg:String);
-
-  /** User cancelled the login */
-  Cancelled;
-}
diff --git a/source/funkin/NGio.hx b/source/funkin/api/newgrounds/NGio.hx
similarity index 99%
rename from source/funkin/NGio.hx
rename to source/funkin/api/newgrounds/NGio.hx
index e5f60c8b5..e505bdedf 100644
--- a/source/funkin/NGio.hx
+++ b/source/funkin/api/newgrounds/NGio.hx
@@ -1,4 +1,4 @@
-package funkin;
+package funkin.api.newgrounds;
 
 #if newgrounds
 import flixel.util.FlxSignal;
diff --git a/source/funkin/api/newgrounds/README.md b/source/funkin/api/newgrounds/README.md
index f61e1b0fd..09534fb71 100644
--- a/source/funkin/api/newgrounds/README.md
+++ b/source/funkin/api/newgrounds/README.md
@@ -6,4 +6,4 @@ This package contains two main classes:
 		such as retrieving achievement status.
 - `NGUnsafe` contains sensitive utility functions for interacting with the Newgrounds API.
 	- This includes any functions which scripts should not be able to use,
-		such as writing high scores or posting achievements.
\ No newline at end of file
+		such as writing high scores or posting achievements.
diff --git a/source/funkin/audiovis/ABot.hx b/source/funkin/audio/visualize/ABot.hx
similarity index 85%
rename from source/funkin/audiovis/ABot.hx
rename to source/funkin/audio/visualize/ABot.hx
index 11c123fb2..0b2ec619e 100644
--- a/source/funkin/audiovis/ABot.hx
+++ b/source/funkin/audio/visualize/ABot.hx
@@ -1,4 +1,4 @@
-package funkin.audiovis;
+package funkin.audio.visualize;
 
 import flixel.FlxSprite;
 import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
diff --git a/source/funkin/audiovis/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx
similarity index 96%
rename from source/funkin/audiovis/ABotVis.hx
rename to source/funkin/audio/visualize/ABotVis.hx
index 060bddcf7..681287808 100644
--- a/source/funkin/audiovis/ABotVis.hx
+++ b/source/funkin/audio/visualize/ABotVis.hx
@@ -1,12 +1,13 @@
-package funkin.audiovis;
+package funkin.audio.visualize;
 
-import funkin.audiovis.dsp.FFT;
+import funkin.audio.visualize.dsp.FFT;
 import flixel.FlxSprite;
 import flixel.addons.plugin.taskManager.FlxTask;
 import flixel.graphics.frames.FlxAtlasFrames;
 import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
 import flixel.math.FlxMath;
 import flixel.sound.FlxSound;
+import funkin.util.MathUtil;
 
 using Lambda;
 
@@ -86,7 +87,7 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
         for (i in 0...group.members.length)
         {
           var getSliceShit = function(s:Int) {
-            var powShit = FlxMath.remapToRange(s, 0, group.members.length, 0, CoolUtil.coolBaseLog(10, freqShit[0].length));
+            var powShit = FlxMath.remapToRange(s, 0, group.members.length, 0, MathUtil.logBase(10, freqShit[0].length));
             return Math.round(Math.pow(10, powShit));
           };
 
diff --git a/source/funkin/audio/visualize/PolygonSpectogram.hx b/source/funkin/audio/visualize/PolygonSpectogram.hx
index 6b7e280ec..604bc910b 100644
--- a/source/funkin/audio/visualize/PolygonSpectogram.hx
+++ b/source/funkin/audio/visualize/PolygonSpectogram.hx
@@ -4,7 +4,7 @@ import flixel.math.FlxMath;
 import flixel.math.FlxPoint;
 import flixel.sound.FlxSound;
 import flixel.util.FlxColor;
-import funkin.audiovis.VisShit;
+import funkin.audio.visualize.VisShit;
 import funkin.graphics.rendering.MeshRender;
 import lime.utils.Int16Array;
 
diff --git a/source/funkin/audiovis/SpectogramSprite.hx b/source/funkin/audio/visualize/SpectogramSprite.hx
similarity index 98%
rename from source/funkin/audiovis/SpectogramSprite.hx
rename to source/funkin/audio/visualize/SpectogramSprite.hx
index c4f8234eb..63d0fcd2e 100644
--- a/source/funkin/audiovis/SpectogramSprite.hx
+++ b/source/funkin/audio/visualize/SpectogramSprite.hx
@@ -1,4 +1,4 @@
-package funkin.audiovis;
+package funkin.audio.visualize;
 
 import flixel.FlxSprite;
 import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
@@ -8,8 +8,8 @@ import flixel.math.FlxVector;
 import flixel.sound.FlxSound;
 import flixel.util.FlxColor;
 import funkin.audio.visualize.PolygonSpectogram.VISTYPE;
-import funkin.audiovis.VisShit.CurAudioInfo;
-import funkin.audiovis.dsp.FFT;
+import funkin.audio.visualize.VisShit.CurAudioInfo;
+import funkin.audio.visualize.dsp.FFT;
 import haxe.Timer;
 import lime.system.ThreadPool;
 import lime.utils.Int16Array;
diff --git a/source/funkin/audiovis/VisShit.hx b/source/funkin/audio/visualize/VisShit.hx
similarity index 93%
rename from source/funkin/audiovis/VisShit.hx
rename to source/funkin/audio/visualize/VisShit.hx
index ee531a977..5bfb8c7c5 100644
--- a/source/funkin/audiovis/VisShit.hx
+++ b/source/funkin/audio/visualize/VisShit.hx
@@ -1,11 +1,12 @@
-package funkin.audiovis;
+package funkin.audio.visualize;
 
 import flixel.math.FlxMath;
 import flixel.sound.FlxSound;
-import funkin.audiovis.dsp.FFT;
+import funkin.audio.visualize.dsp.FFT;
 import haxe.Timer;
 import lime.system.ThreadPool;
 import lime.utils.Int16Array;
+import funkin.util.MathUtil;
 
 using Lambda;
 
@@ -42,7 +43,7 @@ class VisShit
     // helpers, note that spectrum indexes suppose non-negative frequencies
     final binSize = fs / fftN;
     final indexToFreq = function(k:Int) {
-      var powShit:Float = FlxMath.remapToRange(k, 0, halfN, 0, CoolUtil.coolBaseLog(10, halfN)); // 4.3 is almost the log of 20Khz or so. Close enuf lol
+      var powShit:Float = FlxMath.remapToRange(k, 0, halfN, 0, MathUtil.logBase(10, halfN)); // 4.3 is almost the log of 20Khz or so. Close enuf lol
 
       return 1.0 * (Math.pow(10, powShit)); // we need the `1.0` to avoid overflows
     };
diff --git a/source/funkin/audiovis/dsp/Complex.hx b/source/funkin/audio/visualize/dsp/Complex.hx
similarity index 98%
rename from source/funkin/audiovis/dsp/Complex.hx
rename to source/funkin/audio/visualize/dsp/Complex.hx
index 523549e99..37861bcc3 100644
--- a/source/funkin/audiovis/dsp/Complex.hx
+++ b/source/funkin/audio/visualize/dsp/Complex.hx
@@ -1,4 +1,4 @@
-package funkin.audiovis.dsp;
+package funkin.audio.visualize.dsp;
 
 /**
   Complex number representation.
diff --git a/source/funkin/audiovis/dsp/FFT.hx b/source/funkin/audio/visualize/dsp/FFT.hx
similarity index 97%
rename from source/funkin/audiovis/dsp/FFT.hx
rename to source/funkin/audio/visualize/dsp/FFT.hx
index d1d99140e..dc75acb81 100644
--- a/source/funkin/audiovis/dsp/FFT.hx
+++ b/source/funkin/audio/visualize/dsp/FFT.hx
@@ -1,9 +1,9 @@
-package funkin.audiovis.dsp;
+package funkin.audio.visualize.dsp;
 
-import funkin.audiovis.dsp.Complex;
+import funkin.audio.visualize.dsp.Complex;
 
-using funkin.audiovis.dsp.OffsetArray;
-using funkin.audiovis.dsp.Signal;
+using funkin.audio.visualize.dsp.OffsetArray;
+using funkin.audio.visualize.dsp.Signal;
 
 // these are only used for testing, down in FFT.main()
 
diff --git a/source/funkin/audiovis/dsp/OffsetArray.hx b/source/funkin/audio/visualize/dsp/OffsetArray.hx
similarity index 98%
rename from source/funkin/audiovis/dsp/OffsetArray.hx
rename to source/funkin/audio/visualize/dsp/OffsetArray.hx
index bd066a727..c8a5c27c3 100644
--- a/source/funkin/audiovis/dsp/OffsetArray.hx
+++ b/source/funkin/audio/visualize/dsp/OffsetArray.hx
@@ -1,4 +1,4 @@
-package funkin.audiovis.dsp;
+package funkin.audio.visualize.dsp;
 
 /**
   A view into an Array with an indexing offset.
diff --git a/source/funkin/audiovis/dsp/Signal.hx b/source/funkin/audio/visualize/dsp/Signal.hx
similarity index 98%
rename from source/funkin/audiovis/dsp/Signal.hx
rename to source/funkin/audio/visualize/dsp/Signal.hx
index 1f7cc6114..4557dc199 100644
--- a/source/funkin/audiovis/dsp/Signal.hx
+++ b/source/funkin/audio/visualize/dsp/Signal.hx
@@ -1,4 +1,4 @@
-package funkin.audiovis.dsp;
+package funkin.audio.visualize.dsp;
 
 using Lambda;
 
diff --git a/source/funkin/shaderslmfao/AngleMask.hx b/source/funkin/graphics/shaders/AngleMask.hx
similarity index 96%
rename from source/funkin/shaderslmfao/AngleMask.hx
rename to source/funkin/graphics/shaders/AngleMask.hx
index b9188201b..30e508a58 100644
--- a/source/funkin/shaderslmfao/AngleMask.hx
+++ b/source/funkin/graphics/shaders/AngleMask.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.system.FlxAssets.FlxShader;
 
diff --git a/source/funkin/shaderslmfao/BlendModeEffect.hx b/source/funkin/graphics/shaders/BlendModeEffect.hx
similarity index 95%
rename from source/funkin/shaderslmfao/BlendModeEffect.hx
rename to source/funkin/graphics/shaders/BlendModeEffect.hx
index 8fe98f70a..bf2246795 100644
--- a/source/funkin/shaderslmfao/BlendModeEffect.hx
+++ b/source/funkin/graphics/shaders/BlendModeEffect.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.util.FlxColor;
 import openfl.display.ShaderParameter;
diff --git a/source/funkin/shaderslmfao/BlendModesShader.hx b/source/funkin/graphics/shaders/BlendModesShader.hx
similarity index 92%
rename from source/funkin/shaderslmfao/BlendModesShader.hx
rename to source/funkin/graphics/shaders/BlendModesShader.hx
index 6807a65c0..acd2c1586 100644
--- a/source/funkin/shaderslmfao/BlendModesShader.hx
+++ b/source/funkin/graphics/shaders/BlendModesShader.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.addons.display.FlxRuntimeShader;
 import funkin.Paths;
diff --git a/source/funkin/shaderslmfao/ColorSwap.hx b/source/funkin/graphics/shaders/ColorSwap.hx
similarity index 99%
rename from source/funkin/shaderslmfao/ColorSwap.hx
rename to source/funkin/graphics/shaders/ColorSwap.hx
index 2c1f5664b..1be4d5429 100644
--- a/source/funkin/shaderslmfao/ColorSwap.hx
+++ b/source/funkin/graphics/shaders/ColorSwap.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.system.FlxAssets.FlxShader;
 import flixel.util.FlxColor;
diff --git a/source/funkin/shaderslmfao/GaussianBlurShader.hx b/source/funkin/graphics/shaders/GaussianBlurShader.hx
similarity index 93%
rename from source/funkin/shaderslmfao/GaussianBlurShader.hx
rename to source/funkin/graphics/shaders/GaussianBlurShader.hx
index ad472ac31..81167655b 100644
--- a/source/funkin/shaderslmfao/GaussianBlurShader.hx
+++ b/source/funkin/graphics/shaders/GaussianBlurShader.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.addons.display.FlxRuntimeShader;
 import funkin.Paths;
diff --git a/source/funkin/shaderslmfao/Grayscale.hx b/source/funkin/graphics/shaders/Grayscale.hx
similarity index 92%
rename from source/funkin/shaderslmfao/Grayscale.hx
rename to source/funkin/graphics/shaders/Grayscale.hx
index 016d64b46..6673ace24 100644
--- a/source/funkin/shaderslmfao/Grayscale.hx
+++ b/source/funkin/graphics/shaders/Grayscale.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.addons.display.FlxRuntimeShader;
 import funkin.Paths;
diff --git a/source/funkin/shaderslmfao/HSVShader.hx b/source/funkin/graphics/shaders/HSVShader.hx
similarity index 96%
rename from source/funkin/shaderslmfao/HSVShader.hx
rename to source/funkin/graphics/shaders/HSVShader.hx
index 066a49c96..733bbca7f 100644
--- a/source/funkin/shaderslmfao/HSVShader.hx
+++ b/source/funkin/graphics/shaders/HSVShader.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.addons.display.FlxRuntimeShader;
 import funkin.Paths;
diff --git a/source/funkin/shaderslmfao/LeftMaskShader.hx b/source/funkin/graphics/shaders/LeftMaskShader.hx
similarity index 97%
rename from source/funkin/shaderslmfao/LeftMaskShader.hx
rename to source/funkin/graphics/shaders/LeftMaskShader.hx
index e921a7f2b..f82a5c208 100644
--- a/source/funkin/shaderslmfao/LeftMaskShader.hx
+++ b/source/funkin/graphics/shaders/LeftMaskShader.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.math.FlxRect;
 import flixel.system.FlxAssets.FlxShader;
diff --git a/source/funkin/shaderslmfao/MultiplyShader.hx b/source/funkin/graphics/shaders/MultiplyShader.hx
similarity index 94%
rename from source/funkin/shaderslmfao/MultiplyShader.hx
rename to source/funkin/graphics/shaders/MultiplyShader.hx
index 2868982a2..5fe95f04e 100644
--- a/source/funkin/shaderslmfao/MultiplyShader.hx
+++ b/source/funkin/graphics/shaders/MultiplyShader.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.system.FlxAssets.FlxShader;
 
diff --git a/source/funkin/shaderslmfao/OverlayBlend.hx b/source/funkin/graphics/shaders/OverlayBlend.hx
similarity index 97%
rename from source/funkin/shaderslmfao/OverlayBlend.hx
rename to source/funkin/graphics/shaders/OverlayBlend.hx
index 8845a3b55..e44f3152a 100644
--- a/source/funkin/shaderslmfao/OverlayBlend.hx
+++ b/source/funkin/graphics/shaders/OverlayBlend.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.math.FlxPoint;
 import flixel.system.FlxAssets.FlxShader;
diff --git a/source/funkin/shaderslmfao/PureColor.hx b/source/funkin/graphics/shaders/PureColor.hx
similarity index 96%
rename from source/funkin/shaderslmfao/PureColor.hx
rename to source/funkin/graphics/shaders/PureColor.hx
index 767a29d0d..1d2216a8c 100644
--- a/source/funkin/shaderslmfao/PureColor.hx
+++ b/source/funkin/graphics/shaders/PureColor.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.system.FlxAssets.FlxShader;
 import flixel.util.FlxColor;
diff --git a/source/funkin/shaderslmfao/ScreenWipeShader.hx b/source/funkin/graphics/shaders/ScreenWipeShader.hx
similarity index 98%
rename from source/funkin/shaderslmfao/ScreenWipeShader.hx
rename to source/funkin/graphics/shaders/ScreenWipeShader.hx
index 1aeb069ba..bc45f0ef6 100644
--- a/source/funkin/shaderslmfao/ScreenWipeShader.hx
+++ b/source/funkin/graphics/shaders/ScreenWipeShader.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.system.FlxAssets.FlxShader;
 
diff --git a/source/funkin/shaderslmfao/StrokeShader.hx b/source/funkin/graphics/shaders/StrokeShader.hx
similarity index 98%
rename from source/funkin/shaderslmfao/StrokeShader.hx
rename to source/funkin/graphics/shaders/StrokeShader.hx
index 38dc41636..fd133ac0a 100644
--- a/source/funkin/shaderslmfao/StrokeShader.hx
+++ b/source/funkin/graphics/shaders/StrokeShader.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.system.FlxAssets.FlxShader;
 import flixel.util.FlxColor;
diff --git a/source/funkin/shaderslmfao/TitleOutline.hx b/source/funkin/graphics/shaders/TitleOutline.hx
similarity index 98%
rename from source/funkin/shaderslmfao/TitleOutline.hx
rename to source/funkin/graphics/shaders/TitleOutline.hx
index 9a849f795..db60fc3ae 100644
--- a/source/funkin/shaderslmfao/TitleOutline.hx
+++ b/source/funkin/graphics/shaders/TitleOutline.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.math.FlxPoint;
 import flixel.system.FlxAssets.FlxShader;
diff --git a/source/funkin/shaderslmfao/WaveShader.hx b/source/funkin/graphics/shaders/WaveShader.hx
similarity index 90%
rename from source/funkin/shaderslmfao/WaveShader.hx
rename to source/funkin/graphics/shaders/WaveShader.hx
index 89171b089..8738cc405 100644
--- a/source/funkin/shaderslmfao/WaveShader.hx
+++ b/source/funkin/graphics/shaders/WaveShader.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.system.FlxAssets.FlxShader;
 
diff --git a/source/funkin/shaderslmfao/WiggleEffectRuntime.hx b/source/funkin/graphics/shaders/WiggleEffectRuntime.hx
similarity index 98%
rename from source/funkin/shaderslmfao/WiggleEffectRuntime.hx
rename to source/funkin/graphics/shaders/WiggleEffectRuntime.hx
index 23f93b672..a04941df5 100644
--- a/source/funkin/shaderslmfao/WiggleEffectRuntime.hx
+++ b/source/funkin/graphics/shaders/WiggleEffectRuntime.hx
@@ -1,4 +1,4 @@
-package funkin.shaderslmfao;
+package funkin.graphics.shaders;
 
 import flixel.addons.display.FlxRuntimeShader;
 import openfl.Assets;
diff --git a/source/funkin/input/TurboKeyHandler.hx b/source/funkin/input/TurboKeyHandler.hx
index 099d373b4..36b8e2087 100644
--- a/source/funkin/input/TurboKeyHandler.hx
+++ b/source/funkin/input/TurboKeyHandler.hx
@@ -108,8 +108,7 @@ class TurboKeyHandler extends FlxBasic
    * @param repeatDelay How long to wait between repeats.
    * @return A TurboKeyHandler
    */
-  public static overload inline extern function build(inputKeys:Array<FlxKey>, ?delay:Float = DEFAULT_DELAY,
-      ?interval:Float = DEFAULT_INTERVAL):TurboKeyHandler
+  public static overload inline extern function build(inputKeys:Array<FlxKey>, ?delay:Float = DEFAULT_DELAY, ?interval:Float = DEFAULT_INTERVAL):TurboKeyHandler
   {
     return new TurboKeyHandler(inputKeys, delay, interval);
   }
diff --git a/source/funkin/modding/base/ScriptedMusicBeatState.hx b/source/funkin/modding/base/ScriptedMusicBeatState.hx
index 782e4d0b8..6dc6826c4 100644
--- a/source/funkin/modding/base/ScriptedMusicBeatState.hx
+++ b/source/funkin/modding/base/ScriptedMusicBeatState.hx
@@ -5,4 +5,4 @@ package funkin.modding.base;
  * Create a scripted class that extends MusicBeatState to use this.
  */
 @:hscriptClass
-class ScriptedMusicBeatState extends funkin.MusicBeatState implements HScriptedClass {}
+class ScriptedMusicBeatState extends funkin.ui.MusicBeatState implements HScriptedClass {}
diff --git a/source/funkin/modding/base/ScriptedMusicBeatSubState.hx b/source/funkin/modding/base/ScriptedMusicBeatSubState.hx
index 7dab3d7dd..79c98ea3f 100644
--- a/source/funkin/modding/base/ScriptedMusicBeatSubState.hx
+++ b/source/funkin/modding/base/ScriptedMusicBeatSubState.hx
@@ -5,4 +5,4 @@ package funkin.modding.base;
  * Create a scripted class that extends MusicBeatSubState to use this.
  */
 @:hscriptClass
-class ScriptedMusicBeatSubState extends funkin.MusicBeatSubState implements HScriptedClass {}
+class ScriptedMusicBeatSubState extends funkin.ui.MusicBeatSubState implements HScriptedClass {}
diff --git a/source/funkin/play/Fighter.hx b/source/funkin/play/Fighter.hx
deleted file mode 100644
index 691d21b83..000000000
--- a/source/funkin/play/Fighter.hx
+++ /dev/null
@@ -1,68 +0,0 @@
-package funkin.play;
-
-import funkin.play.character.BaseCharacter;
-import flixel.FlxSprite;
-
-class Fighter extends BaseCharacter
-{
-  public function new(?x:Float = 0, ?y:Float = 0, ?char:String = "pico-fighter")
-  {
-    super(char, Custom);
-    this.x = x;
-    this.y = y;
-
-    animation.finishCallback = function(anim:String) {
-      switch anim
-      {
-        case "punch low" | "punch high" | "block" | 'dodge':
-          dance(true);
-      }
-    };
-  }
-
-  public var actions:Array<ACTIONS> = [PUNCH, BLOCK, DODGE];
-
-  public function doSomething(?forceAction:ACTIONS)
-  {
-    var daAction:ACTIONS = FlxG.random.getObject(actions);
-
-    if (forceAction != null) daAction = forceAction;
-
-    switch (daAction)
-    {
-      case PUNCH:
-        punch();
-      case BLOCK:
-        block();
-      case DODGE:
-        dodge();
-    }
-  }
-
-  public var curAction:ACTIONS = DODGE;
-
-  function dodge()
-  {
-    playAnimation('dodge');
-    curAction = DODGE;
-  }
-
-  public function block()
-  {
-    playAnimation('block');
-    curAction = BLOCK;
-  }
-
-  public function punch()
-  {
-    curAction = PUNCH;
-    playAnimation('punch ' + (FlxG.random.bool() ? "low" : "high"));
-  }
-}
-
-enum ACTIONS
-{
-  DODGE;
-  BLOCK;
-  PUNCH;
-}
diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx
index c5d9b4b0b..6eb53e2d5 100644
--- a/source/funkin/play/GameOverSubState.hx
+++ b/source/funkin/play/GameOverSubState.hx
@@ -7,9 +7,11 @@ import flixel.sound.FlxSound;
 import funkin.ui.story.StoryMenuState;
 import flixel.util.FlxColor;
 import flixel.util.FlxTimer;
+import funkin.ui.MusicBeatSubState;
 import funkin.modding.events.ScriptEvent;
 import funkin.modding.events.ScriptEventDispatcher;
 import funkin.play.PlayState;
+import funkin.ui.freeplay.FreeplayState;
 import funkin.play.character.BaseCharacter;
 
 /**
diff --git a/source/funkin/GitarooPause.hx b/source/funkin/play/GitarooPause.hx
similarity index 96%
rename from source/funkin/GitarooPause.hx
rename to source/funkin/play/GitarooPause.hx
index a4dc766be..dbfbf5961 100644
--- a/source/funkin/GitarooPause.hx
+++ b/source/funkin/play/GitarooPause.hx
@@ -1,9 +1,11 @@
-package funkin;
+package funkin.play;
 
 import flixel.FlxSprite;
 import flixel.graphics.frames.FlxAtlasFrames;
 import funkin.play.PlayState;
+import funkin.ui.MusicBeatState;
 import flixel.addons.transition.FlxTransitionableState;
+import funkin.ui.mainmenu.MainMenuState;
 
 class GitarooPause extends MusicBeatState
 {
diff --git a/source/funkin/PauseSubState.hx b/source/funkin/play/PauseSubState.hx
similarity index 97%
rename from source/funkin/PauseSubState.hx
rename to source/funkin/play/PauseSubState.hx
index 2ce9abf65..f5555b66e 100644
--- a/source/funkin/PauseSubState.hx
+++ b/source/funkin/play/PauseSubState.hx
@@ -1,9 +1,10 @@
-package funkin;
+package funkin.play;
 
 import funkin.play.PlayStatePlaylist;
 import flixel.FlxSprite;
 import flixel.addons.transition.FlxTransitionableState;
 import flixel.group.FlxGroup.FlxTypedGroup;
+import funkin.ui.MusicBeatSubState;
 import flixel.sound.FlxSound;
 import flixel.text.FlxText;
 import flixel.tweens.FlxEase;
@@ -11,6 +12,7 @@ import flixel.tweens.FlxTween;
 import flixel.util.FlxColor;
 import funkin.play.PlayState;
 import funkin.data.song.SongRegistry;
+import funkin.ui.Alphabet;
 
 class PauseSubState extends MusicBeatSubState
 {
@@ -231,11 +233,11 @@ class PauseSubState extends MusicBeatSubState
 
             if (PlayStatePlaylist.isStoryMode)
             {
-              openSubState(new funkin.ui.StickerSubState(null, STORY));
+              openSubState(new funkin.ui.transition.StickerSubState(null, STORY));
             }
             else
             {
-              openSubState(new funkin.ui.StickerSubState(null, FREEPLAY));
+              openSubState(new funkin.ui.transition.StickerSubState(null, FREEPLAY));
             }
 
           case 'Exit to Chart Editor':
diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx
index 4542b9f98..c1e62146b 100644
--- a/source/funkin/play/PlayState.hx
+++ b/source/funkin/play/PlayState.hx
@@ -1,5 +1,6 @@
 package funkin.play;
 
+import funkin.ui.SwagCamera;
 import flixel.addons.transition.FlxTransitionableSubState;
 import funkin.ui.debug.charting.ChartEditorState;
 import haxe.Int64;
@@ -16,19 +17,24 @@ import flixel.FlxState;
 import flixel.FlxSubState;
 import flixel.input.keyboard.FlxKey;
 import flixel.math.FlxMath;
+import funkin.play.components.ComboMilestone;
 import flixel.math.FlxPoint;
+import funkin.play.components.HealthIcon;
+import funkin.ui.MusicBeatSubState;
 import flixel.math.FlxRect;
 import flixel.text.FlxText;
 import flixel.tweens.FlxEase;
 import flixel.tweens.FlxTween;
 import flixel.ui.FlxBar;
 import flixel.util.FlxColor;
+import funkin.api.newgrounds.NGio;
 import flixel.util.FlxTimer;
 import funkin.audio.VoicesGroup;
 import funkin.save.Save;
 import funkin.Highscore.Tallies;
 import funkin.input.PreciseInputManager;
 import funkin.modding.events.ScriptEvent;
+import funkin.ui.mainmenu.MainMenuState;
 import funkin.modding.events.ScriptEventDispatcher;
 import funkin.play.character.BaseCharacter;
 import funkin.play.character.CharacterData.CharacterDataParser;
@@ -42,7 +48,6 @@ import funkin.play.notes.NoteDirection;
 import funkin.play.notes.Strumline;
 import funkin.play.notes.SustainTrail;
 import funkin.play.scoring.Scoring;
-import funkin.NoteSplash;
 import funkin.play.song.Song;
 import funkin.data.song.SongRegistry;
 import funkin.data.song.SongData.SongEventData;
@@ -50,9 +55,10 @@ import funkin.data.song.SongData.SongNoteData;
 import funkin.data.song.SongData.SongCharacterData;
 import funkin.play.stage.Stage;
 import funkin.play.stage.StageData.StageDataParser;
-import funkin.ui.PopUpStuff;
-import funkin.ui.PreferencesMenu;
-import funkin.ui.stageBuildShit.StageOffsetSubState;
+import funkin.ui.transition.LoadingState;
+import funkin.play.components.PopUpStuff;
+import funkin.ui.options.PreferencesMenu;
+import funkin.ui.debug.stage.StageOffsetSubState;
 import funkin.ui.story.StoryMenuState;
 import funkin.util.SerializerUtil;
 import funkin.util.SortUtil;
@@ -510,8 +516,6 @@ class PlayState extends MusicBeatSubState
     }
     instance = this;
 
-    NoteSplash.buildSplashFrames();
-
     if (!assertChartExists()) return;
 
     if (false)
diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx
index 3f7231c2a..507fa1236 100644
--- a/source/funkin/play/ResultState.hx
+++ b/source/funkin/play/ResultState.hx
@@ -8,16 +8,18 @@ import flixel.graphics.frames.FlxAtlasFrames;
 import flixel.graphics.frames.FlxBitmapFont;
 import flixel.group.FlxGroup.FlxTypedGroup;
 import flixel.math.FlxPoint;
+import funkin.ui.MusicBeatSubState;
 import flixel.math.FlxRect;
 import flixel.text.FlxBitmapText;
 import flixel.text.FlxText;
 import flixel.tweens.FlxEase;
+import funkin.ui.freeplay.FreeplayState;
 import flixel.tweens.FlxTween;
 import flixel.util.FlxColor;
 import flixel.util.FlxGradient;
 import flixel.util.FlxTimer;
-import funkin.shaderslmfao.LeftMaskShader;
-import funkin.ui.TallyCounter;
+import funkin.graphics.shaders.LeftMaskShader;
+import funkin.play.components.TallyCounter;
 import flxanimate.FlxAnimate.Settings;
 
 class ResultState extends MusicBeatSubState
diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx
index 588b5663d..7ad0892f6 100644
--- a/source/funkin/play/character/BaseCharacter.hx
+++ b/source/funkin/play/character/BaseCharacter.hx
@@ -58,7 +58,7 @@ class BaseCharacter extends Bopper
    */
   public var dropNoteCounts(default, null):Array<Int>;
 
-  @:allow(funkin.ui.animDebugShit.DebugBoundingState)
+  @:allow(funkin.ui.debug.anim.DebugBoundingState)
   final _data:CharacterData;
   final singTimeSec:Float;
 
diff --git a/source/funkin/ComboMilestone.hx b/source/funkin/play/components/ComboMilestone.hx
similarity index 98%
rename from source/funkin/ComboMilestone.hx
rename to source/funkin/play/components/ComboMilestone.hx
index 79e454c44..54d1438f1 100644
--- a/source/funkin/ComboMilestone.hx
+++ b/source/funkin/play/components/ComboMilestone.hx
@@ -1,4 +1,4 @@
-package funkin;
+package funkin.play.components;
 
 import flixel.FlxSprite;
 import flixel.group.FlxGroup.FlxTypedGroup;
diff --git a/source/funkin/play/HealthIcon.hx b/source/funkin/play/components/HealthIcon.hx
similarity index 98%
rename from source/funkin/play/HealthIcon.hx
rename to source/funkin/play/components/HealthIcon.hx
index 958933df8..0d90df5a0 100644
--- a/source/funkin/play/HealthIcon.hx
+++ b/source/funkin/play/components/HealthIcon.hx
@@ -1,4 +1,4 @@
-package funkin.play;
+package funkin.play.components;
 
 import funkin.play.character.CharacterData;
 import flixel.FlxSprite;
@@ -6,6 +6,7 @@ import flixel.math.FlxMath;
 import flixel.math.FlxPoint;
 import funkin.play.character.CharacterData.CharacterDataParser;
 import openfl.utils.Assets;
+import funkin.util.MathUtil;
 
 /**
  * This is a rework of the health icon with the following changes:
@@ -201,19 +202,19 @@ class HealthIcon extends FlxSprite
       if (this.width > this.height)
       {
         // Apply linear interpolation while accounting for frame rate.
-        var targetSize:Int = Std.int(CoolUtil.coolLerp(this.width, HEALTH_ICON_SIZE * this.size.x, 0.15));
+        var targetSize:Int = Std.int(MathUtil.coolLerp(this.width, HEALTH_ICON_SIZE * this.size.x, 0.15));
 
         setGraphicSize(targetSize, 0);
       }
       else
       {
-        var targetSize:Int = Std.int(CoolUtil.coolLerp(this.height, HEALTH_ICON_SIZE * this.size.y, 0.15));
+        var targetSize:Int = Std.int(MathUtil.coolLerp(this.height, HEALTH_ICON_SIZE * this.size.y, 0.15));
 
         setGraphicSize(0, targetSize);
       }
 
       // Lerp the health icon back to its normal angle.
-      this.angle = CoolUtil.coolLerp(this.angle, 0, 0.15);
+      this.angle = MathUtil.coolLerp(this.angle, 0, 0.15);
 
       this.updateHitbox();
     }
diff --git a/source/funkin/ui/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx
similarity index 99%
rename from source/funkin/ui/PopUpStuff.hx
rename to source/funkin/play/components/PopUpStuff.hx
index 75fc87c8b..38a6ec15a 100644
--- a/source/funkin/ui/PopUpStuff.hx
+++ b/source/funkin/play/components/PopUpStuff.hx
@@ -1,4 +1,4 @@
-package funkin.ui;
+package funkin.play.components;
 
 import flixel.FlxSprite;
 import flixel.group.FlxGroup.FlxTypedGroup;
diff --git a/source/funkin/ui/TallyCounter.hx b/source/funkin/play/components/TallyCounter.hx
similarity index 94%
rename from source/funkin/ui/TallyCounter.hx
rename to source/funkin/play/components/TallyCounter.hx
index 72857671e..77e6ef4ec 100644
--- a/source/funkin/ui/TallyCounter.hx
+++ b/source/funkin/play/components/TallyCounter.hx
@@ -1,4 +1,4 @@
-package funkin.ui;
+package funkin.play.components;
 
 import flixel.FlxSprite;
 import flixel.group.FlxGroup.FlxTypedGroup;
@@ -8,7 +8,7 @@ import flixel.tweens.FlxEase;
 import flixel.tweens.FlxTween;
 
 /**
- * Similar to ComboCounter, but it's not!
+ * Numerical counters used next to each judgement in the Results screen.
  */
 class TallyCounter extends FlxTypedSpriteGroup<FlxSprite>
 {
diff --git a/source/funkin/play/cutscene/dialogue/ConversationDebugState.hx b/source/funkin/play/cutscene/dialogue/ConversationDebugState.hx
index 70ac011a2..13697b9f4 100644
--- a/source/funkin/play/cutscene/dialogue/ConversationDebugState.hx
+++ b/source/funkin/play/cutscene/dialogue/ConversationDebugState.hx
@@ -4,6 +4,7 @@ import flixel.FlxState;
 import funkin.modding.events.ScriptEventDispatcher;
 import funkin.modding.events.ScriptEvent;
 import flixel.util.FlxColor;
+import funkin.ui.MusicBeatState;
 
 /**
  * A state with displays a conversation with no background.
diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx
index 60b995c06..369a4144a 100644
--- a/source/funkin/play/notes/Strumline.hx
+++ b/source/funkin/play/notes/Strumline.hx
@@ -12,7 +12,7 @@ import funkin.play.notes.NoteSplash;
 import funkin.play.notes.NoteSprite;
 import funkin.play.notes.SustainTrail;
 import funkin.data.song.SongData.SongNoteData;
-import funkin.ui.PreferencesMenu;
+import funkin.ui.options.PreferencesMenu;
 import funkin.util.SortUtil;
 
 /**
diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx
index f55799828..ab4bf5f16 100644
--- a/source/funkin/play/notes/SustainTrail.hx
+++ b/source/funkin/play/notes/SustainTrail.hx
@@ -8,7 +8,7 @@ import flixel.FlxSprite;
 import flixel.graphics.FlxGraphic;
 import flixel.graphics.tile.FlxDrawTrianglesItem;
 import flixel.math.FlxMath;
-import funkin.ui.PreferencesMenu;
+import funkin.ui.options.PreferencesMenu;
 
 /**
  * This is based heavily on the `FlxStrip` class. It uses `drawTriangles()` to clip a sustain note
diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx
index 187b5ec32..1bc0632f9 100644
--- a/source/funkin/play/stage/Bopper.hx
+++ b/source/funkin/play/stage/Bopper.hx
@@ -85,7 +85,7 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
     return globalOffsets = value;
   }
 
-  @:allow(funkin.ui.animDebugShit.DebugBoundingState)
+  @:allow(funkin.ui.debug.anim.DebugBoundingState)
   var animOffsets(default, set):Array<Float> = [0, 0];
 
   public var originalPosition:FlxPoint = new FlxPoint(0, 0);
diff --git a/source/funkin/Alphabet.hx b/source/funkin/ui/Alphabet.hx
similarity index 97%
rename from source/funkin/Alphabet.hx
rename to source/funkin/ui/Alphabet.hx
index 45e9a2aee..66b95f5b8 100644
--- a/source/funkin/Alphabet.hx
+++ b/source/funkin/ui/Alphabet.hx
@@ -1,9 +1,10 @@
-package funkin;
+package funkin.ui;
 
 import flixel.FlxSprite;
 import flixel.group.FlxSpriteGroup;
 import flixel.math.FlxMath;
 import flixel.util.FlxTimer;
+import funkin.util.MathUtil;
 
 /**
  * Loosley based on FlxTypeText lolol
@@ -151,7 +152,6 @@ class Alphabet extends FlxSpriteGroup
       if (AlphaCharacter.alphabet.indexOf(splitWords[loopNum].toLowerCase()) != -1
         || isNumber
         || isSymbol) // if (AlphaCharacter.alphabet.contains(splitWords[loopNum].toLowerCase()) || isNumber || isSymbol)
-
       {
         if (lastSprite != null && !xPosResetted)
         {
@@ -220,8 +220,8 @@ class Alphabet extends FlxSpriteGroup
     {
       var scaledY = FlxMath.remapToRange(targetY, 0, 1, 0, 1.3);
 
-      y = CoolUtil.coolLerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16);
-      x = CoolUtil.coolLerp(x, (targetY * 20) + 90, 0.16);
+      y = MathUtil.coolLerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16);
+      x = MathUtil.coolLerp(x, (targetY * 20) + 90, 0.16);
     }
 
     super.update(elapsed);
diff --git a/source/funkin/ui/AtlasMenuList.hx b/source/funkin/ui/AtlasMenuList.hx
index 028a00eef..efff6da93 100644
--- a/source/funkin/ui/AtlasMenuList.hx
+++ b/source/funkin/ui/AtlasMenuList.hx
@@ -38,7 +38,7 @@ class AtlasMenuList extends MenuTypedList<AtlasMenuItem>
 /**
  * A menu list item which uses single texture atlas.
  */
-class AtlasMenuItem extends MenuItem
+class AtlasMenuItem extends MenuListItem
 {
   var atlas:FlxAtlasFrames;
 
diff --git a/source/funkin/MenuItem.hx b/source/funkin/ui/MenuItem.hx
similarity index 93%
rename from source/funkin/MenuItem.hx
rename to source/funkin/ui/MenuItem.hx
index 261092a1a..ba5cc066b 100644
--- a/source/funkin/MenuItem.hx
+++ b/source/funkin/ui/MenuItem.hx
@@ -1,9 +1,10 @@
-package funkin;
+package funkin.ui;
 
 import flixel.FlxSprite;
 import flixel.graphics.frames.FlxAtlasFrames;
 import flixel.group.FlxSpriteGroup;
 import flixel.math.FlxMath;
+import funkin.util.MathUtil;
 import flixel.util.FlxColor;
 
 class MenuItem extends FlxSpriteGroup
@@ -44,7 +45,7 @@ class MenuItem extends FlxSpriteGroup
   override function update(elapsed:Float)
   {
     super.update(elapsed);
-    y = CoolUtil.coolLerp(y, (targetY * 120) + 480, 0.17);
+    y = MathUtil.coolLerp(y, (targetY * 120) + 480, 0.17);
 
     if (isFlashing) flashingInt += 1;
 
diff --git a/source/funkin/ui/MenuList.hx b/source/funkin/ui/MenuList.hx
index f1de8d40e..3ffe3c330 100644
--- a/source/funkin/ui/MenuList.hx
+++ b/source/funkin/ui/MenuList.hx
@@ -6,7 +6,7 @@ import flixel.group.FlxGroup;
 import flixel.math.FlxPoint;
 import flixel.util.FlxSignal;
 
-class MenuTypedList<T:MenuItem> extends FlxTypedGroup<T>
+class MenuTypedList<T:MenuListItem> extends FlxTypedGroup<T>
 {
   public var selectedIndex(default, null) = 0;
   public var selectedItem(get, never):T;
@@ -206,7 +206,7 @@ class MenuTypedList<T:MenuItem> extends FlxTypedGroup<T>
   }
 }
 
-class MenuItem extends FlxSprite
+class MenuListItem extends FlxSprite
 {
   public var callback:Void->Void;
   public var name:String;
@@ -261,7 +261,7 @@ class MenuItem extends FlxSprite
   }
 }
 
-class MenuTypedItem<T:FlxSprite> extends MenuItem
+class MenuTypedItem<T:FlxSprite> extends MenuListItem
 {
   public var label(default, set):T;
 
diff --git a/source/funkin/MusicBeatState.hx b/source/funkin/ui/MusicBeatState.hx
similarity index 98%
rename from source/funkin/MusicBeatState.hx
rename to source/funkin/ui/MusicBeatState.hx
index 9861c48c7..6d592f438 100644
--- a/source/funkin/MusicBeatState.hx
+++ b/source/funkin/ui/MusicBeatState.hx
@@ -1,6 +1,7 @@
-package funkin;
+package funkin.ui;
 
 import funkin.modding.IScriptedClass.IEventHandler;
+import funkin.ui.mainmenu.MainMenuState;
 import flixel.FlxState;
 import flixel.FlxSubState;
 import flixel.addons.transition.FlxTransitionableState;
diff --git a/source/funkin/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx
similarity index 98%
rename from source/funkin/MusicBeatSubState.hx
rename to source/funkin/ui/MusicBeatSubState.hx
index 53fe19bdd..c4eedc7c6 100644
--- a/source/funkin/MusicBeatSubState.hx
+++ b/source/funkin/ui/MusicBeatSubState.hx
@@ -1,8 +1,9 @@
-package funkin;
+package funkin.ui;
 
 import flixel.addons.transition.FlxTransitionableSubState;
 import flixel.FlxSubState;
 import flixel.text.FlxText;
+import funkin.ui.mainmenu.MainMenuState;
 import flixel.util.FlxColor;
 import funkin.modding.events.ScriptEvent;
 import funkin.modding.IScriptedClass.IEventHandler;
diff --git a/source/funkin/SwagCamera.hx b/source/funkin/ui/SwagCamera.hx
similarity index 87%
rename from source/funkin/SwagCamera.hx
rename to source/funkin/ui/SwagCamera.hx
index 386eaea62..70791d38f 100644
--- a/source/funkin/SwagCamera.hx
+++ b/source/funkin/ui/SwagCamera.hx
@@ -1,8 +1,9 @@
-package funkin;
+package funkin.ui;
 
 import flixel.FlxCamera;
 import flixel.FlxSprite;
 import flixel.math.FlxPoint;
+import funkin.util.MathUtil;
 
 class SwagCamera extends FlxCamera
 {
@@ -92,10 +93,10 @@ class SwagCamera extends FlxCamera
       else
       {
         // THIS THE PART THAT ACTUALLY MATTERS LOL
-        scroll.x = CoolUtil.coolLerp(scroll.x, _scrollTarget.x, followLerp);
-        scroll.y = CoolUtil.coolLerp(scroll.y, _scrollTarget.y, followLerp);
-        // scroll.x += (_scrollTarget.x - scroll.x) * CoolUtil.camLerpShit(followLerp);
-        // scroll.y += (_scrollTarget.y - scroll.y) * CoolUtil.camLerpShit(followLerp);
+        scroll.x = MathUtil.coolLerp(scroll.x, _scrollTarget.x, followLerp);
+        scroll.y = MathUtil.coolLerp(scroll.y, _scrollTarget.y, followLerp);
+        // scroll.x += (_scrollTarget.x - scroll.x) * MathUtil.cameraLerp(followLerp);
+        // scroll.y += (_scrollTarget.y - scroll.y) * MathUtil.cameraLerp(followLerp);
       }
     }
   }
diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx
index 7ef4cb238..ef02a802e 100644
--- a/source/funkin/ui/debug/DebugMenuSubState.hx
+++ b/source/funkin/ui/debug/DebugMenuSubState.hx
@@ -3,9 +3,10 @@ package funkin.ui.debug;
 import flixel.math.FlxPoint;
 import flixel.FlxObject;
 import flixel.FlxSprite;
-import funkin.MusicBeatSubState;
+import funkin.ui.MusicBeatSubState;
 import funkin.ui.TextMenuList;
 import funkin.ui.debug.charting.ChartEditorState;
+import funkin.ui.MusicBeatSubState;
 
 class DebugMenuSubState extends MusicBeatSubState
 {
@@ -85,13 +86,13 @@ class DebugMenuSubState extends MusicBeatSubState
 
   function openAnimationEditor()
   {
-    FlxG.switchState(new funkin.ui.animDebugShit.DebugBoundingState());
+    FlxG.switchState(new funkin.ui.debug.anim.DebugBoundingState());
     trace('Animation Editor');
   }
 
   function testStickers()
   {
-    openSubState(new funkin.ui.StickerSubState());
+    openSubState(new funkin.ui.transition.StickerSubState());
     trace('opened stickers');
   }
 
diff --git a/source/funkin/MemoryCounter.hx b/source/funkin/ui/debug/MemoryCounter.hx
similarity index 97%
rename from source/funkin/MemoryCounter.hx
rename to source/funkin/ui/debug/MemoryCounter.hx
index 658febe59..312d853e7 100644
--- a/source/funkin/MemoryCounter.hx
+++ b/source/funkin/ui/debug/MemoryCounter.hx
@@ -1,4 +1,4 @@
-package funkin;
+package funkin.ui.debug;
 
 import openfl.text.TextFormat;
 import openfl.system.System;
diff --git a/source/funkin/ui/animDebugShit/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx
similarity index 98%
rename from source/funkin/ui/animDebugShit/DebugBoundingState.hx
rename to source/funkin/ui/debug/anim/DebugBoundingState.hx
index 297c44e8e..4e06913b4 100644
--- a/source/funkin/ui/animDebugShit/DebugBoundingState.hx
+++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx
@@ -1,4 +1,4 @@
-package funkin.ui.animDebugShit;
+package funkin.ui.debug.anim;
 
 import funkin.util.SerializerUtil;
 import funkin.play.character.CharacterData;
@@ -15,6 +15,7 @@ import flixel.math.FlxPoint;
 import flixel.sound.FlxSound;
 import flixel.text.FlxText;
 import flixel.util.FlxColor;
+import funkin.util.MouseUtil;
 import flixel.util.FlxSpriteUtil;
 import flixel.util.FlxTimer;
 import funkin.play.character.BaseCharacter;
@@ -25,6 +26,7 @@ import haxe.ui.components.DropDown;
 import haxe.ui.core.Component;
 import haxe.ui.events.ItemEvent;
 import haxe.ui.events.UIEvent;
+import funkin.ui.mainmenu.MainMenuState;
 import lime.utils.Assets as LimeAssets;
 import openfl.Assets;
 import openfl.events.Event;
@@ -32,6 +34,7 @@ import openfl.events.IOErrorEvent;
 import openfl.geom.Rectangle;
 import openfl.net.FileReference;
 import openfl.net.URLLoader;
+import funkin.ui.mainmenu.MainMenuState;
 import openfl.net.URLRequest;
 import openfl.utils.ByteArray;
 import funkin.input.Cursor;
@@ -363,8 +366,8 @@ class DebugBoundingState extends FlxState
 
     if (FlxG.keys.justPressed.F4) FlxG.switchState(new MainMenuState());
 
-    CoolUtil.mouseCamDrag();
-    CoolUtil.mouseWheelZoom();
+    MouseUtil.mouseCamDrag();
+    MouseUtil.mouseWheelZoom();
 
     // bg.scale.x = FlxG.camera.zoom;
     // bg.scale.y = FlxG.camera.zoom;
diff --git a/source/funkin/ui/animDebugShit/FlxAnimateTest.hx b/source/funkin/ui/debug/anim/FlxAnimateTest.hx
similarity index 94%
rename from source/funkin/ui/animDebugShit/FlxAnimateTest.hx
rename to source/funkin/ui/debug/anim/FlxAnimateTest.hx
index 738e109ef..c83d2c370 100644
--- a/source/funkin/ui/animDebugShit/FlxAnimateTest.hx
+++ b/source/funkin/ui/debug/anim/FlxAnimateTest.hx
@@ -1,7 +1,8 @@
-package funkin.ui.animDebugShit;
+package funkin.ui.debug.anim;
 
 import flixel.FlxG;
 import funkin.graphics.adobeanimate.FlxAtlasSprite;
+import funkin.ui.MusicBeatState;
 
 /**
  * A simple test of FlxAnimate.
diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index 366e446e5..abe3ebf6f 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -16,6 +16,7 @@ import flixel.tweens.FlxEase;
 import flixel.tweens.FlxTween;
 import flixel.tweens.misc.VarTween;
 import flixel.util.FlxColor;
+import funkin.ui.mainmenu.MainMenuState;
 import flixel.util.FlxSort;
 import flixel.util.FlxTimer;
 import funkin.audio.visualize.PolygonSpectogram;
@@ -31,7 +32,7 @@ import funkin.input.TurboKeyHandler;
 import funkin.modding.events.ScriptEvent;
 import funkin.play.character.BaseCharacter.CharacterType;
 import funkin.play.character.CharacterData;
-import funkin.play.HealthIcon;
+import funkin.play.components.HealthIcon;
 import funkin.play.notes.NoteSprite;
 import funkin.play.PlayState;
 import funkin.play.song.Song;
diff --git a/source/funkin/ui/CoolStatsGraph.hx b/source/funkin/ui/debug/latency/CoolStatsGraph.hx
similarity index 99%
rename from source/funkin/ui/CoolStatsGraph.hx
rename to source/funkin/ui/debug/latency/CoolStatsGraph.hx
index d3c4c3895..01689f494 100644
--- a/source/funkin/ui/CoolStatsGraph.hx
+++ b/source/funkin/ui/debug/latency/CoolStatsGraph.hx
@@ -1,4 +1,4 @@
-package funkin.ui;
+package funkin.ui.debug.latency;
 
 import flash.display.Graphics;
 import flash.display.Shape;
diff --git a/source/funkin/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx
similarity index 98%
rename from source/funkin/LatencyState.hx
rename to source/funkin/ui/debug/latency/LatencyState.hx
index 7385ca640..7cb18a3de 100644
--- a/source/funkin/LatencyState.hx
+++ b/source/funkin/ui/debug/latency/LatencyState.hx
@@ -1,4 +1,4 @@
-package funkin;
+package funkin.ui.debug.latency;
 
 import funkin.data.notestyle.NoteStyleRegistry;
 import flixel.FlxSprite;
@@ -6,13 +6,14 @@ import flixel.FlxSubState;
 import flixel.group.FlxGroup;
 import flixel.group.FlxGroup.FlxTypedGroup;
 import flixel.math.FlxMath;
+import funkin.ui.MusicBeatSubState;
 import flixel.sound.FlxSound;
 import flixel.system.debug.stats.StatsGraph;
 import flixel.text.FlxText;
 import flixel.util.FlxColor;
 import funkin.audio.visualize.PolygonSpectogram;
 import funkin.play.notes.NoteSprite;
-import funkin.ui.CoolStatsGraph;
+import funkin.ui.debug.latency.CoolStatsGraph;
 import haxe.Timer;
 import openfl.events.KeyboardEvent;
 
diff --git a/source/funkin/ui/stageBuildShit/CharStage.hx b/source/funkin/ui/debug/stage/CharStage.hx
similarity index 81%
rename from source/funkin/ui/stageBuildShit/CharStage.hx
rename to source/funkin/ui/debug/stage/CharStage.hx
index cd13a7251..37e2e1c26 100644
--- a/source/funkin/ui/stageBuildShit/CharStage.hx
+++ b/source/funkin/ui/debug/stage/CharStage.hx
@@ -1,4 +1,4 @@
-package funkin.ui.stageBuildShit;
+package funkin.ui.debug.stage;
 
 class CharStage extends SprStage
 {
diff --git a/source/funkin/ui/stageBuildShit/SprStage.hx b/source/funkin/ui/debug/stage/SprStage.hx
similarity index 97%
rename from source/funkin/ui/stageBuildShit/SprStage.hx
rename to source/funkin/ui/debug/stage/SprStage.hx
index 2229adfe9..e53f3bc26 100644
--- a/source/funkin/ui/stageBuildShit/SprStage.hx
+++ b/source/funkin/ui/debug/stage/SprStage.hx
@@ -1,4 +1,4 @@
-package funkin.ui.stageBuildShit;
+package funkin.ui.debug.stage;
 
 import flixel.FlxSprite;
 import flixel.input.mouse.FlxMouseEvent;
diff --git a/source/funkin/ui/stageBuildShit/StageBuilderState.hx b/source/funkin/ui/debug/stage/StageBuilderState.hx
similarity index 98%
rename from source/funkin/ui/stageBuildShit/StageBuilderState.hx
rename to source/funkin/ui/debug/stage/StageBuilderState.hx
index 31a73ff8f..074914f58 100644
--- a/source/funkin/ui/stageBuildShit/StageBuilderState.hx
+++ b/source/funkin/ui/debug/stage/StageBuilderState.hx
@@ -1,4 +1,4 @@
-package funkin.ui.stageBuildShit;
+package funkin.ui.debug.stage;
 
 import flixel.FlxCamera;
 import flixel.FlxSprite;
@@ -7,10 +7,12 @@ import flixel.group.FlxGroup;
 import flixel.input.mouse.FlxMouseButton.FlxMouseButtonID;
 import flixel.input.mouse.FlxMouseEvent;
 import flixel.math.FlxPoint;
+import funkin.ui.MusicBeatState;
 import flixel.text.FlxText;
 import flixel.ui.FlxButton;
 import flixel.util.FlxColor;
 import flixel.util.FlxSort;
+import funkin.util.MouseUtil;
 import flixel.util.FlxTimer;
 
 class StageBuilderState extends MusicBeatState
@@ -185,9 +187,9 @@ class StageBuilderState extends MusicBeatState
       if (curSelectedSpr != null) sprGrp.remove(curSelectedSpr, true);
     }
 
-    CoolUtil.mouseCamDrag();
+    MouseUtil.mouseCamDrag();
 
-    if (FlxG.keys.pressed.CONTROL) CoolUtil.mouseWheelZoom();
+    if (FlxG.keys.pressed.CONTROL) MouseUtil.mouseWheelZoom();
 
     if (isShaking)
     {
diff --git a/source/funkin/ui/stageBuildShit/StageEditorCommand.hx b/source/funkin/ui/debug/stage/StageEditorCommand.hx
similarity index 95%
rename from source/funkin/ui/stageBuildShit/StageEditorCommand.hx
rename to source/funkin/ui/debug/stage/StageEditorCommand.hx
index d61281e07..ff59f67e5 100644
--- a/source/funkin/ui/stageBuildShit/StageEditorCommand.hx
+++ b/source/funkin/ui/debug/stage/StageEditorCommand.hx
@@ -1,6 +1,6 @@
-package funkin.ui.stageBuildShit;
+package funkin.ui.debug.stage;
 
-import funkin.ui.stageBuildShit.StageOffsetSubState;
+import funkin.ui.debug.stage.StageOffsetSubState;
 import flixel.FlxSprite;
 
 /**
diff --git a/source/funkin/ui/stageBuildShit/StageOffsetSubState.hx b/source/funkin/ui/debug/stage/StageOffsetSubState.hx
similarity index 97%
rename from source/funkin/ui/stageBuildShit/StageOffsetSubState.hx
rename to source/funkin/ui/debug/stage/StageOffsetSubState.hx
index a6aa6fa68..68546f1c7 100644
--- a/source/funkin/ui/stageBuildShit/StageOffsetSubState.hx
+++ b/source/funkin/ui/debug/stage/StageOffsetSubState.hx
@@ -1,4 +1,4 @@
-package funkin.ui.stageBuildShit;
+package funkin.ui.debug.stage;
 
 import flixel.FlxSprite;
 import flixel.input.mouse.FlxMouseEvent;
@@ -7,10 +7,11 @@ import funkin.play.character.BaseCharacter;
 import funkin.play.PlayState;
 import funkin.play.stage.StageData;
 import funkin.play.stage.StageProp;
-import funkin.shaderslmfao.StrokeShader;
+import funkin.graphics.shaders.StrokeShader;
 import funkin.ui.haxeui.HaxeUISubState;
-import funkin.ui.stageBuildShit.StageEditorCommand;
+import funkin.ui.debug.stage.StageEditorCommand;
 import funkin.util.SerializerUtil;
+import funkin.util.MouseUtil;
 import haxe.ui.containers.ListView;
 import haxe.ui.core.Component;
 import haxe.ui.events.UIEvent;
@@ -28,7 +29,7 @@ import openfl.net.FileReference;
  * @author ninjamuffin99
  */
 // Give other classes access to private instance fields
-@:allow(funkin.ui.stageBuildShit.StageEditorCommand)
+@:allow(funkin.ui.debug.stage.StageEditorCommand)
 class StageOffsetSubState extends HaxeUISubState
 {
   var uiStuff:Component;
@@ -244,9 +245,9 @@ class StageOffsetSubState extends HaxeUISubState
 
     FlxG.mouse.visible = true;
 
-    CoolUtil.mouseCamDrag();
+    MouseUtil.mouseCamDrag();
 
-    if (FlxG.keys.pressed.CONTROL) CoolUtil.mouseWheelZoom();
+    if (FlxG.keys.pressed.CONTROL) MouseUtil.mouseWheelZoom();
 
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.Z) undoLastCommand();
 
diff --git a/source/funkin/ui/stageBuildShit/StagetoolBar.hx b/source/funkin/ui/debug/stage/StagetoolBar.hx
similarity index 67%
rename from source/funkin/ui/stageBuildShit/StagetoolBar.hx
rename to source/funkin/ui/debug/stage/StagetoolBar.hx
index 1a443f42a..243fd3f69 100644
--- a/source/funkin/ui/stageBuildShit/StagetoolBar.hx
+++ b/source/funkin/ui/debug/stage/StagetoolBar.hx
@@ -1,4 +1,4 @@
-package funkin.ui.stageBuildShit;
+package funkin.ui.debug.stage;
 
 import flixel.group.FlxGroup;
 
@@ -10,13 +10,5 @@ class StagetoolBar extends FlxGroup
   public function new()
   {
     super();
-
-    for (icon in icons)
-    {
-      // switch (icon)
-      // {
-      // case SELECT:
-      // }
-    }
   }
 }
diff --git a/source/funkin/freeplayStuff/BGScrollingText.hx b/source/funkin/ui/freeplay/BGScrollingText.hx
similarity index 98%
rename from source/funkin/freeplayStuff/BGScrollingText.hx
rename to source/funkin/ui/freeplay/BGScrollingText.hx
index 586f83822..5511959f5 100644
--- a/source/funkin/freeplayStuff/BGScrollingText.hx
+++ b/source/funkin/ui/freeplay/BGScrollingText.hx
@@ -1,4 +1,4 @@
-package funkin.freeplayStuff;
+package funkin.ui.freeplay;
 
 import flixel.FlxObject;
 import flixel.group.FlxGroup.FlxTypedGroup;
diff --git a/source/funkin/freeplayStuff/CapsuleText.hx b/source/funkin/ui/freeplay/CapsuleText.hx
similarity index 93%
rename from source/funkin/freeplayStuff/CapsuleText.hx
rename to source/funkin/ui/freeplay/CapsuleText.hx
index dda687f5e..1a5a0a335 100644
--- a/source/funkin/freeplayStuff/CapsuleText.hx
+++ b/source/funkin/ui/freeplay/CapsuleText.hx
@@ -1,9 +1,9 @@
-package funkin.freeplayStuff;
+package funkin.ui.freeplay;
 
 import openfl.filters.BitmapFilterQuality;
 import flixel.text.FlxText;
 import flixel.group.FlxSpriteGroup;
-import funkin.shaderslmfao.GaussianBlurShader;
+import funkin.graphics.shaders.GaussianBlurShader;
 
 class CapsuleText extends FlxSpriteGroup
 {
diff --git a/source/funkin/freeplayStuff/DJBoyfriend.hx b/source/funkin/ui/freeplay/DJBoyfriend.hx
similarity index 99%
rename from source/funkin/freeplayStuff/DJBoyfriend.hx
rename to source/funkin/ui/freeplay/DJBoyfriend.hx
index ba0ce464d..2417cdf9a 100644
--- a/source/funkin/freeplayStuff/DJBoyfriend.hx
+++ b/source/funkin/ui/freeplay/DJBoyfriend.hx
@@ -1,4 +1,4 @@
-package funkin.freeplayStuff;
+package funkin.ui.freeplay;
 
 import flixel.FlxSprite;
 import flixel.util.FlxSignal;
diff --git a/source/funkin/freeplayStuff/DifficultyStars.hx b/source/funkin/ui/freeplay/DifficultyStars.hx
similarity index 96%
rename from source/funkin/freeplayStuff/DifficultyStars.hx
rename to source/funkin/ui/freeplay/DifficultyStars.hx
index 8611727be..51526bcbe 100644
--- a/source/funkin/freeplayStuff/DifficultyStars.hx
+++ b/source/funkin/ui/freeplay/DifficultyStars.hx
@@ -1,8 +1,8 @@
-package funkin.freeplayStuff;
+package funkin.ui.freeplay;
 
 import flixel.group.FlxSpriteGroup;
 import funkin.graphics.adobeanimate.FlxAtlasSprite;
-import funkin.shaderslmfao.HSVShader;
+import funkin.graphics.shaders.HSVShader;
 
 class DifficultyStars extends FlxSpriteGroup
 {
diff --git a/source/funkin/freeplayStuff/FreeplayFlames.hx b/source/funkin/ui/freeplay/FreeplayFlames.hx
similarity index 98%
rename from source/funkin/freeplayStuff/FreeplayFlames.hx
rename to source/funkin/ui/freeplay/FreeplayFlames.hx
index 8f54d210b..a116fb813 100644
--- a/source/funkin/freeplayStuff/FreeplayFlames.hx
+++ b/source/funkin/ui/freeplay/FreeplayFlames.hx
@@ -1,4 +1,4 @@
-package funkin.freeplayStuff;
+package funkin.ui.freeplay;
 
 import flixel.group.FlxSpriteGroup;
 import flixel.FlxSprite;
diff --git a/source/funkin/freeplayStuff/FreeplayScore.hx b/source/funkin/ui/freeplay/FreeplayScore.hx
similarity index 98%
rename from source/funkin/freeplayStuff/FreeplayScore.hx
rename to source/funkin/ui/freeplay/FreeplayScore.hx
index ec8f4baa7..e266efca1 100644
--- a/source/funkin/freeplayStuff/FreeplayScore.hx
+++ b/source/funkin/ui/freeplay/FreeplayScore.hx
@@ -1,4 +1,4 @@
-package funkin.freeplayStuff;
+package funkin.ui.freeplay;
 
 import flixel.FlxSprite;
 import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
diff --git a/source/funkin/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx
similarity index 97%
rename from source/funkin/FreeplayState.hx
rename to source/funkin/ui/freeplay/FreeplayState.hx
index 918e7c725..5c8c35753 100644
--- a/source/funkin/FreeplayState.hx
+++ b/source/funkin/ui/freeplay/FreeplayState.hx
@@ -1,6 +1,5 @@
-package funkin;
+package funkin.ui.freeplay;
 
-import funkin.play.song.Song;
 import flash.text.TextField;
 import flixel.addons.display.FlxGridOverlay;
 import flixel.addons.transition.FlxTransitionableState;
@@ -26,24 +25,31 @@ import flixel.util.FlxTimer;
 import funkin.Controls.Control;
 import funkin.data.level.LevelRegistry;
 import funkin.data.song.SongRegistry;
-import funkin.freeplayStuff.BGScrollingText;
-import funkin.freeplayStuff.DifficultyStars;
-import funkin.freeplayStuff.DJBoyfriend;
-import funkin.freeplayStuff.FreeplayScore;
-import funkin.freeplayStuff.LetterSort;
-import funkin.freeplayStuff.SongMenuItem;
 import funkin.graphics.adobeanimate.FlxAtlasSprite;
-import funkin.play.HealthIcon;
+import funkin.graphics.shaders.AngleMask;
+import funkin.graphics.shaders.HSVShader;
+import funkin.graphics.shaders.PureColor;
+import funkin.util.MathUtil;
+import funkin.graphics.shaders.StrokeShader;
+import funkin.play.components.HealthIcon;
 import funkin.play.PlayState;
 import funkin.play.PlayStatePlaylist;
 import funkin.play.song.Song;
+import funkin.play.song.Song;
 import funkin.save.Save;
 import funkin.save.Save.SaveScoreData;
-import funkin.shaderslmfao.AngleMask;
-import funkin.shaderslmfao.HSVShader;
-import funkin.shaderslmfao.PureColor;
-import funkin.shaderslmfao.StrokeShader;
-import funkin.ui.StickerSubState;
+import funkin.ui.freeplay.BGScrollingText;
+import funkin.ui.freeplay.DifficultyStars;
+import funkin.ui.freeplay.DJBoyfriend;
+import funkin.ui.freeplay.FreeplayScore;
+import funkin.ui.freeplay.LetterSort;
+import funkin.ui.freeplay.SongMenuItem;
+import funkin.ui.MusicBeatState;
+import funkin.ui.MusicBeatSubState;
+import funkin.ui.mainmenu.MainMenuState;
+import funkin.ui.transition.LoadingState;
+import funkin.ui.transition.StickerSubState;
+import funkin.util.MathUtil;
 import lime.app.Future;
 import lime.utils.Assets;
 
@@ -664,8 +670,8 @@ class FreeplayState extends MusicBeatSubState
       }
     }
 
-    lerpScore = CoolUtil.coolLerp(lerpScore, intendedScore, 0.2);
-    lerpCompletion = CoolUtil.coolLerp(lerpCompletion, intendedCompletion, 0.9);
+    lerpScore = MathUtil.coolLerp(lerpScore, intendedScore, 0.2);
+    lerpCompletion = MathUtil.coolLerp(lerpCompletion, intendedCompletion, 0.9);
 
     fp.updateScore(Std.int(lerpScore));
 
diff --git a/source/funkin/freeplayStuff/LetterSort.hx b/source/funkin/ui/freeplay/LetterSort.hx
similarity index 99%
rename from source/funkin/freeplayStuff/LetterSort.hx
rename to source/funkin/ui/freeplay/LetterSort.hx
index e6d923c90..a66b386ee 100644
--- a/source/funkin/freeplayStuff/LetterSort.hx
+++ b/source/funkin/ui/freeplay/LetterSort.hx
@@ -1,4 +1,4 @@
-package funkin.freeplayStuff;
+package funkin.ui.freeplay;
 
 import flixel.FlxSprite;
 import flixel.group.FlxGroup.FlxTypedGroup;
diff --git a/source/funkin/freeplayStuff/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx
similarity index 96%
rename from source/funkin/freeplayStuff/SongMenuItem.hx
rename to source/funkin/ui/freeplay/SongMenuItem.hx
index 06de92886..477047c68 100644
--- a/source/funkin/freeplayStuff/SongMenuItem.hx
+++ b/source/funkin/ui/freeplay/SongMenuItem.hx
@@ -1,8 +1,8 @@
-package funkin.freeplayStuff;
+package funkin.ui.freeplay;
 
-import funkin.FreeplayState.FreeplaySongData;
-import funkin.shaderslmfao.HSVShader;
-import funkin.shaderslmfao.GaussianBlurShader;
+import funkin.ui.freeplay.FreeplayState.FreeplaySongData;
+import funkin.graphics.shaders.HSVShader;
+import funkin.graphics.shaders.GaussianBlurShader;
 import flixel.group.FlxGroup;
 import flixel.FlxSprite;
 import flixel.graphics.frames.FlxAtlasFrames;
@@ -12,7 +12,8 @@ import flixel.math.FlxMath;
 import flixel.math.FlxPoint;
 import flixel.text.FlxText;
 import flixel.util.FlxTimer;
-import funkin.shaderslmfao.Grayscale;
+import funkin.util.MathUtil;
+import funkin.graphics.shaders.Grayscale;
 
 class SongMenuItem extends FlxSpriteGroup
 {
@@ -312,8 +313,8 @@ class SongMenuItem extends FlxSpriteGroup
 
     if (doLerp)
     {
-      x = CoolUtil.coolLerp(x, targetPos.x, 0.3);
-      y = CoolUtil.coolLerp(y, targetPos.y, 0.4);
+      x = MathUtil.coolLerp(x, targetPos.x, 0.3);
+      y = MathUtil.coolLerp(y, targetPos.y, 0.4);
     }
 
     super.update(elapsed);
diff --git a/source/funkin/ui/haxeui/HaxeUIState.hx b/source/funkin/ui/haxeui/HaxeUIState.hx
index d9d00dd23..fa95b2d1d 100644
--- a/source/funkin/ui/haxeui/HaxeUIState.hx
+++ b/source/funkin/ui/haxeui/HaxeUIState.hx
@@ -5,6 +5,7 @@ import haxe.ui.containers.menus.MenuCheckBox;
 import haxe.ui.containers.menus.MenuItem;
 import haxe.ui.core.Component;
 import haxe.ui.core.Screen;
+import funkin.ui.MusicBeatState;
 import haxe.ui.events.MouseEvent;
 import haxe.ui.events.UIEvent;
 import haxe.ui.RuntimeComponentBuilder;
diff --git a/source/funkin/ui/haxeui/HaxeUISubState.hx b/source/funkin/ui/haxeui/HaxeUISubState.hx
index ba218f37c..82c15be4c 100644
--- a/source/funkin/ui/haxeui/HaxeUISubState.hx
+++ b/source/funkin/ui/haxeui/HaxeUISubState.hx
@@ -4,6 +4,9 @@ import haxe.ui.RuntimeComponentBuilder;
 import haxe.ui.components.CheckBox;
 import haxe.ui.containers.menus.MenuCheckBox;
 import haxe.ui.core.Component;
+import funkin.ui.MusicBeatState;
+import funkin.ui.mainmenu.MainMenuState;
+import funkin.ui.MusicBeatSubState;
 import haxe.ui.events.MouseEvent;
 import haxe.ui.events.UIEvent;
 
diff --git a/source/funkin/ui/haxeui/components/README.md b/source/funkin/ui/haxeui/components/README.md
index f051a6236..90f8ab553 100644
--- a/source/funkin/ui/haxeui/components/README.md
+++ b/source/funkin/ui/haxeui/components/README.md
@@ -1,3 +1,3 @@
 # funkin.ui.haxeui.components
 
-Since there is a line in `source/module.xml` pointing to this folder, all components in this folder will automatically be accessible in any HaxeUI layouts.
\ No newline at end of file
+Since there is a line in `source/module.xml` pointing to this folder, all components in this folder will automatically be accessible in any HaxeUI layouts.
diff --git a/source/funkin/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx
similarity index 97%
rename from source/funkin/MainMenuState.hx
rename to source/funkin/ui/mainmenu/MainMenuState.hx
index 7267a6da8..769493c45 100644
--- a/source/funkin/MainMenuState.hx
+++ b/source/funkin/ui/mainmenu/MainMenuState.hx
@@ -1,4 +1,4 @@
-package funkin;
+package funkin.ui.mainmenu;
 
 import flixel.addons.transition.FlxTransitionableSubState;
 import funkin.ui.debug.DebugMenuSubState;
@@ -13,8 +13,10 @@ import flixel.input.touch.FlxTouch;
 import flixel.text.FlxText;
 import flixel.tweens.FlxEase;
 import flixel.tweens.FlxTween;
+import funkin.ui.MusicBeatState;
 import flixel.util.FlxTimer;
 import funkin.ui.AtlasMenuList;
+import funkin.ui.freeplay.FreeplayState;
 import funkin.ui.MenuList;
 import funkin.ui.title.TitleState;
 import funkin.ui.story.StoryMenuState;
@@ -108,7 +110,7 @@ class MainMenuState extends MusicBeatState
     #end
 
     createMenuItem('options', 'mainmenu/options', function() {
-      startExitState(new funkin.ui.OptionsState());
+      startExitState(new funkin.ui.options.OptionsState());
     });
 
     // Reset position of menu items.
@@ -187,7 +189,7 @@ class MainMenuState extends MusicBeatState
     // #end
   }
 
-  function onMenuItemChange(selected:MenuItem)
+  function onMenuItemChange(selected:MenuListItem)
   {
     camFollow.setPosition(selected.getGraphicMidpoint().x, selected.getGraphicMidpoint().y);
   }
diff --git a/source/funkin/ButtonRemapSubstate.hx b/source/funkin/ui/options/ButtonRemapSubstate.hx
similarity index 82%
rename from source/funkin/ButtonRemapSubstate.hx
rename to source/funkin/ui/options/ButtonRemapSubstate.hx
index 8905ec8ba..b692dbe82 100644
--- a/source/funkin/ButtonRemapSubstate.hx
+++ b/source/funkin/ui/options/ButtonRemapSubstate.hx
@@ -1,4 +1,4 @@
-package funkin;
+package funkin.ui.options;
 
 import flixel.FlxSubState;
 
diff --git a/source/funkin/ui/ColorsMenu.hx b/source/funkin/ui/options/ColorsMenu.hx
similarity index 96%
rename from source/funkin/ui/ColorsMenu.hx
rename to source/funkin/ui/options/ColorsMenu.hx
index 6a844eef3..928f74ba8 100644
--- a/source/funkin/ui/ColorsMenu.hx
+++ b/source/funkin/ui/options/ColorsMenu.hx
@@ -1,11 +1,11 @@
-package funkin.ui;
+package funkin.ui.options;
 
 import funkin.data.notestyle.NoteStyleRegistry;
 import flixel.addons.effects.chainable.FlxEffectSprite;
 import flixel.addons.effects.chainable.FlxOutlineEffect;
 import flixel.group.FlxGroup.FlxTypedGroup;
 import flixel.util.FlxColor;
-import funkin.ui.OptionsState.Page;
+import funkin.ui.options.OptionsState.Page;
 import funkin.play.notes.NoteSprite;
 
 class ColorsMenu extends Page
diff --git a/source/funkin/ui/ControlsMenu.hx b/source/funkin/ui/options/ControlsMenu.hx
similarity index 98%
rename from source/funkin/ui/ControlsMenu.hx
rename to source/funkin/ui/options/ControlsMenu.hx
index 8197424ee..2aee473d3 100644
--- a/source/funkin/ui/ControlsMenu.hx
+++ b/source/funkin/ui/options/ControlsMenu.hx
@@ -1,5 +1,6 @@
-package funkin.ui;
+package funkin.ui.options;
 
+import funkin.util.InputUtil;
 import flixel.FlxCamera;
 import flixel.FlxObject;
 import flixel.FlxSprite;
@@ -12,7 +13,7 @@ import funkin.ui.AtlasText;
 import funkin.ui.MenuList;
 import funkin.ui.TextMenuList;
 
-class ControlsMenu extends funkin.ui.OptionsState.Page
+class ControlsMenu extends funkin.ui.options.OptionsState.Page
 {
   public static inline final COLUMNS = 2;
   static var controlList = Control.createAll();
@@ -456,6 +457,6 @@ class InputItem extends TextMenuItem
 
   public function getLabel(input:Int)
   {
-    return input == FlxKey.NONE ? "---" : InputFormatter.format(input, device);
+    return input == FlxKey.NONE ? "---" : InputUtil.format(input, device);
   }
 }
diff --git a/source/funkin/ui/ModMenu.hx b/source/funkin/ui/options/ModMenu.hx
similarity index 97%
rename from source/funkin/ui/ModMenu.hx
rename to source/funkin/ui/options/ModMenu.hx
index 769d3eca2..574a93c49 100644
--- a/source/funkin/ui/ModMenu.hx
+++ b/source/funkin/ui/options/ModMenu.hx
@@ -1,11 +1,11 @@
-package funkin.ui;
+package funkin.ui.options;
 
 import funkin.modding.PolymodHandler;
 import flixel.group.FlxGroup.FlxTypedGroup;
 import flixel.text.FlxText;
 import flixel.util.FlxColor;
 import polymod.Polymod;
-import funkin.ui.OptionsState.Page;
+import funkin.ui.options.OptionsState.Page;
 
 class ModMenu extends Page
 {
diff --git a/source/funkin/ui/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx
similarity index 98%
rename from source/funkin/ui/OptionsState.hx
rename to source/funkin/ui/options/OptionsState.hx
index 6c32c7f4c..72bb6c60c 100644
--- a/source/funkin/ui/OptionsState.hx
+++ b/source/funkin/ui/options/OptionsState.hx
@@ -1,10 +1,12 @@
-package funkin.ui;
+package funkin.ui.options;
 
 import flixel.FlxSprite;
 import flixel.FlxSubState;
 import flixel.addons.transition.FlxTransitionableState;
 import flixel.group.FlxGroup;
 import flixel.util.FlxSignal;
+import funkin.ui.mainmenu.MainMenuState;
+import funkin.ui.MusicBeatState;
 import funkin.util.WindowUtil;
 
 class OptionsState extends MusicBeatState
diff --git a/source/funkin/ui/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx
similarity index 98%
rename from source/funkin/ui/PreferencesMenu.hx
rename to source/funkin/ui/options/PreferencesMenu.hx
index 812d0ab49..b4b3c7db8 100644
--- a/source/funkin/ui/PreferencesMenu.hx
+++ b/source/funkin/ui/options/PreferencesMenu.hx
@@ -1,11 +1,11 @@
-package funkin.ui;
+package funkin.ui.options;
 
 import flixel.FlxCamera;
 import flixel.FlxObject;
 import flixel.FlxSprite;
 import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
 import funkin.ui.AtlasText.AtlasFont;
-import funkin.ui.OptionsState.Page;
+import funkin.ui.options.OptionsState.Page;
 import funkin.ui.TextMenuList.TextMenuItem;
 
 class PreferencesMenu extends Page
diff --git a/source/funkin/ui/story/LevelTitle.hx b/source/funkin/ui/story/LevelTitle.hx
index e1765d453..e6f989016 100644
--- a/source/funkin/ui/story/LevelTitle.hx
+++ b/source/funkin/ui/story/LevelTitle.hx
@@ -4,7 +4,7 @@ import flixel.FlxSprite;
 import flixel.graphics.frames.FlxAtlasFrames;
 import flixel.group.FlxSpriteGroup;
 import flixel.util.FlxColor;
-import funkin.CoolUtil;
+import funkin.util.MathUtil;
 
 class LevelTitle extends FlxSpriteGroup
 {
@@ -54,7 +54,7 @@ class LevelTitle extends FlxSpriteGroup
 
   public override function update(elapsed:Float):Void
   {
-    this.y = CoolUtil.coolLerp(y, targetY, 0.17);
+    this.y = MathUtil.coolLerp(y, targetY, 0.17);
 
     if (isFlashing) flashingInt += 1;
     if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) title.color = 0xFF33ffff;
diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx
index 09b9cb600..e5bb6c34c 100644
--- a/source/funkin/ui/story/StoryMenuState.hx
+++ b/source/funkin/ui/story/StoryMenuState.hx
@@ -1,5 +1,6 @@
 package funkin.ui.story;
 
+import funkin.ui.mainmenu.MainMenuState;
 import funkin.save.Save;
 import funkin.save.Save.SaveScoreData;
 import openfl.utils.Assets;
@@ -9,6 +10,7 @@ import flixel.group.FlxGroup.FlxTypedGroup;
 import flixel.text.FlxText;
 import flixel.addons.transition.FlxTransitionableState;
 import flixel.tweens.FlxEase;
+import funkin.ui.MusicBeatState;
 import flixel.tweens.FlxTween;
 import flixel.util.FlxColor;
 import flixel.util.FlxTimer;
@@ -17,9 +19,13 @@ import funkin.modding.events.ScriptEvent;
 import funkin.modding.events.ScriptEventDispatcher;
 import funkin.play.PlayState;
 import funkin.play.PlayStatePlaylist;
+import funkin.ui.mainmenu.MainMenuState;
 import funkin.play.song.Song;
 import funkin.data.song.SongData.SongMusicData;
 import funkin.data.song.SongRegistry;
+import funkin.util.MathUtil;
+import funkin.ui.transition.LoadingState;
+import funkin.ui.transition.StickerSubState;
 
 class StoryMenuState extends MusicBeatState
 {
@@ -313,7 +319,7 @@ class StoryMenuState extends MusicBeatState
   {
     Conductor.update();
 
-    highScoreLerp = Std.int(CoolUtil.coolLerp(highScoreLerp, highScore, 0.5));
+    highScoreLerp = Std.int(MathUtil.coolLerp(highScoreLerp, highScore, 0.5));
 
     scoreText.text = 'LEVEL SCORE: ${Math.round(highScoreLerp)}';
 
diff --git a/source/funkin/ui/title/AttractState.hx b/source/funkin/ui/title/AttractState.hx
index 67c762da4..38cff7cc8 100644
--- a/source/funkin/ui/title/AttractState.hx
+++ b/source/funkin/ui/title/AttractState.hx
@@ -5,6 +5,7 @@ import funkin.graphics.video.FlxVideo;
 #else
 import hxcodec.flixel.FlxVideoSprite;
 #end
+import funkin.ui.MusicBeatState;
 
 /**
  * After about 2 minutes of inactivity on the title screen,
diff --git a/source/funkin/ui/title/FlxSpriteOverlay.hx b/source/funkin/ui/title/FlxSpriteOverlay.hx
index ddf58bbfd..1900e25f0 100644
--- a/source/funkin/ui/title/FlxSpriteOverlay.hx
+++ b/source/funkin/ui/title/FlxSpriteOverlay.hx
@@ -1,7 +1,7 @@
 package funkin.ui.title;
 
 import flixel.FlxSprite;
-import funkin.shaderslmfao.BlendModesShader;
+import funkin.graphics.shaders.BlendModesShader;
 import openfl.display.BitmapData;
 import flixel.FlxCamera;
 import flixel.FlxG;
diff --git a/source/funkin/OutdatedSubState.hx b/source/funkin/ui/title/OutdatedSubState.hx
similarity index 95%
rename from source/funkin/OutdatedSubState.hx
rename to source/funkin/ui/title/OutdatedSubState.hx
index 7684e5ae4..d262fc4e4 100644
--- a/source/funkin/OutdatedSubState.hx
+++ b/source/funkin/ui/title/OutdatedSubState.hx
@@ -1,9 +1,10 @@
-package funkin;
+package funkin.ui.title;
 
 import flixel.FlxSprite;
 import flixel.FlxSubState;
 import flixel.text.FlxText;
 import flixel.util.FlxColor;
+import funkin.ui.MusicBeatState;
 import lime.app.Application;
 
 #if newgrounds
diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx
index 9820e4ecc..da3ba6c89 100644
--- a/source/funkin/ui/title/TitleState.hx
+++ b/source/funkin/ui/title/TitleState.hx
@@ -9,20 +9,25 @@ import flixel.tweens.FlxTween;
 import flixel.util.FlxColor;
 import flixel.util.FlxDirectionFlags;
 import flixel.util.FlxTimer;
-import funkin.audiovis.SpectogramSprite;
-import funkin.shaderslmfao.ColorSwap;
-import funkin.shaderslmfao.LeftMaskShader;
+import funkin.audio.visualize.SpectogramSprite;
+import funkin.graphics.shaders.ColorSwap;
+import funkin.graphics.shaders.LeftMaskShader;
 import funkin.data.song.SongRegistry;
+import funkin.ui.MusicBeatState;
 import funkin.data.song.SongData.SongMusicData;
-import funkin.shaderslmfao.TitleOutline;
+import funkin.graphics.shaders.TitleOutline;
+import funkin.ui.freeplay.FreeplayState;
 import funkin.ui.AtlasText;
 import openfl.Assets;
 import openfl.display.Sprite;
 import openfl.events.AsyncErrorEvent;
+import funkin.ui.mainmenu.MainMenuState;
 import openfl.events.MouseEvent;
 import openfl.events.NetStatusEvent;
+import funkin.ui.freeplay.FreeplayState;
 import openfl.media.Video;
 import openfl.net.NetStream;
+import funkin.api.newgrounds.NGio;
 import openfl.display.BlendMode;
 
 #if desktop
@@ -167,10 +172,6 @@ class TitleState extends MusicBeatState
       credGroup.add(textGroup);
     }
 
-    // var atlasBullShit:FlxSprite = new FlxSprite();
-    // atlasBullShit.frames = CoolUtil.fromAnimate(Paths.image('money'), Paths.file('images/money.json'));
-    // credGroup.add(atlasBullShit);
-
     ngSpr = new FlxSprite(0, FlxG.height * 0.52);
 
     if (FlxG.random.bool(1))
diff --git a/source/funkin/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx
similarity index 89%
rename from source/funkin/LoadingState.hx
rename to source/funkin/ui/transition/LoadingState.hx
index 216d9ba74..69590bfe3 100644
--- a/source/funkin/LoadingState.hx
+++ b/source/funkin/ui/transition/LoadingState.hx
@@ -1,18 +1,24 @@
-package funkin;
+package funkin.ui.transition;
 
 import funkin.play.PlayStatePlaylist;
 import flixel.FlxSprite;
 import flixel.FlxState;
+import funkin.graphics.shaders.ScreenWipeShader;
 import flixel.math.FlxMath;
 import flixel.util.FlxTimer;
 import funkin.play.PlayState;
 import haxe.io.Path;
 import lime.app.Future;
+import flixel.tweens.FlxTween;
+import funkin.ui.MusicBeatState;
 import lime.app.Promise;
 import lime.utils.AssetLibrary;
+import flixel.tweens.FlxEase;
 import lime.utils.AssetManifest;
 import lime.utils.Assets as LimeAssets;
 import openfl.utils.Assets;
+import funkin.ui.mainmenu.MainMenuState;
+import openfl.filters.ShaderFilter;
 
 class LoadingState extends MusicBeatState
 {
@@ -321,4 +327,21 @@ class MultiCallback
 
   public function getUnfired():Array<Void->Void>
     return unfired.array();
+
+  public static function coolSwitchState(state:FlxState, transitionTex:String = "shaderTransitionStuff/coolDots", time:Float = 2)
+  {
+    var screenShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("shaderTransitionStuff/coolDots"));
+    var screenWipeShit:ScreenWipeShader = new ScreenWipeShader();
+
+    screenWipeShit.funnyShit.input = screenShit.pixels;
+    FlxTween.tween(screenWipeShit, {daAlphaShit: 1}, time,
+      {
+        ease: FlxEase.quadInOut,
+        onComplete: function(twn) {
+          screenShit.destroy();
+          FlxG.switchState(new MainMenuState());
+        }
+      });
+    FlxG.camera.setFilters([new ShaderFilter(screenWipeShit)]);
+  }
 }
diff --git a/source/funkin/ui/StickerSubState.hx b/source/funkin/ui/transition/StickerSubState.hx
similarity index 98%
rename from source/funkin/ui/StickerSubState.hx
rename to source/funkin/ui/transition/StickerSubState.hx
index a4e3a6acb..1c012e00c 100644
--- a/source/funkin/ui/StickerSubState.hx
+++ b/source/funkin/ui/transition/StickerSubState.hx
@@ -1,9 +1,10 @@
-package funkin.ui;
+package funkin.ui.transition;
 
 import flixel.FlxSprite;
 import haxe.Json;
 import lime.utils.Assets;
 // import flxtyped group
+import funkin.ui.MusicBeatSubState;
 import funkin.ui.story.StoryMenuState;
 import flixel.group.FlxGroup.FlxTypedGroup;
 import flixel.util.FlxTimer;
@@ -11,8 +12,10 @@ import flixel.FlxG;
 import flixel.math.FlxMath;
 import flixel.util.FlxSort;
 import flixel.util.FlxSignal;
+import funkin.ui.mainmenu.MainMenuState;
 import flixel.addons.transition.FlxTransitionableState;
 import openfl.display.BitmapData;
+import funkin.ui.freeplay.FreeplayState;
 import openfl.geom.Matrix;
 import openfl.display.Sprite;
 import openfl.display.Bitmap;
diff --git a/source/funkin/util/BezierUtil.hx b/source/funkin/util/BezierUtil.hx
index b3cf51d1d..37d91223b 100644
--- a/source/funkin/util/BezierUtil.hx
+++ b/source/funkin/util/BezierUtil.hx
@@ -2,6 +2,9 @@ package funkin.util;
 
 import flixel.math.FlxPoint;
 
+/**
+ * Utilities for performing math with bezier curves.
+ */
 class BezierUtil
 {
   /**
diff --git a/source/funkin/util/DateUtil.hx b/source/funkin/util/DateUtil.hx
index 72838477c..2d08fd48b 100644
--- a/source/funkin/util/DateUtil.hx
+++ b/source/funkin/util/DateUtil.hx
@@ -1,5 +1,8 @@
 package funkin.util;
 
+/**
+ * Utilities for performing operations on dates.
+ */
 class DateUtil
 {
   public static function generateTimestamp(?date:Date = null):String
diff --git a/source/funkin/util/FlxGamepadUtil.hx b/source/funkin/util/FlxGamepadUtil.hx
index d768b42c4..7e72e7138 100644
--- a/source/funkin/util/FlxGamepadUtil.hx
+++ b/source/funkin/util/FlxGamepadUtil.hx
@@ -6,6 +6,9 @@ import lime.ui.Gamepad as LimeGamepad;
 import lime.ui.GamepadAxis as LimeGamepadAxis;
 import lime.ui.GamepadButton as LimeGamepadButton;
 
+/**
+ * Utilities for working with Flixel gamepads.
+ */
 class FlxGamepadUtil
 {
   public static function getInputID(gamepad:FlxGamepad, button:LimeGamepadButton):FlxGamepadInputID
diff --git a/source/funkin/InputFormatter.hx b/source/funkin/util/InputUtil.hx
similarity index 96%
rename from source/funkin/InputFormatter.hx
rename to source/funkin/util/InputUtil.hx
index 2a7011f64..97478294a 100644
--- a/source/funkin/InputFormatter.hx
+++ b/source/funkin/util/InputUtil.hx
@@ -1,4 +1,4 @@
-package funkin;
+package funkin.util;
 
 import funkin.Controls;
 import flixel.input.gamepad.FlxGamepad;
@@ -7,9 +7,12 @@ import flixel.input.keyboard.FlxKey;
 
 using flixel.util.FlxStringUtil;
 
-class InputFormatter
+/**
+ * Utilities for working with inputs.
+ */
+class InputUtil
 {
-  static public function format(id:Int, device:Device):String
+  public static function format(id:Int, device:Device):String
   {
     return switch (device)
     {
@@ -18,7 +21,7 @@ class InputFormatter
     }
   }
 
-  static public function getKeyName(id:Int):String
+  public static function getKeyName(id:Int):String
   {
     return switch (id)
     {
diff --git a/source/funkin/util/MathUtil.hx b/source/funkin/util/MathUtil.hx
new file mode 100644
index 000000000..3cb6621a7
--- /dev/null
+++ b/source/funkin/util/MathUtil.hx
@@ -0,0 +1,31 @@
+package funkin.util;
+
+/**
+ * Utilities for performing mathematical operations.
+ */
+class MathUtil
+{
+  /**
+   * Perform linear interpolation between the base and the target, based on the current framerate.
+   */
+  public static function coolLerp(base:Float, target:Float, ratio:Float):Float
+  {
+    return base + cameraLerp(ratio) * (target - base);
+  }
+
+  public static function cameraLerp(lerp:Float):Float
+  {
+    return lerp * (FlxG.elapsed / (1 / 60));
+  }
+
+  /**
+   * Get the logarithm of a value with a given base.
+   * @param base The base of the logarithm.
+   * @param value The value to get the logarithm of.
+   * @return `log_base(value)`
+   */
+  public static function logBase(base:Float, value:Float):Float
+  {
+    return Math.log(value) / Math.log(base);
+  }
+}
diff --git a/source/funkin/util/MouseUtil.hx b/source/funkin/util/MouseUtil.hx
new file mode 100644
index 000000000..c3f46819e
--- /dev/null
+++ b/source/funkin/util/MouseUtil.hx
@@ -0,0 +1,45 @@
+package funkin.util;
+
+import flixel.math.FlxPoint;
+
+/**
+ * Utility functions related to the mouse.
+ */
+class MouseUtil
+{
+  static var oldCamPos:FlxPoint = new FlxPoint();
+  static var oldMousePos:FlxPoint = new FlxPoint();
+
+  /**
+   * Used to be for general camera middle click dragging, now generalized for any click and drag type shit!
+   * Listen I don't make the rules here
+   * @param target what you want to be dragged, defaults to CAMERA SCROLL
+   * @param jusPres the "justPressed", should be a button of some sort
+   * @param pressed the "pressed", which should be the same button as `jusPres`
+   */
+  public static function mouseCamDrag(?target:FlxPoint, ?jusPres:Bool, ?pressed:Bool):Void
+  {
+    if (target == null) target = FlxG.camera.scroll;
+
+    if (jusPres == null) jusPres = FlxG.mouse.justPressedMiddle;
+
+    if (pressed == null) pressed = FlxG.mouse.pressedMiddle;
+
+    if (jusPres)
+    {
+      oldCamPos.set(target.x, target.y);
+      oldMousePos.set(FlxG.mouse.screenX, FlxG.mouse.screenY);
+    }
+
+    if (pressed)
+    {
+      target.x = oldCamPos.x - (FlxG.mouse.screenX - oldMousePos.x);
+      target.y = oldCamPos.y - (FlxG.mouse.screenY - oldMousePos.y);
+    }
+  }
+
+  public static function mouseWheelZoom():Void
+  {
+    if (FlxG.mouse.wheel != 0) FlxG.camera.zoom += FlxG.mouse.wheel * (0.1 * FlxG.camera.zoom);
+  }
+}
diff --git a/source/funkin/util/PlatformUtil.hx b/source/funkin/util/PlatformUtil.hx
index b709eb475..e11a21c9f 100644
--- a/source/funkin/util/PlatformUtil.hx
+++ b/source/funkin/util/PlatformUtil.hx
@@ -1,5 +1,8 @@
 package funkin.util;
 
+/**
+ * Utility functions related to specific platforms.
+ */
 class PlatformUtil
 {
   /**
diff --git a/source/funkin/util/SerializerUtil.hx b/source/funkin/util/SerializerUtil.hx
index 0af0fc9ea..abac04115 100644
--- a/source/funkin/util/SerializerUtil.hx
+++ b/source/funkin/util/SerializerUtil.hx
@@ -12,8 +12,8 @@ typedef ScoreInput =
 }
 
 /**
- * A class of functions dedicated to serializing and deserializing data.
- * TODO: Rewrite/refactor this to use json2object.
+ * Functions dedicated to serializing and deserializing data.
+ * NOTE: Use `json2object` wherever possible, it's way more efficient.
  */
 class SerializerUtil
 {
diff --git a/source/funkin/util/SortUtil.hx b/source/funkin/util/SortUtil.hx
index 178015068..d87592c91 100644
--- a/source/funkin/util/SortUtil.hx
+++ b/source/funkin/util/SortUtil.hx
@@ -10,7 +10,7 @@ import funkin.data.song.SongData.SongEventData;
 import funkin.data.song.SongData.SongNoteData;
 
 /**
- * A set of functions related to sorting.
+ * Utility functions related to sorting.
  *
  * NOTE: `Array.sort()` takes a function `(x, y) -> Int`.
  * If the objects are in the correct order (x before y), return a negative value.
diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx
index 1dc00473a..480bcea71 100644
--- a/source/funkin/util/VersionUtil.hx
+++ b/source/funkin/util/VersionUtil.hx
@@ -4,6 +4,8 @@ import thx.semver.Version;
 import thx.semver.VersionRule;
 
 /**
+ * Utility functions for operating on semantic versions.
+ *
  * Remember, increment the patch version (1.0.x) if you make a bugfix,
  * increment the minor version (1.x.0) if you make a new feature (but previous content is still compatible),
  * and increment the major version (x.0.0) if you make a breaking change (e.g. new API or reorganized file format).
diff --git a/source/funkin/util/WindowUtil.hx b/source/funkin/util/WindowUtil.hx
index 6e6a41641..0e9b76bc2 100644
--- a/source/funkin/util/WindowUtil.hx
+++ b/source/funkin/util/WindowUtil.hx
@@ -2,6 +2,9 @@ package funkin.util;
 
 import flixel.util.FlxSignal.FlxTypedSignal;
 
+/**
+ * Utilities for operating on the current window, such as changing the title.
+ */
 #if (cpp && windows)
 @:cppFileCode('
 #include <iostream>

From da08e0fa39ca4e66751cd462f1a9f74f7e4fb94d Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Wed, 8 Nov 2023 23:22:55 -0500
Subject: [PATCH 2/4] assets update

---
 .gitmodules | 1 +
 assets      | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/.gitmodules b/.gitmodules
index 8968471e3..c7aa48202 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -5,3 +5,4 @@
 [submodule "art"]
 	path = art
 	url = https://github.com/FunkinCrew/Funkin-history-rewrite-art
+	branch = master
diff --git a/assets b/assets
index 53f63f549..bbd6386e1 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 53f63f549f34b9c03d0e2d7149dde551a61acb26
+Subproject commit bbd6386e11e3d0a8278ffcdef77f53e0f7ade750

From 01be0293e3ef16d7c691f9568fb38707750b0631 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Mon, 13 Nov 2023 18:03:24 -0500
Subject: [PATCH 3/4] Revert asset changes (temporarily)

---
 assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/assets b/assets
index 11a1af02f..be9d790af 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 11a1af02fd38ed6086f09bf59567e1efa57b5715
+Subproject commit be9d790af9c6f1f5e3afc7aed2b1d5c21823bc20

From 70049765ee8f4b8090f6697d1e47f1aeb99e6b67 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Tue, 14 Nov 2023 15:30:49 -0500
Subject: [PATCH 4/4] assets push / update

---
 assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/assets b/assets
index bbd6386e1..69283c667 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit bbd6386e11e3d0a8278ffcdef77f53e0f7ade750
+Subproject commit 69283c667d93e44da8d63f0588c7554f608575fb