From 4804b9ae22eec299d84569402cb25ca21baf6a86 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 6 Jan 2024 01:06:10 -0500 Subject: [PATCH 01/43] Work in progress for Chart Editor gamepad support (navigation implemented, note placement WIP) --- source/funkin/input/Controls.hx | 367 +++++++++++----- source/funkin/input/TurboActionHandler.hx | 111 +++++ source/funkin/input/TurboButtonHandler.hx | 127 ++++++ .../ui/debug/charting/ChartEditorState.hx | 397 ++++++++++++++++-- .../charting/commands/RemoveEventsCommand.hx | 4 + .../charting/commands/RemoveItemsCommand.hx | 4 + .../charting/commands/RemoveNotesCommand.hx | 4 + .../components/ChartEditorHoldNoteSprite.hx | 9 +- .../handlers/ChartEditorGamepadHandler.hx | 133 ++++++ source/funkin/ui/debug/charting/import.hx | 1 + 10 files changed, 1009 insertions(+), 148 deletions(-) create mode 100644 source/funkin/input/TurboActionHandler.hx create mode 100644 source/funkin/input/TurboButtonHandler.hx create mode 100644 source/funkin/ui/debug/charting/handlers/ChartEditorGamepadHandler.hx diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index 3fa4e0f75..5c761cd19 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -30,47 +30,31 @@ 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); - var _ui_down = new FlxActionDigital(Action.UI_DOWN); - var _ui_upP = new FlxActionDigital(Action.UI_UP_P); - var _ui_leftP = new FlxActionDigital(Action.UI_LEFT_P); - var _ui_rightP = new FlxActionDigital(Action.UI_RIGHT_P); - var _ui_downP = new FlxActionDigital(Action.UI_DOWN_P); - var _ui_upR = new FlxActionDigital(Action.UI_UP_R); - var _ui_leftR = new FlxActionDigital(Action.UI_LEFT_R); - var _ui_rightR = new FlxActionDigital(Action.UI_RIGHT_R); - var _ui_downR = new FlxActionDigital(Action.UI_DOWN_R); - var _note_up = new FlxActionDigital(Action.NOTE_UP); - var _note_left = new FlxActionDigital(Action.NOTE_LEFT); - var _note_right = new FlxActionDigital(Action.NOTE_RIGHT); - var _note_down = new FlxActionDigital(Action.NOTE_DOWN); - var _note_upP = new FlxActionDigital(Action.NOTE_UP_P); - var _note_leftP = new FlxActionDigital(Action.NOTE_LEFT_P); - var _note_rightP = new FlxActionDigital(Action.NOTE_RIGHT_P); - var _note_downP = new FlxActionDigital(Action.NOTE_DOWN_P); - var _note_upR = new FlxActionDigital(Action.NOTE_UP_R); - var _note_leftR = new FlxActionDigital(Action.NOTE_LEFT_R); - var _note_rightR = new FlxActionDigital(Action.NOTE_RIGHT_R); - var _note_downR = new FlxActionDigital(Action.NOTE_DOWN_R); - var _accept = new FlxActionDigital(Action.ACCEPT); - var _back = new FlxActionDigital(Action.BACK); - var _pause = new FlxActionDigital(Action.PAUSE); - var _reset = new FlxActionDigital(Action.RESET); - var _cutscene_advance = new FlxActionDigital(Action.CUTSCENE_ADVANCE); - var _cutscene_skip = new FlxActionDigital(Action.CUTSCENE_SKIP); - var _debug_menu = new FlxActionDigital(Action.DEBUG_MENU); - var _debug_chart = new FlxActionDigital(Action.DEBUG_CHART); - var _debug_stage = new FlxActionDigital(Action.DEBUG_STAGE); - var _volume_up = new FlxActionDigital(Action.VOLUME_UP); - var _volume_down = new FlxActionDigital(Action.VOLUME_DOWN); - var _volume_mute = new FlxActionDigital(Action.VOLUME_MUTE); + var _ui_up = new FunkinAction(Action.UI_UP, Action.UI_UP_P, Action.UI_UP_R); + var _ui_left = new FunkinAction(Action.UI_LEFT, Action.UI_LEFT_P, Action.UI_LEFT_R); + var _ui_right = new FunkinAction(Action.UI_RIGHT, Action.UI_RIGHT_P, Action.UI_RIGHT_R); + var _ui_down = new FunkinAction(Action.UI_DOWN, Action.UI_DOWN_P, Action.UI_DOWN_R); + var _note_up = new FunkinAction(Action.NOTE_UP, Action.NOTE_UP_P, Action.NOTE_UP_R); + var _note_left = new FunkinAction(Action.NOTE_LEFT, Action.NOTE_LEFT_P, Action.NOTE_LEFT_R); + var _note_right = new FunkinAction(Action.NOTE_RIGHT, Action.NOTE_RIGHT_P, Action.NOTE_RIGHT_R); + var _note_down = new FunkinAction(Action.NOTE_DOWN, Action.NOTE_DOWN_P, Action.NOTE_DOWN_R); + var _accept = new FunkinAction(Action.ACCEPT); + var _back = new FunkinAction(Action.BACK); + var _pause = new FunkinAction(Action.PAUSE); + var _reset = new FunkinAction(Action.RESET); + var _cutscene_advance = new FunkinAction(Action.CUTSCENE_ADVANCE); + var _cutscene_skip = new FunkinAction(Action.CUTSCENE_SKIP); + var _debug_menu = new FunkinAction(Action.DEBUG_MENU); + var _debug_chart = new FunkinAction(Action.DEBUG_CHART); + var _debug_stage = new FunkinAction(Action.DEBUG_STAGE); + var _volume_up = new FunkinAction(Action.VOLUME_UP); + var _volume_down = new FunkinAction(Action.VOLUME_DOWN); + var _volume_mute = new FunkinAction(Action.VOLUME_MUTE); #if CAN_CHEAT - var _cheat = new FlxActionDigital(Action.CHEAT); + var _cheat = new FunkinAction(Action.CHEAT); #end - var byName:Map = new Map(); + var byName:Map = new Map(); public var gamepadsAdded:Array = []; public var keyboardScheme = KeyboardScheme.None; @@ -78,122 +62,142 @@ class Controls extends FlxActionSet public var UI_UP(get, never):Bool; inline function get_UI_UP() - return _ui_up.check(); + return _ui_up.checkPressed(); public var UI_LEFT(get, never):Bool; inline function get_UI_LEFT() - return _ui_left.check(); + return _ui_left.checkPressed(); public var UI_RIGHT(get, never):Bool; inline function get_UI_RIGHT() - return _ui_right.check(); + return _ui_right.checkPressed(); public var UI_DOWN(get, never):Bool; inline function get_UI_DOWN() - return _ui_down.check(); + return _ui_down.checkPressed(); public var UI_UP_P(get, never):Bool; inline function get_UI_UP_P() - return _ui_upP.check(); + return _ui_up.checkJustPressed(); public var UI_LEFT_P(get, never):Bool; inline function get_UI_LEFT_P() - return _ui_leftP.check(); + return _ui_left.checkJustPressed(); public var UI_RIGHT_P(get, never):Bool; inline function get_UI_RIGHT_P() - return _ui_rightP.check(); + return _ui_right.checkJustPressed(); public var UI_DOWN_P(get, never):Bool; inline function get_UI_DOWN_P() - return _ui_downP.check(); + return _ui_down.checkJustPressed(); public var UI_UP_R(get, never):Bool; inline function get_UI_UP_R() - return _ui_upR.check(); + return _ui_up.checkJustReleased(); public var UI_LEFT_R(get, never):Bool; inline function get_UI_LEFT_R() - return _ui_leftR.check(); + return _ui_left.checkJustReleased(); public var UI_RIGHT_R(get, never):Bool; inline function get_UI_RIGHT_R() - return _ui_rightR.check(); + return _ui_right.checkJustReleased(); public var UI_DOWN_R(get, never):Bool; inline function get_UI_DOWN_R() - return _ui_downR.check(); + return _ui_down.checkJustReleased(); + + public var UI_UP_GAMEPAD(get, never):Bool; + + inline function get_UI_UP_GAMEPAD() + return _ui_up.checkPressedGamepad(); + + public var UI_LEFT_GAMEPAD(get, never):Bool; + + inline function get_UI_LEFT_GAMEPAD() + return _ui_left.checkPressedGamepad(); + + public var UI_RIGHT_GAMEPAD(get, never):Bool; + + inline function get_UI_RIGHT_GAMEPAD() + return _ui_right.checkPressedGamepad(); + + public var UI_DOWN_GAMEPAD(get, never):Bool; + + inline function get_UI_DOWN_GAMEPAD() + return _ui_down.checkPressedGamepad(); public var NOTE_UP(get, never):Bool; inline function get_NOTE_UP() - return _note_up.check(); + return _note_up.checkPressed(); public var NOTE_LEFT(get, never):Bool; inline function get_NOTE_LEFT() - return _note_left.check(); + return _note_left.checkPressed(); public var NOTE_RIGHT(get, never):Bool; inline function get_NOTE_RIGHT() - return _note_right.check(); + return _note_right.checkPressed(); public var NOTE_DOWN(get, never):Bool; inline function get_NOTE_DOWN() - return _note_down.check(); + return _note_down.checkPressed(); public var NOTE_UP_P(get, never):Bool; inline function get_NOTE_UP_P() - return _note_upP.check(); + return _note_up.checkJustPressed(); public var NOTE_LEFT_P(get, never):Bool; inline function get_NOTE_LEFT_P() - return _note_leftP.check(); + return _note_left.checkJustPressed(); public var NOTE_RIGHT_P(get, never):Bool; inline function get_NOTE_RIGHT_P() - return _note_rightP.check(); + return _note_right.checkJustPressed(); public var NOTE_DOWN_P(get, never):Bool; inline function get_NOTE_DOWN_P() - return _note_downP.check(); + return _note_down.checkJustPressed(); public var NOTE_UP_R(get, never):Bool; inline function get_NOTE_UP_R() - return _note_upR.check(); + return _note_up.checkJustReleased(); public var NOTE_LEFT_R(get, never):Bool; inline function get_NOTE_LEFT_R() - return _note_leftR.check(); + return _note_left.checkJustReleased(); public var NOTE_RIGHT_R(get, never):Bool; inline function get_NOTE_RIGHT_R() - return _note_rightR.check(); + return _note_right.checkJustReleased(); public var NOTE_DOWN_R(get, never):Bool; inline function get_NOTE_DOWN_R() - return _note_downR.check(); + return _note_down.checkJustReleased(); public var ACCEPT(get, never):Bool; @@ -270,26 +274,10 @@ class Controls extends FlxActionSet add(_ui_left); add(_ui_right); add(_ui_down); - add(_ui_upP); - add(_ui_leftP); - add(_ui_rightP); - add(_ui_downP); - add(_ui_upR); - add(_ui_leftR); - add(_ui_rightR); - add(_ui_downR); add(_note_up); add(_note_left); add(_note_right); add(_note_down); - add(_note_upP); - add(_note_leftP); - add(_note_rightP); - add(_note_downP); - add(_note_upR); - add(_note_leftR); - add(_note_rightR); - add(_note_downR); add(_accept); add(_back); add(_pause); @@ -303,8 +291,16 @@ class Controls extends FlxActionSet add(_cheat); #end - for (action in digitalActions) - byName[action.name] = action; + for (action in digitalActions) { + if (Std.isOfType(action, FunkinAction)) { + var funkinAction:FunkinAction = cast action; + byName[funkinAction.name] = funkinAction; + if (funkinAction.namePressed != null) + byName[funkinAction.namePressed] = funkinAction; + if (funkinAction.nameReleased != null) + byName[funkinAction.nameReleased] = funkinAction; + } + } if (scheme == null) scheme = None; @@ -317,14 +313,17 @@ class Controls extends FlxActionSet super.update(); } - // inline - public function checkByName(name:Action):Bool + public function check(name:Action, trigger:FlxInputState = JUST_PRESSED, gamepadOnly:Bool = false):Bool { #if debug if (!byName.exists(name)) throw 'Invalid name: $name'; #end - return byName[name].check(); + var action = byName[name]; + if (gamepadOnly) + return action.checkFiltered(trigger, GAMEPAD); + else + return action.checkFiltered(trigger); } public function getKeysForAction(name:Action):Array { @@ -411,36 +410,36 @@ class Controls extends FlxActionSet { case UI_UP: func(_ui_up, PRESSED); - func(_ui_upP, JUST_PRESSED); - func(_ui_upR, JUST_RELEASED); + func(_ui_up, JUST_PRESSED); + func(_ui_up, JUST_RELEASED); case UI_LEFT: func(_ui_left, PRESSED); - func(_ui_leftP, JUST_PRESSED); - func(_ui_leftR, JUST_RELEASED); + func(_ui_left, JUST_PRESSED); + func(_ui_left, JUST_RELEASED); case UI_RIGHT: func(_ui_right, PRESSED); - func(_ui_rightP, JUST_PRESSED); - func(_ui_rightR, JUST_RELEASED); + func(_ui_right, JUST_PRESSED); + func(_ui_right, JUST_RELEASED); case UI_DOWN: func(_ui_down, PRESSED); - func(_ui_downP, JUST_PRESSED); - func(_ui_downR, JUST_RELEASED); + func(_ui_down, JUST_PRESSED); + func(_ui_down, JUST_RELEASED); case NOTE_UP: func(_note_up, PRESSED); - func(_note_upP, JUST_PRESSED); - func(_note_upR, JUST_RELEASED); + func(_note_up, JUST_PRESSED); + func(_note_up, JUST_RELEASED); case NOTE_LEFT: func(_note_left, PRESSED); - func(_note_leftP, JUST_PRESSED); - func(_note_leftR, JUST_RELEASED); + func(_note_left, JUST_PRESSED); + func(_note_left, JUST_RELEASED); case NOTE_RIGHT: func(_note_right, PRESSED); - func(_note_rightP, JUST_PRESSED); - func(_note_rightR, JUST_RELEASED); + func(_note_right, JUST_PRESSED); + func(_note_right, JUST_RELEASED); case NOTE_DOWN: func(_note_down, PRESSED); - func(_note_downP, JUST_PRESSED); - func(_note_downR, JUST_RELEASED); + func(_note_down, JUST_PRESSED); + func(_note_down, JUST_RELEASED); case ACCEPT: func(_accept, JUST_PRESSED); case BACK: @@ -1053,6 +1052,173 @@ typedef Swipes = ?curTouchPos:FlxPoint }; +/** + * An FlxActionDigital with additional functionality, including: + * - Combining `pressed` and `released` inputs into one action. + * - Filtering by input method (`KEYBOARD`, `MOUSE`, `GAMEPAD`, etc). + */ +class FunkinAction extends FlxActionDigital { + public var namePressed(default, null):Null; + public var nameReleased(default, null):Null; + + var cache:Map = []; + + public function new(?name:String = "", ?namePressed:String, ?nameReleased:String) + { + super(name); + + this.namePressed = namePressed; + this.nameReleased = nameReleased; + } + + /** + * Input checks default to whether the input was just pressed, on any input device. + */ + public override function check():Bool { + return checkFiltered(JUST_PRESSED); + } + + /** + * Check whether the input is currently being held. + */ + public function checkPressed():Bool { + return checkFiltered(PRESSED); + } + + /** + * Check whether the input is currently being held, and was not held last frame. + */ + public function checkJustPressed():Bool { + return checkFiltered(JUST_PRESSED); + } + + /** + * Check whether the input is not currently being held. + */ + public function checkReleased():Bool { + return checkFiltered(RELEASED); + } + + /** + * Check whether the input is not currently being held, and was held last frame. + */ + public function checkJustReleased():Bool { + return checkFiltered(JUST_RELEASED); + } + + /** + * Check whether the input is currently being held by a gamepad device. + */ + public function checkPressedGamepad():Bool { + return checkFiltered(PRESSED, GAMEPAD); + } + + /** + * Check whether the input is currently being held by a gamepad device, and was not held last frame. + */ + public function checkJustPressedGamepad():Bool { + return checkFiltered(JUST_PRESSED, GAMEPAD); + } + + /** + * Check whether the input is not currently being held by a gamepad device. + */ + public function checkReleasedGamepad():Bool { + return checkFiltered(RELEASED, GAMEPAD); + } + + /** + * Check whether the input is not currently being held by a gamepad device, and was held last frame. + */ + public function checkJustReleasedGamepad():Bool { + return checkFiltered(JUST_RELEASED, GAMEPAD); + } + + public function checkMultiFiltered(?filterTriggers:Array, ?filterDevices:Array):Bool { + if (filterTriggers == null) { + filterTriggers = [PRESSED, JUST_PRESSED]; + } + if (filterDevices == null) { + filterDevices = []; + } + + // Perform checkFiltered for each combination. + for (i in filterTriggers) { + if (filterDevices.length == 0) { + if (checkFiltered(i)) { + return true; + } + } else { + for (j in filterDevices) { + if (checkFiltered(i, j)) { + return true; + } + } + } + } + return false; + } + + /** + * Performs the functionality of `FlxActionDigital.check()`, but with optional filters. + * @param action The action to check for. + * @param filterTrigger Optionally filter by trigger condition (`JUST_PRESSED`, `PRESSED`, `JUST_RELEASED`, `RELEASED`). + * @param filterDevice Optionally filter by device (`KEYBOARD`, `MOUSE`, `GAMEPAD`, `OTHER`). + */ + public function checkFiltered(?filterTrigger:FlxInputState, ?filterDevice:FlxInputDevice):Bool { + // The normal + + // Make sure we only update the inputs once per frame. + var key = '${filterTrigger}:${filterDevice}'; + var cacheEntry = cache.get(key); + + if (cacheEntry != null && cacheEntry.timestamp == FlxG.game.ticks) { + return cacheEntry.value; + } + // Use a for loop instead so we can remove inputs while iterating. + + // We don't return early because we need to call check() on ALL inputs. + var result = false; + var len = inputs != null ? inputs.length : 0; + for (i in 0...len) + { + var j = len - i - 1; + var input = inputs[j]; + + // Filter out dead inputs. + if (input.destroyed) + { + inputs.splice(j, 1); + continue; + } + + // Update the input. + input.update(); + + // Check whether the input is the right trigger. + if (filterTrigger != null && input.trigger != filterTrigger) { + continue; + } + + // Check whether the input is the right device. + if (filterDevice != null && input.device != filterDevice) { + continue; + } + + // Check whether the input has triggered. + if (input.check(this)) + { + result = true; + } + } + + // We need to cache this result. + cache.set(key, {timestamp: FlxG.game.ticks, value: result}); + + return result; + } +} + class FlxActionInputDigitalMobileSwipeGameplay extends FlxActionInputDigital { var touchMap:Map = new Map(); @@ -1242,8 +1408,7 @@ enum Control #end } -enum -abstract Action(String) to String from String +enum abstract Action(String) to String from String { // NOTE var NOTE_UP = "note_up"; diff --git a/source/funkin/input/TurboActionHandler.hx b/source/funkin/input/TurboActionHandler.hx new file mode 100644 index 000000000..9425db8cd --- /dev/null +++ b/source/funkin/input/TurboActionHandler.hx @@ -0,0 +1,111 @@ +package funkin.input; + +import flixel.input.keyboard.FlxKey; +import flixel.FlxBasic; +import funkin.input.Controls; +import funkin.input.Controls.Action; + +/** + * Handles repeating behavior when holding down a control action. + * + * When the `action` is pressed, `activated` will be true for the first frame, + * then wait `delay` seconds before becoming true for one frame every `interval` seconds. + * + * Example: Pressing Ctrl+Z will undo, while holding Ctrl+Z will start to undo repeatedly. + */ +class TurboActionHandler extends FlxBasic +{ + /** + * Default delay before repeating. + */ + static inline final DEFAULT_DELAY:Float = 0.4; + + /** + * Default interval between repeats. + */ + static inline final DEFAULT_INTERVAL:Float = 0.1; + + /** + * Whether the action for this handler is pressed. + */ + public var pressed(get, never):Bool; + + /** + * Whether the action for this handler is pressed, + * and the handler is ready to repeat. + */ + public var activated(default, null):Bool = false; + + /** + * The Funkin Controls handler. + */ + var controls(get, never):Controls; + + function get_controls():Controls + { + return PlayerSettings.player1.controls; + } + + var action:Action; + + var delay:Float; + var interval:Float; + var gamepadOnly:Bool; + + var pressedTime:Float = 0; + + function new(action:Action, delay:Float = DEFAULT_DELAY, interval:Float = DEFAULT_INTERVAL, gamepadOnly:Bool = false) + { + super(); + this.action = action; + this.delay = delay; + this.interval = interval; + this.gamepadOnly = gamepadOnly; + } + + function get_pressed():Bool + { + return controls.check(action, PRESSED, gamepadOnly); + } + + public override function update(elapsed:Float):Void + { + super.update(elapsed); + + if (pressed) + { + if (pressedTime == 0) + { + activated = true; + } + else if (pressedTime >= (delay + interval)) + { + activated = true; + pressedTime -= interval; + } + else + { + activated = false; + } + pressedTime += elapsed; + } + else + { + pressedTime = 0; + activated = false; + } + } + + /** + * Builds a TurboActionHandler that monitors from a single key. + * @param inputKey The key to monitor. + * @param delay How long to wait before repeating. + * @param repeatDelay How long to wait between repeats. + * @return A TurboActionHandler + */ + public static overload inline extern function build(action:Action, ?delay:Float = DEFAULT_DELAY, ?interval:Float = DEFAULT_INTERVAL, + ?gamepadOnly:Bool = false):TurboActionHandler + { + return new TurboActionHandler(action, delay, interval); + } +} diff --git a/source/funkin/input/TurboButtonHandler.hx b/source/funkin/input/TurboButtonHandler.hx new file mode 100644 index 000000000..63c2a294b --- /dev/null +++ b/source/funkin/input/TurboButtonHandler.hx @@ -0,0 +1,127 @@ +package funkin.input; + +import flixel.input.gamepad.FlxGamepadInputID; +import flixel.input.gamepad.FlxGamepad; +import flixel.FlxBasic; + +/** + * Handles repeating behavior when holding down a gamepad button or button combination. + * + * When the `inputs` are pressed, `activated` will be true for the first frame, + * then wait `delay` seconds before becoming true for one frame every `interval` seconds. + * + * Example: Pressing Ctrl+Z will undo, while holding Ctrl+Z will start to undo repeatedly. + */ +class TurboButtonHandler extends FlxBasic +{ + /** + * Default delay before repeating. + */ + static inline final DEFAULT_DELAY:Float = 0.4; + + /** + * Default interval between repeats. + */ + static inline final DEFAULT_INTERVAL:Float = 0.1; + + /** + * Whether all of the keys for this handler are pressed. + */ + public var allPressed(get, never):Bool; + + /** + * Whether all of the keys for this handler are activated, + * and the handler is ready to repeat. + */ + public var activated(default, null):Bool = false; + + var inputs:Array; + var delay:Float; + var interval:Float; + var targetGamepad:FlxGamepad; + + var allPressedTime:Float = 0; + + function new(inputs:Array, delay:Float = DEFAULT_DELAY, interval:Float = DEFAULT_INTERVAL, ?targetGamepad:FlxGamepad) + { + super(); + this.inputs = inputs; + this.delay = delay; + this.interval = interval; + this.targetGamepad = targetGamepad ?? FlxG.gamepads.firstActive; + } + + function get_allPressed():Bool + { + if (targetGamepad == null) return false; + if (inputs == null || inputs.length == 0) return false; + if (inputs.length == 1) return targetGamepad.anyPressed(inputs); + + // Check if ANY keys are unpressed + for (input in inputs) + { + if (!targetGamepad.anyPressed([input])) return false; + } + return true; + } + + public override function update(elapsed:Float):Void + { + super.update(elapsed); + + // Try to find a gamepad if we don't have one + if (targetGamepad == null) + { + targetGamepad = FlxG.gamepads.firstActive; + } + + if (allPressed) + { + if (allPressedTime == 0) + { + activated = true; + } + else if (allPressedTime >= (delay + interval)) + { + activated = true; + allPressedTime -= interval; + } + else + { + activated = false; + } + allPressedTime += elapsed; + } + else + { + allPressedTime = 0; + activated = false; + } + } + + /** + * Builds a TurboButtonHandler that monitors from a single input. + * @param input The input to monitor. + * @param delay How long to wait before repeating. + * @param repeatDelay How long to wait between repeats. + * @return A TurboKeyHandler + */ + public static overload inline extern function build(input:FlxGamepadInputID, ?delay:Float = DEFAULT_DELAY, + ?interval:Float = DEFAULT_INTERVAL):TurboButtonHandler + { + return new TurboButtonHandler([input], delay, interval); + } + + /** + * Builds a TurboKeyHandler that monitors a key combination. + * @param inputs The combination of inputs to monitor. + * @param delay How long to wait before repeating. + * @param repeatDelay How long to wait between repeats. + * @return A TurboKeyHandler + */ + public static overload inline extern function build(inputs:Array, ?delay:Float = DEFAULT_DELAY, + ?interval:Float = DEFAULT_INTERVAL):TurboButtonHandler + { + return new TurboButtonHandler(inputs, delay, interval); + } +} diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 1773a84fe..f3236578a 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1,24 +1,25 @@ package funkin.ui.debug.charting; -import funkin.util.logging.CrashHandler; -import haxe.ui.containers.HBox; -import haxe.ui.containers.Grid; -import haxe.ui.containers.ScrollView; -import haxe.ui.containers.menus.MenuBar; import flixel.addons.display.FlxSliceSprite; import flixel.addons.display.FlxTiledSprite; import flixel.addons.transition.FlxTransitionableState; import flixel.FlxCamera; import flixel.FlxSprite; import flixel.FlxSubState; +import flixel.graphics.FlxGraphic; +import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxSpriteGroup; +import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.keyboard.FlxKey; +import flixel.input.mouse.FlxMouseEvent; import flixel.math.FlxMath; import flixel.math.FlxPoint; import flixel.graphics.FlxGraphic; import flixel.math.FlxRect; import flixel.sound.FlxSound; +import flixel.system.debug.log.LogStyle; import flixel.system.FlxAssets.FlxSoundAsset; +import flixel.text.FlxText; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.tweens.misc.VarTween; @@ -26,19 +27,31 @@ import haxe.ui.Toolkit; import flixel.util.FlxColor; import flixel.util.FlxSort; import flixel.util.FlxTimer; -import funkin.audio.visualize.PolygonSpectogram; -import funkin.audio.VoicesGroup; import funkin.audio.FunkinSound; +import funkin.audio.visualize.PolygonSpectogram; +import funkin.audio.visualize.PolygonSpectogram; +import funkin.audio.visualize.PolygonVisGroup; +import funkin.audio.VoicesGroup; import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.song.SongData.SongCharacterData; +import funkin.data.song.SongData.SongCharacterData; +import funkin.data.song.SongData.SongChartData; import funkin.data.song.SongData.SongChartData; import funkin.data.song.SongData.SongEventData; +import funkin.data.song.SongData.SongEventData; import funkin.data.song.SongData.SongMetadata; +import funkin.data.song.SongData.SongMetadata; +import funkin.data.song.SongData.SongNoteData; import funkin.data.song.SongData.SongNoteData; import funkin.data.song.SongData.SongOffsets; import funkin.data.song.SongDataUtils; +import funkin.data.song.SongDataUtils; import funkin.data.song.SongRegistry; +import funkin.data.song.SongRegistry; +import funkin.input.Controls.Action; import funkin.input.Cursor; +import funkin.input.TurboActionHandler; +import funkin.input.TurboButtonHandler; import funkin.input.TurboKeyHandler; import funkin.modding.events.ScriptEvent; import funkin.play.character.BaseCharacter.CharacterType; @@ -48,20 +61,13 @@ import funkin.play.components.HealthIcon; import funkin.play.notes.NoteSprite; import funkin.play.PlayState; import funkin.play.song.Song; -import funkin.data.song.SongData.SongChartData; -import funkin.data.song.SongRegistry; -import funkin.data.song.SongData.SongEventData; -import funkin.data.song.SongData.SongMetadata; -import funkin.data.song.SongData.SongNoteData; -import funkin.data.song.SongData.SongCharacterData; -import funkin.data.song.SongDataUtils; -import funkin.ui.debug.charting.commands.ChartEditorCommand; import funkin.play.stage.StageData; import funkin.save.Save; import funkin.ui.debug.charting.commands.AddEventsCommand; import funkin.ui.debug.charting.commands.AddNotesCommand; import funkin.ui.debug.charting.commands.ChartEditorCommand; import funkin.ui.debug.charting.commands.ChartEditorCommand; +import funkin.ui.debug.charting.commands.ChartEditorCommand; import funkin.ui.debug.charting.commands.CutItemsCommand; import funkin.ui.debug.charting.commands.DeselectAllItemsCommand; import funkin.ui.debug.charting.commands.DeselectItemsCommand; @@ -80,17 +86,20 @@ import funkin.ui.debug.charting.commands.SelectItemsCommand; import funkin.ui.debug.charting.commands.SetItemSelectionCommand; import funkin.ui.debug.charting.components.ChartEditorEventSprite; import funkin.ui.debug.charting.components.ChartEditorHoldNoteSprite; +import funkin.ui.debug.charting.components.ChartEditorMeasureTicks; import funkin.ui.debug.charting.components.ChartEditorNotePreview; import funkin.ui.debug.charting.components.ChartEditorNoteSprite; import funkin.ui.debug.charting.components.ChartEditorMeasureTicks; import funkin.ui.debug.charting.components.ChartEditorPlaybarHead; import funkin.ui.debug.charting.components.ChartEditorSelectionSquareSprite; import funkin.ui.debug.charting.handlers.ChartEditorShortcutHandler; +import funkin.ui.debug.charting.toolboxes.ChartEditorBaseToolbox; import funkin.ui.haxeui.components.CharacterPlayer; import funkin.ui.haxeui.HaxeUIState; import funkin.ui.mainmenu.MainMenuState; import funkin.util.Constants; import funkin.util.FileUtil; +import funkin.util.logging.CrashHandler; import funkin.util.SortUtil; import funkin.util.WindowUtil; import haxe.DynamicAccess; @@ -98,22 +107,25 @@ import haxe.io.Bytes; import haxe.io.Path; import haxe.ui.backend.flixel.UIRuntimeState; import haxe.ui.backend.flixel.UIState; -import haxe.ui.components.DropDown; -import haxe.ui.components.Label; import haxe.ui.components.Button; +import haxe.ui.components.DropDown; +import haxe.ui.components.Image; +import haxe.ui.components.Label; import haxe.ui.components.NumberStepper; import haxe.ui.components.Slider; import haxe.ui.components.TextField; import haxe.ui.containers.dialogs.CollapsibleDialog; import haxe.ui.containers.Frame; +import haxe.ui.containers.Grid; +import haxe.ui.containers.HBox; import haxe.ui.containers.menus.Menu; import haxe.ui.containers.menus.MenuBar; -import haxe.ui.containers.menus.MenuItem; +import haxe.ui.containers.menus.MenuBar; import haxe.ui.containers.menus.MenuCheckBox; +import haxe.ui.containers.menus.MenuItem; +import haxe.ui.containers.ScrollView; import haxe.ui.containers.TreeView; import haxe.ui.containers.TreeViewNode; -import haxe.ui.components.Image; -import funkin.ui.debug.charting.toolboxes.ChartEditorBaseToolbox; import haxe.ui.core.Component; import haxe.ui.core.Screen; import haxe.ui.events.DragEvent; @@ -122,12 +134,6 @@ import haxe.ui.events.UIEvent; import haxe.ui.events.UIEvent; import haxe.ui.focus.FocusManager; import openfl.display.BitmapData; -import funkin.audio.visualize.PolygonSpectogram; -import flixel.group.FlxGroup.FlxTypedGroup; -import funkin.audio.visualize.PolygonVisGroup; -import flixel.input.mouse.FlxMouseEvent; -import flixel.text.FlxText; -import flixel.system.debug.log.LogStyle; using Lambda; @@ -360,6 +366,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } } + updatePlayheadGhostHoldNotes(); + // Move the rendered notes to the correct position. renderedNotes.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0); renderedHoldNotes.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0); @@ -429,6 +437,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Move the playhead sprite to the correct position. gridPlayhead.y = this.playheadPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD); + updatePlayheadGhostHoldNotes(); + return this.playheadPositionInPixels; } @@ -720,6 +730,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ var currentPlaceNoteData:Null = null; + /** + * The SongNoteData which is currently being placed, for each column. + * `null` if the user isn't currently placing a note. + * As the user moves down, we will update this note's sustain length, and finalize the note when they release. + */ + var currentLiveInputPlaceNoteData:Array = []; + // Note Movement /** @@ -750,6 +767,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ var dragLengthCurrent:Float = 0; + /** + * The current length of the hold note we are placing with the playhead, in steps. + * Play a sound when this value changes. + */ + var playheadDragLengthCurrent:Array = []; + /** * Flip-flop to alternate between two stretching sounds. */ @@ -1020,6 +1043,66 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ var pageDownKeyHandler:TurboKeyHandler = TurboKeyHandler.build(FlxKey.PAGEDOWN); + /** + * Variable used to track how long the user has been holding up on the dpad. + */ + var dpadUpGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.DPAD_UP); + + /** + * Variable used to track how long the user has been holding down on the dpad. + */ + var dpadDownGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.DPAD_DOWN); + + /** + * Variable used to track how long the user has been holding left on the dpad. + */ + var dpadLeftGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.DPAD_LEFT); + + /** + * Variable used to track how long the user has been holding right on the dpad. + */ + var dpadRightGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.DPAD_RIGHT); + + /** + * Variable used to track how long the user has been holding up on the left stick. + */ + var leftStickUpGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.LEFT_STICK_DIGITAL_UP); + + /** + * Variable used to track how long the user has been holding down on the left stick. + */ + var leftStickDownGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.LEFT_STICK_DIGITAL_DOWN); + + /** + * Variable used to track how long the user has been holding left on the left stick. + */ + var leftStickLeftGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.LEFT_STICK_DIGITAL_LEFT); + + /** + * Variable used to track how long the user has been holding right on the left stick. + */ + var leftStickRightGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.LEFT_STICK_DIGITAL_RIGHT); + + /** + * Variable used to track how long the user has been holding up on the right stick. + */ + var rightStickUpGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.RIGHT_STICK_DIGITAL_UP); + + /** + * Variable used to track how long the user has been holding down on the right stick. + */ + var rightStickDownGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.RIGHT_STICK_DIGITAL_DOWN); + + /** + * Variable used to track how long the user has been holding left on the right stick. + */ + var rightStickLeftGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.RIGHT_STICK_DIGITAL_LEFT); + + /** + * Variable used to track how long the user has been holding right on the right stick. + */ + var rightStickRightGamepadHandler:TurboButtonHandler = TurboButtonHandler.build(FlxGamepadInputID.RIGHT_STICK_DIGITAL_RIGHT); + /** * AUDIO AND SOUND DATA */ @@ -1733,10 +1816,15 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var gridGhostNote:Null = null; /** - * A sprite used to indicate the note that will be placed on click. + * A sprite used to indicate the hold note that will be placed on click. */ var gridGhostHoldNote:Null = null; + /** + * A sprite used to indicate the hold note that will be placed on button release. + */ + var gridPlayheadGhostHoldNotes:Array = []; + /** * A sprite used to indicate the event that will be placed on click. */ @@ -2126,11 +2214,23 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState gridGhostHoldNote = new ChartEditorHoldNoteSprite(this); gridGhostHoldNote.alpha = 0.6; - gridGhostHoldNote.noteData = new SongNoteData(0, 0, 0, ""); + gridGhostHoldNote.noteData = null; gridGhostHoldNote.visible = false; add(gridGhostHoldNote); gridGhostHoldNote.zIndex = 11; + while (gridPlayheadGhostHoldNotes.length < (STRUMLINE_SIZE * 2)) + { + var ghost = new ChartEditorHoldNoteSprite(this); + ghost.alpha = 0.6; + ghost.noteData = null; + ghost.visible = false; + add(ghost); + ghost.zIndex = 11; + + gridPlayheadGhostHoldNotes.push(ghost); + } + gridGhostEvent = new ChartEditorEventSprite(this); gridGhostEvent.alpha = 0.6; gridGhostEvent.eventData = new SongEventData(-1, '', {}); @@ -2702,6 +2802,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ function setupTurboKeyHandlers():Void { + // Keyboard shortcuts add(undoKeyHandler); add(redoKeyHandler); add(upKeyHandler); @@ -2710,6 +2811,20 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState add(sKeyHandler); add(pageUpKeyHandler); add(pageDownKeyHandler); + + // Gamepad inputs + add(dpadUpGamepadHandler); + add(dpadDownGamepadHandler); + add(dpadLeftGamepadHandler); + add(dpadRightGamepadHandler); + add(leftStickUpGamepadHandler); + add(leftStickDownGamepadHandler); + add(leftStickLeftGamepadHandler); + add(leftStickRightGamepadHandler); + add(rightStickUpGamepadHandler); + add(rightStickDownGamepadHandler); + add(rightStickLeftGamepadHandler); + add(rightStickRightGamepadHandler); } /** @@ -2865,6 +2980,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState handleTestKeybinds(); handleHelpKeybinds(); + this.handleGamepadControls(); + #if debug handleQuickWatch(); #end @@ -3370,32 +3487,56 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Up Arrow = Scroll Up if (upKeyHandler.activated && currentLiveInputStyle == None) { - scrollAmount = -GRID_SIZE * 0.25 * 25.0; + scrollAmount = -GRID_SIZE * 4; shouldPause = true; } // Down Arrow = Scroll Down if (downKeyHandler.activated && currentLiveInputStyle == None) { - scrollAmount = GRID_SIZE * 0.25 * 25.0; + scrollAmount = GRID_SIZE * 4; shouldPause = true; } // W = Scroll Up (doesn't work with Ctrl+Scroll) if (wKeyHandler.activated && currentLiveInputStyle == None && !FlxG.keys.pressed.CONTROL) { - scrollAmount = -GRID_SIZE * 0.25 * 25.0; + scrollAmount = -GRID_SIZE * 4; shouldPause = true; } // S = Scroll Down (doesn't work with Ctrl+Scroll) if (sKeyHandler.activated && currentLiveInputStyle == None && !FlxG.keys.pressed.CONTROL) { - scrollAmount = GRID_SIZE * 0.25 * 25.0; + scrollAmount = GRID_SIZE * 4; shouldPause = true; } - // PAGE UP = Jump up to nearest measure - if (pageUpKeyHandler.activated) + // GAMEPAD LEFT STICK UP = Scroll Up by 1 note snap + if (leftStickUpGamepadHandler.activated) { + scrollAmount = -GRID_SIZE * noteSnapRatio; + shouldPause = true; + } + // GAMEPAD LEFT STICK DOWN = Scroll Down by 1 note snap + if (leftStickDownGamepadHandler.activated) + { + scrollAmount = GRID_SIZE * noteSnapRatio; + shouldPause = true; + } + + // GAMEPAD RIGHT STICK UP = Scroll Up by 1 note snap (playhead only) + if (rightStickUpGamepadHandler.activated) + { + playheadAmount = -GRID_SIZE * noteSnapRatio; + shouldPause = true; + } + // GAMEPAD RIGHT STICK DOWN = Scroll Down by 1 note snap (playhead only) + if (rightStickDownGamepadHandler.activated) + { + playheadAmount = GRID_SIZE * noteSnapRatio; + shouldPause = true; + } + + var funcJumpUp = (playheadOnly:Bool) -> { var measureHeight:Float = GRID_SIZE * 4 * Conductor.instance.beatsPerMeasure; var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels; var targetScrollPosition:Float = Math.floor(playheadPos / measureHeight) * measureHeight; @@ -3405,20 +3546,37 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { targetScrollPosition -= GRID_SIZE * Constants.STEPS_PER_BEAT * Conductor.instance.beatsPerMeasure; } - scrollAmount = targetScrollPosition - playheadPos; + if (playheadOnly) + { + playheadAmount = targetScrollPosition - playheadPos; + } + else + { + scrollAmount = targetScrollPosition - playheadPos; + } + } + + // PAGE UP = Jump up to nearest measure + // GAMEPAD LEFT STICK LEFT = Jump up to nearest measure + if (pageUpKeyHandler.activated || leftStickLeftGamepadHandler.activated) + { + funcJumpUp(false); + shouldPause = true; + } + if (rightStickLeftGamepadHandler.activated) + { + funcJumpUp(true); shouldPause = true; } if (playbarButtonPressed == 'playbarBack') { playbarButtonPressed = ''; - scrollAmount = -GRID_SIZE * 4 * Conductor.instance.beatsPerMeasure; + funcJumpUp(false); shouldPause = true; } - // PAGE DOWN = Jump down to nearest measure - if (pageDownKeyHandler.activated) - { + var funcJumpDown = (playheadOnly:Bool) -> { var measureHeight:Float = GRID_SIZE * 4 * Conductor.instance.beatsPerMeasure; var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels; var targetScrollPosition:Float = Math.ceil(playheadPos / measureHeight) * measureHeight; @@ -3428,26 +3586,46 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { targetScrollPosition += GRID_SIZE * Constants.STEPS_PER_BEAT * Conductor.instance.beatsPerMeasure; } - scrollAmount = targetScrollPosition - playheadPos; + if (playheadOnly) + { + playheadAmount = targetScrollPosition - playheadPos; + } + else + { + scrollAmount = targetScrollPosition - playheadPos; + } + } + + // PAGE DOWN = Jump down to nearest measure + // GAMEPAD LEFT STICK RIGHT = Jump down to nearest measure + if (pageDownKeyHandler.activated || leftStickRightGamepadHandler.activated) + { + funcJumpDown(false); + shouldPause = true; + } + if (rightStickRightGamepadHandler.activated) + { + funcJumpDown(true); shouldPause = true; } if (playbarButtonPressed == 'playbarForward') { playbarButtonPressed = ''; - scrollAmount = GRID_SIZE * 4 * Conductor.instance.beatsPerMeasure; + funcJumpDown(false); shouldPause = true; } // SHIFT + Scroll = Scroll Fast - if (FlxG.keys.pressed.SHIFT) + // GAMEPAD LEFT STICK CLICK + Scroll = Scroll Fast + if (FlxG.keys.pressed.SHIFT || (FlxG.gamepads.firstActive?.pressed?.LEFT_STICK_CLICK ?? false)) { scrollAmount *= 2; } // CONTROL + Scroll = Scroll Precise if (FlxG.keys.pressed.CONTROL) { - scrollAmount /= 10; + scrollAmount /= 4; } // Alt + Drag = Scroll but move the playhead the same amount. @@ -4520,37 +4698,77 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handlePlayhead():Void { - // Place notes at the playhead. + // Place notes at the playhead with the keyboard. switch (currentLiveInputStyle) { case ChartEditorLiveInputStyle.WASD: if (FlxG.keys.justPressed.A) placeNoteAtPlayhead(4); + if (FlxG.keys.justReleased.A) finishPlaceNoteAtPlayhead(4); if (FlxG.keys.justPressed.S) placeNoteAtPlayhead(5); + if (FlxG.keys.justReleased.S) finishPlaceNoteAtPlayhead(5); if (FlxG.keys.justPressed.W) placeNoteAtPlayhead(6); + if (FlxG.keys.justReleased.W) finishPlaceNoteAtPlayhead(6); if (FlxG.keys.justPressed.D) placeNoteAtPlayhead(7); + if (FlxG.keys.justReleased.D) finishPlaceNoteAtPlayhead(7); if (FlxG.keys.justPressed.LEFT) placeNoteAtPlayhead(0); + if (FlxG.keys.justReleased.LEFT) finishPlaceNoteAtPlayhead(0); if (FlxG.keys.justPressed.DOWN) placeNoteAtPlayhead(1); + if (FlxG.keys.justReleased.DOWN) finishPlaceNoteAtPlayhead(1); if (FlxG.keys.justPressed.UP) placeNoteAtPlayhead(2); + if (FlxG.keys.justReleased.UP) finishPlaceNoteAtPlayhead(2); if (FlxG.keys.justPressed.RIGHT) placeNoteAtPlayhead(3); + if (FlxG.keys.justReleased.RIGHT) finishPlaceNoteAtPlayhead(3); case ChartEditorLiveInputStyle.NumberKeys: // Flipped because Dad is on the left but represents data 0-3. if (FlxG.keys.justPressed.ONE) placeNoteAtPlayhead(4); + if (FlxG.keys.justReleased.ONE) finishPlaceNoteAtPlayhead(4); if (FlxG.keys.justPressed.TWO) placeNoteAtPlayhead(5); + if (FlxG.keys.justReleased.TWO) finishPlaceNoteAtPlayhead(5); if (FlxG.keys.justPressed.THREE) placeNoteAtPlayhead(6); + if (FlxG.keys.justReleased.THREE) finishPlaceNoteAtPlayhead(6); if (FlxG.keys.justPressed.FOUR) placeNoteAtPlayhead(7); + if (FlxG.keys.justReleased.FOUR) finishPlaceNoteAtPlayhead(7); if (FlxG.keys.justPressed.FIVE) placeNoteAtPlayhead(0); + if (FlxG.keys.justReleased.FIVE) finishPlaceNoteAtPlayhead(0); if (FlxG.keys.justPressed.SIX) placeNoteAtPlayhead(1); if (FlxG.keys.justPressed.SEVEN) placeNoteAtPlayhead(2); + if (FlxG.keys.justReleased.SEVEN) finishPlaceNoteAtPlayhead(2); if (FlxG.keys.justPressed.EIGHT) placeNoteAtPlayhead(3); + if (FlxG.keys.justReleased.EIGHT) finishPlaceNoteAtPlayhead(3); case ChartEditorLiveInputStyle.None: // Do nothing. } + + // Place notes at the playhead with the gamepad. + if (FlxG.gamepads.firstActive != null) + { + if (FlxG.gamepads.firstActive.justPressed.DPAD_LEFT) placeNoteAtPlayhead(4); + if (FlxG.gamepads.firstActive.justReleased.DPAD_LEFT) finishPlaceNoteAtPlayhead(4); + if (FlxG.gamepads.firstActive.justPressed.DPAD_DOWN) placeNoteAtPlayhead(5); + if (FlxG.gamepads.firstActive.justReleased.DPAD_DOWN) finishPlaceNoteAtPlayhead(5); + if (FlxG.gamepads.firstActive.justPressed.DPAD_UP) placeNoteAtPlayhead(6); + if (FlxG.gamepads.firstActive.justReleased.DPAD_UP) finishPlaceNoteAtPlayhead(6); + if (FlxG.gamepads.firstActive.justPressed.DPAD_RIGHT) placeNoteAtPlayhead(7); + if (FlxG.gamepads.firstActive.justReleased.DPAD_RIGHT) finishPlaceNoteAtPlayhead(7); + + if (FlxG.gamepads.firstActive.justPressed.X) placeNoteAtPlayhead(0); + if (FlxG.gamepads.firstActive.justReleased.X) finishPlaceNoteAtPlayhead(0); + if (FlxG.gamepads.firstActive.justPressed.A) placeNoteAtPlayhead(1); + if (FlxG.gamepads.firstActive.justReleased.A) finishPlaceNoteAtPlayhead(1); + if (FlxG.gamepads.firstActive.justPressed.Y) placeNoteAtPlayhead(2); + if (FlxG.gamepads.firstActive.justReleased.Y) finishPlaceNoteAtPlayhead(2); + if (FlxG.gamepads.firstActive.justPressed.B) placeNoteAtPlayhead(3); + if (FlxG.gamepads.firstActive.justReleased.B) finishPlaceNoteAtPlayhead(3); + } } function placeNoteAtPlayhead(column:Int):Void { + // SHIFT + press or LEFT_SHOULDER + press to remove notes instead of placing them. + var removeNoteInstead:Bool = FlxG.keys.pressed.SHIFT || (FlxG.gamepads.firstActive?.pressed?.LEFT_SHOULDER ?? false); + var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels; var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / noteSnapRatio; var playheadPosStep:Int = Std.int(Math.floor(playheadPosFractionalStep)); @@ -4561,10 +4779,18 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState playheadPosSnappedMs + Conductor.instance.stepLengthMs * noteSnapRatio); notesAtPos = SongDataUtils.getNotesWithData(notesAtPos, [column]); - if (notesAtPos.length == 0) + if (notesAtPos.length == 0 && !removeNoteInstead) { var newNoteData:SongNoteData = new SongNoteData(playheadPosSnappedMs, column, 0, noteKindToPlace); performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); + currentLiveInputPlaceNoteData[column] = newNoteData; + gridPlayheadGhostHoldNotes[column].noteData = newNoteData.clone(); + gridPlayheadGhostHoldNotes[column].noteDirection = newNoteData.getDirection(); + } + else if (removeNoteInstead) + { + trace('Removing existing note at position.'); + performCommand(new RemoveNotesCommand(notesAtPos)); } else { @@ -4572,6 +4798,87 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } } + function updatePlayheadGhostHoldNotes():Void + { + // Update playhead ghost hold notes. + for (index in 0...gridPlayheadGhostHoldNotes.length) + { + var ghostHold = gridPlayheadGhostHoldNotes[index]; + if (ghostHold == null) continue; + + if (ghostHold.noteData == null) + { + ghostHold.visible = false; + ghostHold.setHeightDirectly(0); + playheadDragLengthCurrent[index] = 0; + continue; + }; + + var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels; + var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / noteSnapRatio; + var playheadPosStep:Int = Std.int(Math.floor(playheadPosFractionalStep)); + var playheadPosSnappedMs:Float = playheadPosStep * Conductor.instance.stepLengthMs * noteSnapRatio; + + var newNoteLength:Float = playheadPosSnappedMs - ghostHold.noteData.time; + trace('newNoteLength: ${newNoteLength}'); + + if (newNoteLength > 0) + { + ghostHold.noteData.length = newNoteLength; + var targetNoteLengthSteps:Float = ghostHold.noteData.getStepLength(true); + var targetNoteLengthStepsInt:Int = Std.int(Math.floor(targetNoteLengthSteps)); + var targetNoteLengthPixels:Float = targetNoteLengthSteps * GRID_SIZE; + + if (playheadDragLengthCurrent[index] != targetNoteLengthStepsInt) + { + stretchySounds = !stretchySounds; + this.playSound(Paths.sound('chartingSounds/stretch' + (stretchySounds ? '1' : '2') + '_UI')); + playheadDragLengthCurrent[index] = targetNoteLengthStepsInt; + } + ghostHold.visible = true; + trace('newHeight: ${targetNoteLengthPixels}'); + ghostHold.setHeightDirectly(targetNoteLengthPixels, true); + ghostHold.updateHoldNotePosition(renderedHoldNotes); + } + else + { + ghostHold.visible = false; + ghostHold.setHeightDirectly(0); + playheadDragLengthCurrent[index] = 0; + } + } + } + + function finishPlaceNoteAtPlayhead(column:Int):Void + { + if (currentLiveInputPlaceNoteData[column] == null) return; + + var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels; + var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / noteSnapRatio; + var playheadPosStep:Int = Std.int(Math.floor(playheadPosFractionalStep)); + var playheadPosSnappedMs:Float = playheadPosStep * Conductor.instance.stepLengthMs * noteSnapRatio; + + var newNoteLength:Float = playheadPosSnappedMs - currentLiveInputPlaceNoteData[column].time; + trace('finishPlace newNoteLength: ${newNoteLength}'); + + if (newNoteLength < Conductor.instance.stepLengthMs) + { + // Don't extend the note if it's too short. + trace('Not extending note.'); + currentLiveInputPlaceNoteData[column] = null; + gridPlayheadGhostHoldNotes[column].noteData = null; + } + else + { + // Extend the note to the playhead position. + trace('Extending note.'); + this.playSound(Paths.sound('chartingSounds/stretchSNAP_UI')); + performCommand(new ExtendNoteLengthCommand(currentLiveInputPlaceNoteData[column], newNoteLength)); + currentLiveInputPlaceNoteData[column] = null; + gridPlayheadGhostHoldNotes[column].noteData = null; + } + } + /** * Handle aligning the health icons next to the grid. */ diff --git a/source/funkin/ui/debug/charting/commands/RemoveEventsCommand.hx b/source/funkin/ui/debug/charting/commands/RemoveEventsCommand.hx index 7e620c210..102257fc8 100644 --- a/source/funkin/ui/debug/charting/commands/RemoveEventsCommand.hx +++ b/source/funkin/ui/debug/charting/commands/RemoveEventsCommand.hx @@ -20,6 +20,8 @@ class RemoveEventsCommand implements ChartEditorCommand public function execute(state:ChartEditorState):Void { + if (events.length == 0) return; + state.currentSongChartEventData = SongDataUtils.subtractEvents(state.currentSongChartEventData, events); state.currentEventSelection = []; @@ -34,6 +36,8 @@ class RemoveEventsCommand implements ChartEditorCommand public function undo(state:ChartEditorState):Void { + if (events.length == 0) return; + for (event in events) { state.currentSongChartEventData.push(event); diff --git a/source/funkin/ui/debug/charting/commands/RemoveItemsCommand.hx b/source/funkin/ui/debug/charting/commands/RemoveItemsCommand.hx index 77184209e..376908726 100644 --- a/source/funkin/ui/debug/charting/commands/RemoveItemsCommand.hx +++ b/source/funkin/ui/debug/charting/commands/RemoveItemsCommand.hx @@ -23,6 +23,8 @@ class RemoveItemsCommand implements ChartEditorCommand public function execute(state:ChartEditorState):Void { + if ((notes.length + events.length) == 0) return; + state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, notes); state.currentSongChartEventData = SongDataUtils.subtractEvents(state.currentSongChartEventData, events); @@ -40,6 +42,8 @@ class RemoveItemsCommand implements ChartEditorCommand public function undo(state:ChartEditorState):Void { + if ((notes.length + events.length) == 0) return; + for (note in notes) { state.currentSongChartNoteData.push(note); diff --git a/source/funkin/ui/debug/charting/commands/RemoveNotesCommand.hx b/source/funkin/ui/debug/charting/commands/RemoveNotesCommand.hx index e189be83e..4e7b480dd 100644 --- a/source/funkin/ui/debug/charting/commands/RemoveNotesCommand.hx +++ b/source/funkin/ui/debug/charting/commands/RemoveNotesCommand.hx @@ -20,6 +20,8 @@ class RemoveNotesCommand implements ChartEditorCommand public function execute(state:ChartEditorState):Void { + if (notes.length == 0) return; + state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, notes); state.currentNoteSelection = []; state.currentEventSelection = []; @@ -35,6 +37,8 @@ class RemoveNotesCommand implements ChartEditorCommand public function undo(state:ChartEditorState):Void { + if (notes.length == 0) return; + for (note in notes) { state.currentSongChartNoteData.push(note); diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index e5971db08..193390341 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -43,11 +43,16 @@ class ChartEditorHoldNoteSprite extends SustainTrail * Set the height directly, to a value in pixels. * @param h The desired height in pixels. */ - public function setHeightDirectly(h:Float, ?lerp:Bool = false) + public function setHeightDirectly(h:Float, lerp:Bool = false) { - if (lerp != null && lerp) sustainLength = FlxMath.lerp(sustainLength, h / (getScrollSpeed() * Constants.PIXELS_PER_MS), 0.25); + if (lerp) + { + sustainLength = FlxMath.lerp(sustainLength, h / (getScrollSpeed() * Constants.PIXELS_PER_MS), 0.25); + } else + { sustainLength = h / (getScrollSpeed() * Constants.PIXELS_PER_MS); + } fullSustainLength = sustainLength; } diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorGamepadHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorGamepadHandler.hx new file mode 100644 index 000000000..896e2df68 --- /dev/null +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorGamepadHandler.hx @@ -0,0 +1,133 @@ +package funkin.ui.debug.charting.handlers; + +/** + * Yes, we're that crazy. Gamepad support for the chart editor. + */ +@:nullSafety +@:access(funkin.ui.debug.charting.ChartEditorState) +class ChartEditorGamepadHandler +{ + public static function handleGamepadControls(chartEditorState:ChartEditorState) + { + if (FlxG.gamepads.firstActive == null) return; + + if (FlxG.gamepads.firstActive.justPressed.A) + { + // trace('Gamepad: A pressed'); + } + if (FlxG.gamepads.firstActive.justPressed.B) + { + // trace('Gamepad: B pressed'); + } + if (FlxG.gamepads.firstActive.justPressed.X) + { + // trace('Gamepad: X pressed'); + } + if (FlxG.gamepads.firstActive.justPressed.Y) + { + // trace('Gamepad: Y pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.LEFT_SHOULDER) + { + // trace('Gamepad: LEFT_SHOULDER pressed'); + } + if (FlxG.gamepads.firstActive.justPressed.RIGHT_SHOULDER) + { + // trace('Gamepad: RIGHT_SHOULDER pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_CLICK) + { + // trace('Gamepad: LEFT_STICK_CLICK pressed'); + } + if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_CLICK) + { + // trace('Gamepad: RIGHT_STICK_CLICK pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.LEFT_TRIGGER) + { + // trace('Gamepad: LEFT_TRIGGER pressed'); + } + if (FlxG.gamepads.firstActive.justPressed.RIGHT_TRIGGER) + { + // trace('Gamepad: RIGHT_TRIGGER pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.START) + { + // trace('Gamepad: START pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.BACK) + { + // trace('Gamepad: BACK pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.GUIDE) + { + // trace('Gamepad: GUIDE pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.DPAD_UP) + { + // trace('Gamepad: DPAD_UP pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.DPAD_DOWN) + { + // trace('Gamepad: DPAD_DOWN pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.DPAD_LEFT) + { + // trace('Gamepad: DPAD_LEFT pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.DPAD_RIGHT) + { + // trace('Gamepad: DPAD_RIGHT pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_DIGITAL_UP) + { + // trace('Gamepad: LEFT_STICK_DIGITAL_UP pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_DIGITAL_DOWN) + { + // trace('Gamepad: LEFT_STICK_DIGITAL_DOWN pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_DIGITAL_LEFT) + { + // trace('Gamepad: LEFT_STICK_DIGITAL_LEFT pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_DIGITAL_RIGHT) + { + // trace('Gamepad: LEFT_STICK_DIGITAL_RIGHT pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_DIGITAL_UP) + { + // trace('Gamepad: RIGHT_STICK_DIGITAL_UP pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_DIGITAL_DOWN) + { + // trace('Gamepad: RIGHT_STICK_DIGITAL_DOWN pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_DIGITAL_LEFT) + { + // trace('Gamepad: RIGHT_STICK_DIGITAL_LEFT pressed'); + } + + if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_DIGITAL_RIGHT) + { + // trace('Gamepad: RIGHT_STICK_DIGITAL_RIGHT pressed'); + } + } +} diff --git a/source/funkin/ui/debug/charting/import.hx b/source/funkin/ui/debug/charting/import.hx index b0569e3bb..2c3d59ef7 100644 --- a/source/funkin/ui/debug/charting/import.hx +++ b/source/funkin/ui/debug/charting/import.hx @@ -5,6 +5,7 @@ package funkin.ui.debug.charting; using funkin.ui.debug.charting.handlers.ChartEditorAudioHandler; using funkin.ui.debug.charting.handlers.ChartEditorContextMenuHandler; using funkin.ui.debug.charting.handlers.ChartEditorDialogHandler; +using funkin.ui.debug.charting.handlers.ChartEditorGamepadHandler; using funkin.ui.debug.charting.handlers.ChartEditorImportExportHandler; using funkin.ui.debug.charting.handlers.ChartEditorNotificationHandler; using funkin.ui.debug.charting.handlers.ChartEditorShortcutHandler; From c6b3499897fd81090f2e7f564dc8d4bf7fe84b0d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 8 Jan 2024 21:26:24 -0500 Subject: [PATCH 02/43] Finished up hold note placement on gamepad, implemented note preview playhead --- source/Main.hx | 2 + .../ui/debug/charting/ChartEditorState.hx | 130 ++++++----- .../handlers/ChartEditorGamepadHandler.hx | 202 ++++++++++++------ .../ui/haxeui/FlxGamepadActionInputSource.hx | 53 +++++ 4 files changed, 263 insertions(+), 124 deletions(-) create mode 100644 source/funkin/ui/haxeui/FlxGamepadActionInputSource.hx diff --git a/source/Main.hx b/source/Main.hx index 86e520e69..a7482c8d6 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -111,6 +111,8 @@ class Main extends Sprite Toolkit.init(); Toolkit.theme = 'dark'; // don't be cringe Toolkit.autoScale = false; + // Don't focus on UI elements when they first appear. + haxe.ui.focus.FocusManager.instance.autoFocus = false; funkin.input.Cursor.registerHaxeUICursors(); haxe.ui.tooltips.ToolTipManager.defaultDelay = 200; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index f3236578a..1b9176174 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -366,8 +366,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } } - updatePlayheadGhostHoldNotes(); - // Move the rendered notes to the correct position. renderedNotes.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0); renderedHoldNotes.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0); @@ -375,8 +373,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState renderedSelectionSquares.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0); // Offset the selection box start position, if we are dragging. if (selectionBoxStartPos != null) selectionBoxStartPos.y -= diff; - // Update the note preview viewport box. + + // Update the note preview. setNotePreviewViewportBounds(calculateNotePreviewViewportBounds()); + refreshNotePreviewPlayheadPosition(); + // Update the measure tick display. if (measureTicks != null) measureTicks.y = gridTiledSprite?.y ?? 0.0; return this.scrollPositionInPixels; @@ -438,6 +439,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState gridPlayhead.y = this.playheadPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD); updatePlayheadGhostHoldNotes(); + refreshNotePreviewPlayheadPosition(); return this.playheadPositionInPixels; } @@ -1842,6 +1844,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ var notePreviewViewport:Null = null; + /** + * The thin sprite used for representing the playhead on the note preview. + * We move this up and down to represent the current position. + */ + var notePreviewPlayhead:Null = null; + /** * The rectangular sprite used for rendering the selection box. * Uses a 9-slice to stretch the selection box to the correct size without warping. @@ -2219,18 +2227,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState add(gridGhostHoldNote); gridGhostHoldNote.zIndex = 11; - while (gridPlayheadGhostHoldNotes.length < (STRUMLINE_SIZE * 2)) - { - var ghost = new ChartEditorHoldNoteSprite(this); - ghost.alpha = 0.6; - ghost.noteData = null; - ghost.visible = false; - add(ghost); - ghost.zIndex = 11; - - gridPlayheadGhostHoldNotes.push(ghost); - } - gridGhostEvent = new ChartEditorEventSprite(this); gridGhostEvent.alpha = 0.6; gridGhostEvent.eventData = new SongEventData(-1, '', {}); @@ -2300,6 +2296,15 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState add(notePreviewViewport); notePreviewViewport.zIndex = 30; + notePreviewPlayhead = new FlxSprite().makeGraphic(2, 2, 0xFFFF0000); + notePreviewPlayhead.scrollFactor.set(0, 0); + notePreviewPlayhead.scale.set(notePreview.width / 2, 0.5); // Setting width does nothing. + notePreviewPlayhead.updateHitbox(); + notePreviewPlayhead.x = notePreview.x; + notePreviewPlayhead.y = notePreview.y; + add(notePreviewPlayhead); + notePreviewPlayhead.zIndex = 31; + setNotePreviewViewportBounds(calculateNotePreviewViewportBounds()); } @@ -2399,6 +2404,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } } + function refreshNotePreviewPlayheadPosition():Void + { + if (notePreviewPlayhead == null) return; + + notePreviewPlayhead.y = notePreview.y + (notePreview.height * ((scrollPositionInPixels + playheadPositionInPixels) / songLengthInPixels)); + } + /** * Builds the group that will hold all the notes. */ @@ -4194,7 +4206,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState gridGhostHoldNote.visible = true; gridGhostHoldNote.noteData = gridGhostNote.noteData; gridGhostHoldNote.noteDirection = gridGhostNote.noteData.getDirection(); - gridGhostHoldNote.setHeightDirectly(dragLengthPixels, true); gridGhostHoldNote.updateHoldNotePosition(renderedHoldNotes); @@ -4741,27 +4752,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Do nothing. } - // Place notes at the playhead with the gamepad. - if (FlxG.gamepads.firstActive != null) - { - if (FlxG.gamepads.firstActive.justPressed.DPAD_LEFT) placeNoteAtPlayhead(4); - if (FlxG.gamepads.firstActive.justReleased.DPAD_LEFT) finishPlaceNoteAtPlayhead(4); - if (FlxG.gamepads.firstActive.justPressed.DPAD_DOWN) placeNoteAtPlayhead(5); - if (FlxG.gamepads.firstActive.justReleased.DPAD_DOWN) finishPlaceNoteAtPlayhead(5); - if (FlxG.gamepads.firstActive.justPressed.DPAD_UP) placeNoteAtPlayhead(6); - if (FlxG.gamepads.firstActive.justReleased.DPAD_UP) finishPlaceNoteAtPlayhead(6); - if (FlxG.gamepads.firstActive.justPressed.DPAD_RIGHT) placeNoteAtPlayhead(7); - if (FlxG.gamepads.firstActive.justReleased.DPAD_RIGHT) finishPlaceNoteAtPlayhead(7); - - if (FlxG.gamepads.firstActive.justPressed.X) placeNoteAtPlayhead(0); - if (FlxG.gamepads.firstActive.justReleased.X) finishPlaceNoteAtPlayhead(0); - if (FlxG.gamepads.firstActive.justPressed.A) placeNoteAtPlayhead(1); - if (FlxG.gamepads.firstActive.justReleased.A) finishPlaceNoteAtPlayhead(1); - if (FlxG.gamepads.firstActive.justPressed.Y) placeNoteAtPlayhead(2); - if (FlxG.gamepads.firstActive.justReleased.Y) finishPlaceNoteAtPlayhead(2); - if (FlxG.gamepads.firstActive.justPressed.B) placeNoteAtPlayhead(3); - if (FlxG.gamepads.firstActive.justReleased.B) finishPlaceNoteAtPlayhead(3); - } + updatePlayheadGhostHoldNotes(); } function placeNoteAtPlayhead(column:Int):Void @@ -4781,38 +4772,68 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (notesAtPos.length == 0 && !removeNoteInstead) { + trace('Placing note. ${column}'); var newNoteData:SongNoteData = new SongNoteData(playheadPosSnappedMs, column, 0, noteKindToPlace); performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); currentLiveInputPlaceNoteData[column] = newNoteData; - gridPlayheadGhostHoldNotes[column].noteData = newNoteData.clone(); - gridPlayheadGhostHoldNotes[column].noteDirection = newNoteData.getDirection(); } else if (removeNoteInstead) { - trace('Removing existing note at position.'); + trace('Removing existing note at position. ${column}'); performCommand(new RemoveNotesCommand(notesAtPos)); } else { - trace('Already a note there.'); + trace('Already a note there. ${column}'); } } function updatePlayheadGhostHoldNotes():Void { - // Update playhead ghost hold notes. - for (index in 0...gridPlayheadGhostHoldNotes.length) + // Ensure all the ghost hold notes exist. + while (gridPlayheadGhostHoldNotes.length < (STRUMLINE_SIZE * 2)) { - var ghostHold = gridPlayheadGhostHoldNotes[index]; - if (ghostHold == null) continue; + var ghost = new ChartEditorHoldNoteSprite(this); + ghost.alpha = 0.6; + ghost.noteData = null; + ghost.visible = false; + ghost.zIndex = 11; + add(ghost); // Don't add to `renderedHoldNotes` because then it will get killed every frame. + + gridPlayheadGhostHoldNotes.push(ghost); + refresh(); + } + + // Update playhead ghost hold notes. + for (column in 0...gridPlayheadGhostHoldNotes.length) + { + var targetNoteData = currentLiveInputPlaceNoteData[column]; + var ghostHold = gridPlayheadGhostHoldNotes[column]; + + if (targetNoteData == null && ghostHold.noteData != null) + { + // Remove the ghost hold note. + ghostHold.noteData = null; + } + + if (targetNoteData != null && ghostHold.noteData == null) + { + // Readd the new ghost hold note. + ghostHold.noteData = targetNoteData.clone(); + ghostHold.noteDirection = ghostHold.noteData.getDirection(); + ghostHold.visible = true; + ghostHold.alpha = 0.6; + ghostHold.setHeightDirectly(0); + ghostHold.updateHoldNotePosition(renderedHoldNotes); + } if (ghostHold.noteData == null) { ghostHold.visible = false; ghostHold.setHeightDirectly(0); - playheadDragLengthCurrent[index] = 0; + playheadDragLengthCurrent[column] = 0; continue; - }; + } var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels; var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / noteSnapRatio; @@ -4829,22 +4850,25 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var targetNoteLengthStepsInt:Int = Std.int(Math.floor(targetNoteLengthSteps)); var targetNoteLengthPixels:Float = targetNoteLengthSteps * GRID_SIZE; - if (playheadDragLengthCurrent[index] != targetNoteLengthStepsInt) + if (playheadDragLengthCurrent[column] != targetNoteLengthStepsInt) { stretchySounds = !stretchySounds; this.playSound(Paths.sound('chartingSounds/stretch' + (stretchySounds ? '1' : '2') + '_UI')); - playheadDragLengthCurrent[index] = targetNoteLengthStepsInt; + playheadDragLengthCurrent[column] = targetNoteLengthStepsInt; } ghostHold.visible = true; - trace('newHeight: ${targetNoteLengthPixels}'); + ghostHold.alpha = 0.6; ghostHold.setHeightDirectly(targetNoteLengthPixels, true); ghostHold.updateHoldNotePosition(renderedHoldNotes); + trace('lerpLength: ${ghostHold.fullSustainLength}'); + trace('position: ${ghostHold.x}, ${ghostHold.y}'); } else { ghostHold.visible = false; ghostHold.setHeightDirectly(0); - playheadDragLengthCurrent[index] = 0; + playheadDragLengthCurrent[column] = 0; + continue; } } } @@ -4864,14 +4888,14 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (newNoteLength < Conductor.instance.stepLengthMs) { // Don't extend the note if it's too short. - trace('Not extending note.'); + trace('Not extending note. ${column}'); currentLiveInputPlaceNoteData[column] = null; gridPlayheadGhostHoldNotes[column].noteData = null; } else { // Extend the note to the playhead position. - trace('Extending note.'); + trace('Extending note. ${column}'); this.playSound(Paths.sound('chartingSounds/stretchSNAP_UI')); performCommand(new ExtendNoteLengthCommand(currentLiveInputPlaceNoteData[column], newNoteLength)); currentLiveInputPlaceNoteData[column] = null; diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorGamepadHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorGamepadHandler.hx index 896e2df68..70383d3fd 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorGamepadHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorGamepadHandler.hx @@ -1,133 +1,193 @@ package funkin.ui.debug.charting.handlers; +import haxe.ui.focus.FocusManager; +import flixel.input.gamepad.FlxGamepad; +import haxe.ui.actions.ActionManager; +import haxe.ui.actions.IActionInputSource; +import haxe.ui.actions.ActionType; + /** * Yes, we're that crazy. Gamepad support for the chart editor. */ -@:nullSafety +// @:nullSafety + @:access(funkin.ui.debug.charting.ChartEditorState) class ChartEditorGamepadHandler { public static function handleGamepadControls(chartEditorState:ChartEditorState) { - if (FlxG.gamepads.firstActive == null) return; + if (FlxG.gamepads.firstActive != null) handleGamepad(chartEditorState, FlxG.gamepads.firstActive); + } - if (FlxG.gamepads.firstActive.justPressed.A) + /** + * Handle context-generic binds for the gamepad. + * @param chartEditorState The chart editor state. + * @param gamepad The gamepad to handle. + */ + static function handleGamepad(chartEditorState:ChartEditorState, gamepad:FlxGamepad):Void + { + if (chartEditorState.isHaxeUIFocused) { - // trace('Gamepad: A pressed'); + ChartEditorGamepadActionInputSource.instance.handleGamepad(gamepad); } - if (FlxG.gamepads.firstActive.justPressed.B) + else { - // trace('Gamepad: B pressed'); - } - if (FlxG.gamepads.firstActive.justPressed.X) - { - // trace('Gamepad: X pressed'); - } - if (FlxG.gamepads.firstActive.justPressed.Y) - { - // trace('Gamepad: Y pressed'); + handleGamepadLiveInputs(chartEditorState, gamepad); + + if (gamepad.justPressed.RIGHT_SHOULDER) + { + trace('Gamepad: Right shoulder pressed, toggling audio playback.'); + chartEditorState.toggleAudioPlayback(); + } + + if (gamepad.justPressed.START) + { + var minimal = gamepad.pressed.LEFT_SHOULDER; + chartEditorState.hideAllToolboxes(); + trace('Gamepad: Start pressed, opening playtest (minimal: ${minimal})'); + chartEditorState.testSongInPlayState(minimal); + } + + if (gamepad.justPressed.BACK && !gamepad.pressed.LEFT_SHOULDER) + { + trace('Gamepad: Back pressed, focusing on HaxeUI menu.'); + // FocusManager.instance.focus = chartEditorState.menubarMenuFile; + } + else if (gamepad.justPressed.BACK && gamepad.pressed.LEFT_SHOULDER) + { + trace('Gamepad: Back pressed, unfocusing on HaxeUI menu.'); + FocusManager.instance.focus = null; + } } - if (FlxG.gamepads.firstActive.justPressed.LEFT_SHOULDER) + if (gamepad.justPressed.GUIDE) { - // trace('Gamepad: LEFT_SHOULDER pressed'); - } - if (FlxG.gamepads.firstActive.justPressed.RIGHT_SHOULDER) - { - // trace('Gamepad: RIGHT_SHOULDER pressed'); + trace('Gamepad: Guide pressed, quitting chart editor.'); + chartEditorState.quitChartEditor(); } + } - if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_CLICK) + static function handleGamepadLiveInputs(chartEditorState:ChartEditorState, gamepad:FlxGamepad):Void + { + // Place notes at the playhead with the gamepad. + // Disable when we are interacting with HaxeUI. + if (!(chartEditorState.isHaxeUIFocused || chartEditorState.isHaxeUIDialogOpen)) { - // trace('Gamepad: LEFT_STICK_CLICK pressed'); - } - if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_CLICK) - { - // trace('Gamepad: RIGHT_STICK_CLICK pressed'); - } + if (gamepad.justPressed.DPAD_LEFT) chartEditorState.placeNoteAtPlayhead(4); + if (gamepad.justReleased.DPAD_LEFT) chartEditorState.finishPlaceNoteAtPlayhead(4); + if (gamepad.justPressed.DPAD_DOWN) chartEditorState.placeNoteAtPlayhead(5); + if (gamepad.justReleased.DPAD_DOWN) chartEditorState.finishPlaceNoteAtPlayhead(5); + if (gamepad.justPressed.DPAD_UP) chartEditorState.placeNoteAtPlayhead(6); + if (gamepad.justReleased.DPAD_UP) chartEditorState.finishPlaceNoteAtPlayhead(6); + if (gamepad.justPressed.DPAD_RIGHT) chartEditorState.placeNoteAtPlayhead(7); + if (gamepad.justReleased.DPAD_RIGHT) chartEditorState.finishPlaceNoteAtPlayhead(7); - if (FlxG.gamepads.firstActive.justPressed.LEFT_TRIGGER) + if (gamepad.justPressed.X) chartEditorState.placeNoteAtPlayhead(0); + if (gamepad.justReleased.X) chartEditorState.finishPlaceNoteAtPlayhead(0); + if (gamepad.justPressed.A) chartEditorState.placeNoteAtPlayhead(1); + if (gamepad.justReleased.A) chartEditorState.finishPlaceNoteAtPlayhead(1); + if (gamepad.justPressed.Y) chartEditorState.placeNoteAtPlayhead(2); + if (gamepad.justReleased.Y) chartEditorState.finishPlaceNoteAtPlayhead(2); + if (gamepad.justPressed.B) chartEditorState.placeNoteAtPlayhead(3); + if (gamepad.justReleased.B) chartEditorState.finishPlaceNoteAtPlayhead(3); + } + } +} + +class ChartEditorGamepadActionInputSource implements IActionInputSource +{ + public static var instance:ChartEditorGamepadActionInputSource = new ChartEditorGamepadActionInputSource(); + + public function new() {} + + public function start():Void {} + + /** + * Handle HaxeUI-specific binds for the gamepad. + * Only called when the HaxeUI menu is focused. + * @param chartEditorState The chart editor state. + * @param gamepad The gamepad to handle. + */ + public function handleGamepad(gamepad:FlxGamepad):Void + { + if (gamepad.justPressed.DPAD_LEFT) { - // trace('Gamepad: LEFT_TRIGGER pressed'); + trace('Gamepad: DPAD_LEFT pressed, moving left.'); + ActionManager.instance.actionStart(ActionType.LEFT, this); } - if (FlxG.gamepads.firstActive.justPressed.RIGHT_TRIGGER) - { - // trace('Gamepad: RIGHT_TRIGGER pressed'); - } - - if (FlxG.gamepads.firstActive.justPressed.START) + else if (gamepad.justReleased.DPAD_LEFT) { - // trace('Gamepad: START pressed'); + ActionManager.instance.actionEnd(ActionType.LEFT, this); } - if (FlxG.gamepads.firstActive.justPressed.BACK) + if (gamepad.justPressed.DPAD_RIGHT) { - // trace('Gamepad: BACK pressed'); + trace('Gamepad: DPAD_RIGHT pressed, moving right.'); + ActionManager.instance.actionStart(ActionType.RIGHT, this); } - - if (FlxG.gamepads.firstActive.justPressed.GUIDE) + else if (gamepad.justReleased.DPAD_RIGHT) { - // trace('Gamepad: GUIDE pressed'); + ActionManager.instance.actionEnd(ActionType.RIGHT, this); } - if (FlxG.gamepads.firstActive.justPressed.DPAD_UP) + if (gamepad.justPressed.DPAD_UP) { - // trace('Gamepad: DPAD_UP pressed'); + trace('Gamepad: DPAD_UP pressed, moving up.'); + ActionManager.instance.actionStart(ActionType.UP, this); } - - if (FlxG.gamepads.firstActive.justPressed.DPAD_DOWN) + else if (gamepad.justReleased.DPAD_UP) { - // trace('Gamepad: DPAD_DOWN pressed'); + ActionManager.instance.actionEnd(ActionType.UP, this); } - if (FlxG.gamepads.firstActive.justPressed.DPAD_LEFT) + if (gamepad.justPressed.DPAD_DOWN) { - // trace('Gamepad: DPAD_LEFT pressed'); + trace('Gamepad: DPAD_DOWN pressed, moving down.'); + ActionManager.instance.actionStart(ActionType.DOWN, this); } - - if (FlxG.gamepads.firstActive.justPressed.DPAD_RIGHT) + else if (gamepad.justReleased.DPAD_DOWN) { - // trace('Gamepad: DPAD_RIGHT pressed'); + ActionManager.instance.actionEnd(ActionType.DOWN, this); } - if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_DIGITAL_UP) + if (gamepad.justPressed.A) { - // trace('Gamepad: LEFT_STICK_DIGITAL_UP pressed'); + trace('Gamepad: A pressed, confirmingg.'); + ActionManager.instance.actionStart(ActionType.CONFIRM, this); } - - if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_DIGITAL_DOWN) + else if (gamepad.justReleased.A) { - // trace('Gamepad: LEFT_STICK_DIGITAL_DOWN pressed'); + ActionManager.instance.actionEnd(ActionType.CONFIRM, this); } - if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_DIGITAL_LEFT) + if (gamepad.justPressed.B) { - // trace('Gamepad: LEFT_STICK_DIGITAL_LEFT pressed'); + trace('Gamepad: B pressed, cancelling.'); + ActionManager.instance.actionStart(ActionType.CANCEL, this); } - - if (FlxG.gamepads.firstActive.justPressed.LEFT_STICK_DIGITAL_RIGHT) + else if (gamepad.justReleased.B) { - // trace('Gamepad: LEFT_STICK_DIGITAL_RIGHT pressed'); + ActionManager.instance.actionEnd(ActionType.CANCEL, this); } - if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_DIGITAL_UP) + if (gamepad.justPressed.LEFT_TRIGGER) { - // trace('Gamepad: RIGHT_STICK_DIGITAL_UP pressed'); + trace('Gamepad: LEFT_TRIGGER pressed, moving to previous item.'); + ActionManager.instance.actionStart(ActionType.PREVIOUS, this); } - - if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_DIGITAL_DOWN) + else if (gamepad.justReleased.LEFT_TRIGGER) { - // trace('Gamepad: RIGHT_STICK_DIGITAL_DOWN pressed'); + ActionManager.instance.actionEnd(ActionType.PREVIOUS, this); } - if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_DIGITAL_LEFT) + if (gamepad.justPressed.RIGHT_TRIGGER) { - // trace('Gamepad: RIGHT_STICK_DIGITAL_LEFT pressed'); + trace('Gamepad: RIGHT_TRIGGER pressed, moving to next item.'); + ActionManager.instance.actionStart(ActionType.NEXT, this); } - - if (FlxG.gamepads.firstActive.justPressed.RIGHT_STICK_DIGITAL_RIGHT) + else if (gamepad.justReleased.RIGHT_TRIGGER) { - // trace('Gamepad: RIGHT_STICK_DIGITAL_RIGHT pressed'); + ActionManager.instance.actionEnd(ActionType.NEXT, this); } } } diff --git a/source/funkin/ui/haxeui/FlxGamepadActionInputSource.hx b/source/funkin/ui/haxeui/FlxGamepadActionInputSource.hx new file mode 100644 index 000000000..9c2901d16 --- /dev/null +++ b/source/funkin/ui/haxeui/FlxGamepadActionInputSource.hx @@ -0,0 +1,53 @@ +package funkin.ui.haxeui; + +import flixel.FlxBasic; +import flixel.input.gamepad.FlxGamepad; +import haxe.ui.actions.IActionInputSource; + +/** + * Receives button presses from the Flixel gamepad and emits HaxeUI events. + */ +class FlxGamepadActionInputSource extends FlxBasic +{ + public static var instance(get, null):FlxGamepadActionInputSource; + + static function get_instance():FlxGamepadActionInputSource + { + if (instance == null) instance = new FlxGamepadActionInputSource(); + return instance; + } + + public function new() + { + super(); + } + + public function start():Void + { + FlxG.plugins.addPlugin(this); + } + + public override function update(elapsed:Float):Void + { + super.update(elapsed); + + if (FlxG.gamepads.firstActive != null) + { + updateGamepad(elapsed, FlxG.gamepads.firstActive); + } + } + + function updateGamepad(elapsed:Float, gamepad:FlxGamepad):Void + { + if (gamepad.justPressed.BACK) + { + // + } + } + + public override function destroy():Void + { + super.destroy(); + FlxG.plugins.remove(this); + } +} From 2dbc0cda6e63a56eccb81f8ad8eb63407dfbc3d7 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 13 Feb 2024 03:18:51 -0500 Subject: [PATCH 03/43] Fix a missing import. --- source/funkin/ui/debug/charting/ChartEditorState.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 6d2b47ef4..d0ed095cc 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -45,6 +45,7 @@ import funkin.graphics.FunkinCamera; import funkin.graphics.FunkinSprite; import funkin.input.Cursor; import funkin.input.TurboActionHandler; +import funkin.input.TurboButtonHandler; import funkin.input.TurboKeyHandler; import funkin.modding.events.ScriptEvent; import funkin.play.character.BaseCharacter.CharacterType; From 8a9a8bb179976b35ee688fcc5fcd6af116f06869 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 22 Feb 2024 01:50:55 -0500 Subject: [PATCH 04/43] abot bars in probress --- assets | 2 +- hmm.json | 9 ++++++++- source/funkin/audio/visualize/ABotVis.hx | 4 +--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/assets b/assets index c8f320e89..d9a0b3b0b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c8f320e89f65f9e6242354b25f04aac2c07cceeb +Subproject commit d9a0b3b0bcc5b9cac89dde01cccf0b77e9187362 diff --git a/hmm.json b/hmm.json index 26cb0d0b4..1e5bf5f18 100644 --- a/hmm.json +++ b/hmm.json @@ -45,6 +45,13 @@ "type": "haxelib", "version": "3.5.0" }, + { + "name": "funkVis", + "type": "git", + "dir": null, + "ref": "separateDSP", + "url": "https://github.com/FunkinCrew/funkVis" + }, { "name": "hamcrest", "type": "haxelib", @@ -164,4 +171,4 @@ "url": "https://github.com/FunkinCrew/thx.semver" } ] -} +} \ No newline at end of file diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 89b004df4..16a023474 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -35,9 +35,7 @@ class ABotVis extends FlxTypedSpriteGroup viz.frames = visFrms; add(viz); - var visStr = 'VIZ'; - if (lol == 5) visStr = 'viz'; // lol makes it lowercase, accomodates for art that I dont wanna rename! - + var visStr = 'viz'; viz.animation.addByPrefix('VIZ', visStr + lol, 0); viz.animation.play('VIZ', false, false, -1); } From fa8d1186544621d6ba6b63ce90391da1a239fe67 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 22 Feb 2024 02:49:08 -0500 Subject: [PATCH 05/43] vis positioning --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d9a0b3b0b..a681c9293 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d9a0b3b0bcc5b9cac89dde01cccf0b77e9187362 +Subproject commit a681c9293fae71fee41aca51266c53ff30564a6f From 40a056078c627be0e78b11bbae4fd6e4cb9a896d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 23 Feb 2024 02:03:34 -0500 Subject: [PATCH 06/43] vispos --- source/funkin/audio/visualize/ABotVis.hx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 16a023474..aa843f6e8 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -26,12 +26,17 @@ class ABotVis extends FlxTypedSpriteGroup var visFrms:FlxAtlasFrames = Paths.getSparrowAtlas('aBotViz'); + // these are the differences in X position, from left to right + var positionX:Array = [0, 59, 56, 66, 54, 52, 51]; + for (lol in 1...8) { // pushes initial value volumes.push(0.0); - var viz:FlxSprite = new FlxSprite(50 * lol, 0); + var posX:Float = positionX[lol - 1] + (positionX[lol - 2] ?? 0); + + var viz:FlxSprite = new FlxSprite(posX, 0); viz.frames = visFrms; add(viz); From b261729fa3b895bc07c6d409be0da73b83239781 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 23 Feb 2024 02:18:50 -0500 Subject: [PATCH 07/43] abot positioning --- assets | 2 +- source/funkin/audio/visualize/ABotVis.hx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/assets b/assets index a681c9293..181e41088 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit a681c9293fae71fee41aca51266c53ff30564a6f +Subproject commit 181e410888e7808ed373e14d539048a4ae17feea diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index aa843f6e8..1bd7d0457 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -28,15 +28,17 @@ class ABotVis extends FlxTypedSpriteGroup // these are the differences in X position, from left to right var positionX:Array = [0, 59, 56, 66, 54, 52, 51]; + var positionY:Array = [0, -8, -3.5, -0.4, 0.5, 4.7, 7]; for (lol in 1...8) { // pushes initial value volumes.push(0.0); + var sum = function(num:Float, total:Float) return total += num; + var posX:Float = positionX.slice(0, lol).fold(sum, 0); + var posY:Float = positionY.slice(0, lol).fold(sum, 0); - var posX:Float = positionX[lol - 1] + (positionX[lol - 2] ?? 0); - - var viz:FlxSprite = new FlxSprite(posX, 0); + var viz:FlxSprite = new FlxSprite(posX, posY); viz.frames = visFrms; add(viz); From 6f88865e0bd827b1858e3a7dbcd3ca7b2bdd3d9f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 23 Feb 2024 04:00:31 -0500 Subject: [PATCH 08/43] viz in progress --- Project.xml | 1 + assets | 2 +- source/funkin/audio/visualize/ABotVis.hx | 214 +++++++++++---------- source/funkin/audio/visualize/AudioClip.hx | 23 +++ source/funkin/play/PlayState.hx | 4 +- 5 files changed, 140 insertions(+), 104 deletions(-) create mode 100644 source/funkin/audio/visualize/AudioClip.hx diff --git a/Project.xml b/Project.xml index c58153575..434ae52c9 100644 --- a/Project.xml +++ b/Project.xml @@ -109,6 +109,7 @@ + diff --git a/assets b/assets index ed3eb91f4..d0dc456b4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ed3eb91f4b04fa0473128698e0e079a28998401e +Subproject commit d0dc456b49bd9d62c924b2f87f0205dba338705e diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 1bd7d0457..2501ca6e6 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -8,20 +8,26 @@ import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.math.FlxMath; import flixel.sound.FlxSound; import funkin.util.MathUtil; +import funkVis.dsp.SpectralAnalyzer; using Lambda; class ABotVis extends FlxTypedSpriteGroup { - public var vis:VisShit; + // public var vis:VisShit; + var analyzer:SpectralAnalyzer; var volumes:Array = []; + public var snd:FlxSound; + public function new(snd:FlxSound) { super(); - vis = new VisShit(snd); + this.snd = snd; + + // vis = new VisShit(snd); // vis.snd = snd; var visFrms:FlxAtlasFrames = Paths.getSparrowAtlas('aBotViz'); @@ -48,118 +54,124 @@ class ABotVis extends FlxTypedSpriteGroup } } + public function initAnalyzer() + { + @:privateAccess + analyzer = new SpectralAnalyzer(7, new AudioClip(cast snd._channel.__source), 0.005, 30); + } + override function update(elapsed:Float) { // updateViz(); - updateFFT(elapsed); + // updateFFT(elapsed); super.update(elapsed); } - function updateFFT(elapsed:Float) + static inline function min(x:Int, y:Int):Int { - if (vis.snd != null) - { - vis.checkAndSetBuffer(); - - if (vis.setBuffer) - { - var remappedShit:Int = 0; - - if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples)); - else - remappedShit = Std.int(FlxMath.remapToRange(Conductor.instance.songPosition, 0, vis.snd.length, 0, vis.numSamples)); - - var fftSamples:Array = []; - - var swagBucks = remappedShit; - - for (i in remappedShit...remappedShit + (Std.int((44100 * (1 / 144))))) - { - var left = vis.audioData[swagBucks] / 32767; - var right = vis.audioData[swagBucks + 1] / 32767; - - var balanced = (left + right) / 2; - - swagBucks += 2; - - fftSamples.push(balanced); - } - - var freqShit = vis.funnyFFT(fftSamples); - - for (i in 0...group.members.length) - { - var getSliceShit = function(s:Int) { - var powShit = FlxMath.remapToRange(s, 0, group.members.length, 0, MathUtil.logBase(10, freqShit[0].length)); - return Math.round(Math.pow(10, powShit)); - }; - - // var powShit:Float = getSliceShit(i); - var hzSliced:Int = getSliceShit(i); - - var sliceLength:Int = Std.int(freqShit[0].length / group.members.length); - - var volSlice = freqShit[0].slice(hzSliced, getSliceShit(i + 1)); - - var avgVel:Float = 0; - - for (slice in volSlice) - { - avgVel += slice; - } - - avgVel /= volSlice.length; - - avgVel *= 10000000; - - volumes[i] += avgVel - (elapsed * (volumes[i] * 50)); - - var animFrame:Int = Std.int(volumes[i]); - - animFrame = Math.floor(Math.min(5, animFrame)); - animFrame = Math.floor(Math.max(0, animFrame)); - - animFrame = Std.int(Math.abs(animFrame - 5)); // shitty dumbass flip, cuz dave got da shit backwards lol! - - group.members[i].animation.curAnim.curFrame = animFrame; - if (FlxG.keys.justPressed.U) - { - trace(avgVel); - trace(group.members[i].animation.curAnim.curFrame); - } - } - - // group.members[0].animation.curAnim.curFrame = - } - } + return x > y ? y : x; } - public function updateViz() + override function draw() { - if (vis.snd != null) + if (analyzer == null) { - var remappedShit:Int = 0; - vis.checkAndSetBuffer(); - - if (vis.setBuffer) - { - // var startingSample:Int = Std.int(FlxMath.remapToRange) - - if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples)); - - for (i in 0...group.members.length) - { - var sampleApprox:Int = Std.int(FlxMath.remapToRange(i, 0, group.members.length, remappedShit, remappedShit + 500)); - - var left = vis.audioData[sampleApprox] / 32767; - - var animFrame:Int = Std.int(FlxMath.remapToRange(left, -1, 1, 0, 6)); - - group.members[i].animation.curAnim.curFrame = animFrame; - } - } + super.draw(); + return; } + + var levels = analyzer.getLevels(false); + + for (i in 0...min(group.members.length, levels.length)) + { + var animFrame:Int = Math.round(levels[i].value * 5); + + animFrame = Math.floor(Math.min(5, animFrame)); + animFrame = Math.floor(Math.max(0, animFrame)); + + animFrame = Std.int(Math.abs(animFrame - 5)); // shitty dumbass flip, cuz dave got da shit backwards lol! + + group.members[i].animation.curAnim.curFrame = animFrame; + } + + super.draw(); } + + // function updateFFT(elapsed:Float) + // { + // if (vis.snd != null) + // { + // vis.checkAndSetBuffer(); + // if (vis.setBuffer) + // { + // var remappedShit:Int = 0; + // if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples)); + // else + // remappedShit = Std.int(FlxMath.remapToRange(Conductor.instance.songPosition, 0, vis.snd.length, 0, vis.numSamples)); + // var fftSamples:Array = []; + // var swagBucks = remappedShit; + // for (i in remappedShit...remappedShit + (Std.int((44100 * (1 / 144))))) + // { + // var left = vis.audioData[swagBucks] / 32767; + // var right = vis.audioData[swagBucks + 1] / 32767; + // var balanced = (left + right) / 2; + // swagBucks += 2; + // fftSamples.push(balanced); + // } + // var freqShit = vis.funnyFFT(fftSamples); + // for (i in 0...group.members.length) + // { + // var getSliceShit = function(s:Int) { + // var powShit = FlxMath.remapToRange(s, 0, group.members.length, 0, MathUtil.logBase(10, freqShit[0].length)); + // return Math.round(Math.pow(10, powShit)); + // }; + // // var powShit:Float = getSliceShit(i); + // var hzSliced:Int = getSliceShit(i); + // var sliceLength:Int = Std.int(freqShit[0].length / group.members.length); + // var volSlice = freqShit[0].slice(hzSliced, getSliceShit(i + 1)); + // var avgVel:Float = 0; + // for (slice in volSlice) + // { + // avgVel += slice; + // } + // avgVel /= volSlice.length; + // avgVel *= 10000000; + // volumes[i] += avgVel - (elapsed * (volumes[i] * 50)); + // var animFrame:Int = Std.int(volumes[i]); + // animFrame = Math.floor(Math.min(5, animFrame)); + // animFrame = Math.floor(Math.max(0, animFrame)); + // animFrame = Std.int(Math.abs(animFrame - 5)); // shitty dumbass flip, cuz dave got da shit backwards lol! + // group.members[i].animation.curAnim.curFrame = animFrame; + // if (FlxG.keys.justPressed.U) + // { + // trace(avgVel); + // trace(group.members[i].animation.curAnim.curFrame); + // } + // } + // // group.members[0].animation.curAnim.curFrame = + // } + // } + // } + // public function updateViz() + // { + // if (vis.snd != null) + // { + // var remappedShit:Int = 0; + // vis.checkAndSetBuffer(); + // if (vis.setBuffer) + // { + // // var startingSample:Int = Std.int(FlxMath.remapToRange) + // if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples)); + // for (i in 0...group.members.length) + // { + // var sampleApprox:Int = Std.int(FlxMath.remapToRange(i, 0, group.members.length, remappedShit, remappedShit + 500)); + // var left = vis.audioData[sampleApprox] / 32767; + // var animFrame:Int = Std.int(FlxMath.remapToRange(left, -1, 1, 0, 6)); + // group.members[i].animation.curAnim.curFrame = animFrame; + // } + // } + // } + // } } diff --git a/source/funkin/audio/visualize/AudioClip.hx b/source/funkin/audio/visualize/AudioClip.hx new file mode 100644 index 000000000..a8e353799 --- /dev/null +++ b/source/funkin/audio/visualize/AudioClip.hx @@ -0,0 +1,23 @@ +package funkin.audio.visualize; + +import flixel.FlxG; +import flixel.math.FlxMath; +import funkVis.AudioBuffer; +import lime.media.AudioSource; + +class AudioClip implements funkVis.AudioClip +{ + public var audioBuffer(default, null):AudioBuffer; + public var currentFrame(get, never):Int; + + public function new(audioSource:AudioSource) + { + var data:lime.utils.UInt16Array = cast audioSource.buffer.data; + this.audioBuffer = new AudioBuffer(data, audioSource.buffer.sampleRate); + } + + private function get_currentFrame():Int + { + return Std.int(FlxMath.remapToRange(FlxG.sound.music.time, 0, FlxG.sound.music.length, 0, audioBuffer.data.length / 2)); + } +} diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 1dbba5b54..0112a59e8 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1741,8 +1741,6 @@ class PlayState extends MusicBeatSubState */ function startSong():Void { - dispatchEvent(new ScriptEvent(SONG_START)); - startingSong = false; if (!overrideMusic && !isGamePaused && currentChart != null) @@ -1772,6 +1770,8 @@ class PlayState extends MusicBeatSubState // FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset; handleSkippedNotes(); } + + dispatchEvent(new ScriptEvent(SONG_START)); } /** From be348d0f13ad36c15d4cfc5fb881b02eceba261a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 1 Mar 2024 00:15:51 -0500 Subject: [PATCH 09/43] moved vis code --- source/funkin/audio/visualize/ABotVis.hx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 2501ca6e6..13c7eb501 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -50,7 +50,7 @@ class ABotVis extends FlxTypedSpriteGroup var visStr = 'viz'; viz.animation.addByPrefix('VIZ', visStr + lol, 0); - viz.animation.play('VIZ', false, false, -1); + viz.animation.play('VIZ', false, false, 2); } } @@ -82,6 +82,16 @@ class ABotVis extends FlxTypedSpriteGroup return; } + // drawFFT(); + + super.draw(); + } + + /** + * TJW funkVis based visualizer! updateFFT() is the old nasty shit that dont worky! + */ + function drawFFT():Void + { var levels = analyzer.getLevels(false); for (i in 0...min(group.members.length, levels.length)) @@ -95,8 +105,6 @@ class ABotVis extends FlxTypedSpriteGroup group.members[i].animation.curAnim.curFrame = animFrame; } - - super.draw(); } // function updateFFT(elapsed:Float) From d6608fe435e8239925b69286cc01082b28b30fad Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 7 Mar 2024 14:19:26 -0500 Subject: [PATCH 10/43] a-bot in progress --- hmm.json | 38 ++++++++++++------------ source/funkin/audio/visualize/ABotVis.hx | 16 +++++----- source/funkin/play/PlayState.hx | 2 +- source/funkin/util/logging/AnsiTrace.hx | 7 ++++- 4 files changed, 33 insertions(+), 30 deletions(-) diff --git a/hmm.json b/hmm.json index b25aae806..021d22070 100644 --- a/hmm.json +++ b/hmm.json @@ -4,21 +4,21 @@ "name": "discord_rpc", "type": "git", "dir": null, - "ref": "2d83fa863ef0c1eace5f1cf67c3ac315d1a3a8a5", + "ref": "2d83fa8", "url": "https://github.com/Aidan63/linc_discord-rpc" }, { "name": "flixel", "type": "git", "dir": null, - "ref": "4d054bd10b05bb1309a0ba3427ffa5378e0b4b99", + "ref": "4d054bd1", "url": "https://github.com/FunkinCrew/flixel" }, { "name": "flixel-addons", "type": "git", "dir": null, - "ref": "a523c3b56622f0640933944171efed46929e360e", + "ref": "a523c3b", "url": "https://github.com/FunkinCrew/flixel-addons" }, { @@ -30,14 +30,14 @@ "name": "flixel-ui", "type": "git", "dir": null, - "ref": "719b4f10d94186ed55f6fef1b6618d32abec8c15", + "ref": "719b4f1", "url": "https://github.com/HaxeFlixel/flixel-ui" }, { "name": "flxanimate", "type": "git", "dir": null, - "ref": "9bacdd6ea39f5e3a33b0f5dfb7bc583fe76060d4", + "ref": "9bacdd6", "url": "https://github.com/FunkinCrew/flxanimate" }, { @@ -49,7 +49,7 @@ "name": "funkVis", "type": "git", "dir": null, - "ref": "separateDSP", + "ref": "7ed1f8fa6d8ca580f2359254482578a128be7ab8", "url": "https://github.com/FunkinCrew/funkVis" }, { @@ -61,14 +61,14 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "0212d8fdfcafeb5f0d5a41e1ddba8ff21d0e183b", + "ref": "0212d8fd", "url": "https://github.com/haxeui/haxeui-core" }, { "name": "haxeui-flixel", "type": "git", "dir": null, - "ref": "63a906a6148958dbfde8c7b48d90b0693767fd95", + "ref": "63a906a", "url": "https://github.com/haxeui/haxeui-flixel" }, { @@ -80,7 +80,7 @@ "name": "hxCodec", "type": "git", "dir": null, - "ref": "387e1665d6feb5762358134f168e6ebfe46acec8", + "ref": "387e166", "url": "https://github.com/FunkinCrew/hxCodec" }, { @@ -92,7 +92,7 @@ "name": "hxcpp-debug-server", "type": "git", "dir": "hxcpp-debug-server", - "ref": "147294123f983e35f50a966741474438069a7a8f", + "ref": "1472941", "url": "https://github.com/FunkinCrew/hxcpp-debugger" }, { @@ -104,56 +104,56 @@ "name": "json2object", "type": "git", "dir": null, - "ref": "a8c26f18463c98da32f744c214fe02273e1823fa", + "ref": "a8c26f1", "url": "https://github.com/FunkinCrew/json2object" }, { "name": "lime", "type": "git", "dir": null, - "ref": "1359fe6ad52e91175dc636a516d460bd54ea22ed", + "ref": "1359fe6a", "url": "https://github.com/FunkinCrew/lime" }, { "name": "mconsole", "type": "git", "dir": null, - "ref": "master", + "ref": "06c0499", "url": "https://github.com/massive-oss/mconsole" }, { "name": "mcover", "type": "git", "dir": "src", - "ref": "master", + "ref": "c3c47cd", "url": "https://github.com/massive-oss/mcover" }, { "name": "mockatoo", "type": "git", "dir": "src", - "ref": "master", + "ref": "13d77a0", "url": "https://github.com/FunkinCrew/mockatoo" }, { "name": "munit", "type": "git", "dir": "src", - "ref": "master", + "ref": "f61be7f", "url": "https://github.com/FunkinCrew/MassiveUnit" }, { "name": "openfl", "type": "git", "dir": null, - "ref": "f229d76361c7e31025a048fe7909847f75bb5d5e", + "ref": "f229d763", "url": "https://github.com/FunkinCrew/openfl" }, { "name": "polymod", "type": "git", "dir": null, - "ref": "d5a3b8995f64d20b95f844454e8c3b38c3d3a9fa", + "ref": "d5a3b89", "url": "https://github.com/larsiusprime/polymod" }, { @@ -171,4 +171,4 @@ "url": "https://github.com/FunkinCrew/thx.semver" } ] -} \ No newline at end of file +} diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 13c7eb501..05131b795 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -57,15 +57,21 @@ class ABotVis extends FlxTypedSpriteGroup public function initAnalyzer() { @:privateAccess - analyzer = new SpectralAnalyzer(7, new AudioClip(cast snd._channel.__source), 0.005, 30); + analyzer = new SpectralAnalyzer(7, new AudioClip(cast snd._channel.__source), 0.06, 30); + analyzer.fftN = 2048; } + var visTimer:Float = -1; + var visTimeMax:Float = 1 / 30; + override function update(elapsed:Float) { // updateViz(); // updateFFT(elapsed); + if (analyzer != null) drawFFT(); + super.update(elapsed); } @@ -76,14 +82,6 @@ class ABotVis extends FlxTypedSpriteGroup override function draw() { - if (analyzer == null) - { - super.draw(); - return; - } - - // drawFFT(); - super.draw(); } diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 341f1d1b6..3c42834a5 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1784,7 +1784,7 @@ class PlayState extends MusicBeatSubState // I am going insane. FlxG.sound.music.volume = 1.0; - FlxG.sound.music.fadeTween.cancel(); + FlxG.sound.music.fadeTween?.cancel(); trace('Playing vocals...'); add(vocals); diff --git a/source/funkin/util/logging/AnsiTrace.hx b/source/funkin/util/logging/AnsiTrace.hx index c8d27b86f..9fdc19e1b 100644 --- a/source/funkin/util/logging/AnsiTrace.hx +++ b/source/funkin/util/logging/AnsiTrace.hx @@ -52,7 +52,12 @@ class AnsiTrace public static function traceBF() { #if sys - if (colorSupported) Sys.println(ansiBF.join("\n")); + if (colorSupported) + { + for (line in ansiBF) + Sys.stdout().writeString(line + "\n"); + Sys.stdout().flush(); + } #end } From 31ba13630269268b6cf5b6f8c6d5b21194ecf6b9 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 8 Mar 2024 20:52:30 -0500 Subject: [PATCH 11/43] Update assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index f550436bf..c8c395450 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f550436bfed37f2e6efb1b97edd66a5c840bd262 +Subproject commit c8c395450b0cd899224bd4fbfd940ed2b376de44 From 4eea9b76e7393601b857168631bdb1eb5960a0ae Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 19 Mar 2024 13:04:58 -0700 Subject: [PATCH 12/43] idk assets revert this if I busted shit here lol --- hmm.json | 2 +- source/funkin/audio/visualize/ABotVis.hx | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/hmm.json b/hmm.json index 3e5c07c29..04c09e50f 100644 --- a/hmm.json +++ b/hmm.json @@ -49,7 +49,7 @@ "name": "funkVis", "type": "git", "dir": null, - "ref": "7ed1f8fa6d8ca580f2359254482578a128be7ab8", + "ref": "0ac2fffa67fd30563df97c66718551efa92d283e", "url": "https://github.com/FunkinCrew/funkVis" }, { diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 05131b795..a8b6fb937 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -57,8 +57,9 @@ class ABotVis extends FlxTypedSpriteGroup public function initAnalyzer() { @:privateAccess - analyzer = new SpectralAnalyzer(7, new AudioClip(cast snd._channel.__source), 0.06, 30); - analyzer.fftN = 2048; + analyzer = new SpectralAnalyzer(7, new AudioClip(cast snd._channel.__source), 0.01, 30); + analyzer.maxDb = -35; + // analyzer.fftN = 2048; } var visTimer:Float = -1; @@ -70,8 +71,7 @@ class ABotVis extends FlxTypedSpriteGroup // updateFFT(elapsed); - if (analyzer != null) drawFFT(); - + // super.update(elapsed); } @@ -82,6 +82,8 @@ class ABotVis extends FlxTypedSpriteGroup override function draw() { + if (analyzer != null) drawFFT(); + super.draw(); } From b75c7c23614785fd31af2bdd2c6b059fd6c4f1b9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 28 Mar 2024 23:08:50 -0400 Subject: [PATCH 13/43] funkVis html5 --- hmm.json | 2 +- source/funkin/audio/visualize/ABotVis.hx | 3 ++- source/funkin/audio/visualize/AudioClip.hx | 23 ---------------------- 3 files changed, 3 insertions(+), 25 deletions(-) delete mode 100644 source/funkin/audio/visualize/AudioClip.hx diff --git a/hmm.json b/hmm.json index 81624a08a..430f33f0d 100644 --- a/hmm.json +++ b/hmm.json @@ -49,7 +49,7 @@ "name": "funkVis", "type": "git", "dir": null, - "ref": "0ac2fffa67fd30563df97c66718551efa92d283e", + "ref": "backend-rework", "url": "https://github.com/FunkinCrew/funkVis" }, { diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index a8b6fb937..1188d389f 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -9,6 +9,7 @@ import flixel.math.FlxMath; import flixel.sound.FlxSound; import funkin.util.MathUtil; import funkVis.dsp.SpectralAnalyzer; +import funkVis.audioclip.frontends.LimeAudioClip; using Lambda; @@ -57,7 +58,7 @@ class ABotVis extends FlxTypedSpriteGroup public function initAnalyzer() { @:privateAccess - analyzer = new SpectralAnalyzer(7, new AudioClip(cast snd._channel.__source), 0.01, 30); + analyzer = new SpectralAnalyzer(7, new LimeAudioClip(cast snd._channel.__source), 0.01, 30); analyzer.maxDb = -35; // analyzer.fftN = 2048; } diff --git a/source/funkin/audio/visualize/AudioClip.hx b/source/funkin/audio/visualize/AudioClip.hx deleted file mode 100644 index a8e353799..000000000 --- a/source/funkin/audio/visualize/AudioClip.hx +++ /dev/null @@ -1,23 +0,0 @@ -package funkin.audio.visualize; - -import flixel.FlxG; -import flixel.math.FlxMath; -import funkVis.AudioBuffer; -import lime.media.AudioSource; - -class AudioClip implements funkVis.AudioClip -{ - public var audioBuffer(default, null):AudioBuffer; - public var currentFrame(get, never):Int; - - public function new(audioSource:AudioSource) - { - var data:lime.utils.UInt16Array = cast audioSource.buffer.data; - this.audioBuffer = new AudioBuffer(data, audioSource.buffer.sampleRate); - } - - private function get_currentFrame():Int - { - return Std.int(FlxMath.remapToRange(FlxG.sound.music.time, 0, FlxG.sound.music.length, 0, audioBuffer.data.length / 2)); - } -} From c97227b1300a40d2f6153940d86a04882ca8bdca Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 29 Mar 2024 00:39:32 -0400 Subject: [PATCH 14/43] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 69ac1b5f1..8a48607c8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 69ac1b5f10ee8722ac0586a0e0282f04dccc07eb +Subproject commit 8a48607c800e096bbe6e67395adbbd48639a72ed From 5beb20ec7cb876e6b571c9da7bf53c19ae14647d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 6 Apr 2024 21:42:18 -0400 Subject: [PATCH 15/43] Fix bug where restarting the song would sometimes crash. --- source/funkin/play/PlayState.hx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 795f493e8..dbae9ed2a 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -834,9 +834,12 @@ class PlayState extends MusicBeatSubState inputSpitter = []; // Reset music properly. - FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset; - FlxG.sound.music.pitch = playbackRate; - FlxG.sound.music.pause(); + if (FlxG.sound.music != null) + { + FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset; + FlxG.sound.music.pitch = playbackRate; + FlxG.sound.music.pause(); + } if (!overrideMusic) { @@ -852,7 +855,7 @@ class PlayState extends MusicBeatSubState vocals.pause(); vocals.time = 0; - FlxG.sound.music.volume = 1; + if (FlxG.sound.music != null) FlxG.sound.music.volume = 1; vocals.volume = 1; vocals.playerVolume = 1; vocals.opponentVolume = 1; From ea1d123c49531d2f94063b0d4ed39a94b4654849 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 6 Apr 2024 21:42:31 -0400 Subject: [PATCH 16/43] Fixes to Pico Blazin' animations. --- assets | 2 +- source/funkin/play/character/AnimateAtlasCharacter.hx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/assets b/assets index e8f4d2d91..287f8e222 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit e8f4d2d91c7bd5a922465e7d67a0efb7d7574bd6 +Subproject commit 287f8e222d00cfd0d24eb79465b7a256bb80318f diff --git a/source/funkin/play/character/AnimateAtlasCharacter.hx b/source/funkin/play/character/AnimateAtlasCharacter.hx index f1dadf3e2..ed58b92b5 100644 --- a/source/funkin/play/character/AnimateAtlasCharacter.hx +++ b/source/funkin/play/character/AnimateAtlasCharacter.hx @@ -192,6 +192,7 @@ class AnimateAtlasCharacter extends BaseCharacter if (!this.mainSprite.hasAnimation(prefix)) { FlxG.log.warn('[ATLASCHAR] Animation ${prefix} not found in Animate Atlas ${_data.assetPath}'); + trace('[ATLASCHAR] Animation ${prefix} not found in Animate Atlas ${_data.assetPath}'); continue; } animations.set(anim.name, anim); From b464f51ba2572ce57d01caedde7cb0fa03789c77 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 6 Apr 2024 22:38:32 -0400 Subject: [PATCH 17/43] Fix an issue where a missing stage would cause a crash (rather than an error popup) --- source/funkin/play/PlayState.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index dbae9ed2a..a5fbb7624 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1551,10 +1551,11 @@ class PlayState extends MusicBeatSubState function loadStage(id:String):Void { currentStage = StageRegistry.instance.fetchEntry(id); - currentStage.revive(); // Stages are killed and props destroyed when the PlayState is destroyed to save memory. if (currentStage != null) { + currentStage.revive(); // Stages are killed and props destroyed when the PlayState is destroyed to save memory. + // Actually create and position the sprites. var event:ScriptEvent = new ScriptEvent(CREATE, false); ScriptEventDispatcher.callEvent(currentStage, event); From 207eedf7b5dc4f9c92fc3c216576fff3858ea262 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 6 Apr 2024 22:38:39 -0400 Subject: [PATCH 18/43] Update assets submodule. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 287f8e222..6e098afdc 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 287f8e222d00cfd0d24eb79465b7a256bb80318f +Subproject commit 6e098afdcc30c8508afc09bc3e57b502821029ab From 6f5c3a043f87152c813ea0915629c7224cd67e01 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 10 Apr 2024 14:45:07 -0400 Subject: [PATCH 19/43] Fix crash caused when game tries to render disposed sprites during a Sticker transition. --- source/funkin/graphics/FunkinCamera.hx | 6 +++++- source/funkin/play/PlayState.hx | 2 +- .../funkin/ui/debug/charting/ChartEditorState.hx | 4 ++-- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/mainmenu/MainMenuState.hx | 2 +- source/funkin/ui/options/ControlsMenu.hx | 2 +- source/funkin/ui/options/PreferencesMenu.hx | 2 +- source/funkin/ui/transition/StickerSubState.hx | 14 +++++++++----- 8 files changed, 21 insertions(+), 13 deletions(-) diff --git a/source/funkin/graphics/FunkinCamera.hx b/source/funkin/graphics/FunkinCamera.hx index 90861c263..8c8a1c9a7 100644 --- a/source/funkin/graphics/FunkinCamera.hx +++ b/source/funkin/graphics/FunkinCamera.hx @@ -47,9 +47,13 @@ class FunkinCamera extends FlxCamera public var shouldDraw:Bool = true; - public function new(x:Int = 0, y:Int = 0, width:Int = 0, height:Int = 0, zoom:Float = 0) + // Used to identify the camera during debugging. + final id:String = 'unknown'; + + public function new(id:String = 'unknown', x:Int = 0, y:Int = 0, width:Int = 0, height:Int = 0, zoom:Float = 0) { super(x, y, width, height, zoom); + this.id = id; bgTexture = pickTexture(width, height); bgBitmap = FixedBitmapData.fromTexture(bgTexture); bgFrame = new FlxFrame(new FlxGraphic('', null)); diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 795f493e8..486eb742c 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1467,7 +1467,7 @@ class PlayState extends MusicBeatSubState */ function initCameras():Void { - camGame = new FunkinCamera(); + camGame = new FunkinCamera('playStateCamGame'); camGame.bgColor = BACKGROUND_COLOR; // Show a pink background behind the stage. camHUD = new FlxCamera(); camHUD.bgColor.alpha = 0; // Show the game scene behind the camera. diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index dba1a7e55..78222570a 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2091,7 +2091,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState loadPreferences(); - uiCamera = new FunkinCamera(); + uiCamera = new FunkinCamera('chartEditorUI'); FlxG.cameras.reset(uiCamera); buildDefaultSongData(); @@ -5382,7 +5382,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Kill and replace the UI camera so it doesn't get destroyed during the state transition. uiCamera.kill(); FlxG.cameras.remove(uiCamera, false); - FlxG.cameras.reset(new FunkinCamera()); + FlxG.cameras.reset(new FunkinCamera('chartEditorUI2')); this.persistentUpdate = false; this.persistentDraw = false; diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index dc1f164ea..6fdc7e309 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -513,7 +513,7 @@ class FreeplayState extends MusicBeatSubState // var swag:Alphabet = new Alphabet(1, 0, 'swag'); - var funnyCam:FunkinCamera = new FunkinCamera(0, 0, FlxG.width, FlxG.height); + var funnyCam:FunkinCamera = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); funnyCam.bgColor = FlxColor.TRANSPARENT; FlxG.cameras.add(funnyCam); diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index ecd67b4da..0e444782c 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -172,7 +172,7 @@ class MainMenuState extends MusicBeatState function resetCamStuff() { - FlxG.cameras.reset(new FunkinCamera()); + FlxG.cameras.reset(new FunkinCamera('mainMenu')); FlxG.camera.follow(camFollow, null, 0.06); FlxG.camera.snapToTarget(); } diff --git a/source/funkin/ui/options/ControlsMenu.hx b/source/funkin/ui/options/ControlsMenu.hx index 62ae4b1a9..dd7d5ff38 100644 --- a/source/funkin/ui/options/ControlsMenu.hx +++ b/source/funkin/ui/options/ControlsMenu.hx @@ -48,7 +48,7 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page { super(); - menuCamera = new FunkinCamera(); + menuCamera = new FunkinCamera('controlsMenu'); FlxG.cameras.add(menuCamera, false); menuCamera.bgColor = 0x0; camera = menuCamera; diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index c23c3f165..783aef0ba 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -21,7 +21,7 @@ class PreferencesMenu extends Page { super(); - menuCamera = new FunkinCamera(); + menuCamera = new FunkinCamera('prefMenu'); FlxG.cameras.add(menuCamera, false); menuCamera.bgColor = 0x0; camera = menuCamera; diff --git a/source/funkin/ui/transition/StickerSubState.hx b/source/funkin/ui/transition/StickerSubState.hx index 0b5e16f97..e5abef872 100644 --- a/source/funkin/ui/transition/StickerSubState.hx +++ b/source/funkin/ui/transition/StickerSubState.hx @@ -247,10 +247,6 @@ class StickerSubState extends MusicBeatSubState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - // TODO: Rework this asset caching stuff - FunkinSprite.preparePurgeCache(); - FunkinSprite.purgeCache(); - // I think this grabs the screen and puts it under the stickers? // Leaving this commented out rather than stripping it out because it's cool... /* @@ -265,7 +261,15 @@ class StickerSubState extends MusicBeatSubState // FlxG.addChildBelowMouse(dipshit); */ - FlxG.switchState(() -> targetState(this)); + FlxG.switchState(() -> { + // TODO: Rework this asset caching stuff + // NOTE: This has to come AFTER the state switch, + // otherwise the game tries to render destroyed sprites! + FunkinSprite.preparePurgeCache(); + FunkinSprite.purgeCache(); + + return targetState(this); + }); } }); }); From bc0af9ae9ffd0c0b1eb9ee1aa24e358ed7fd15b6 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 14 Apr 2024 03:01:07 -0400 Subject: [PATCH 20/43] temp enabling fps --- source/Main.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/Main.hx b/source/Main.hx index f4c5d9eb2..7037bf390 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -113,6 +113,8 @@ class Main extends Sprite addChild(game); + addChild(fpsCounter); + #if hxcpp_debug_server trace('hxcpp_debug_server is enabled! You can now connect to the game with a debugger.'); #else From 2210f8bc183888d755bcd23934a0152e6bd60370 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 16 Apr 2024 18:42:43 -0400 Subject: [PATCH 21/43] Made Blazin' death a separate asset to fix blend modes. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 1b12b6c66..235d2695c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 1b12b6c6666af6c84addf5aa0795546aa0d04185 +Subproject commit 235d2695c6de11b0daa49277a602d1045d45e510 From bc0a27c985eb7319cef8d5e9350b6198b1177279 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 16 Apr 2024 18:43:11 -0400 Subject: [PATCH 22/43] Fix references to missing graphics in Freeplay --- .vscode/settings.json | 5 +++++ source/funkin/ui/freeplay/SongMenuItem.hx | 24 +++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index c28bebeab..a8a67245b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -170,6 +170,11 @@ "target": "windows", "args": ["-debug", "-DANIMDEBUG", "-DFORCE_DEBUG_VERSION"] }, + { + "label": "Windows / Debug (Debug hxCodec)", + "target": "windows", + "args": ["-debug", "-DHXC_LIBVLC_LOGGING", "-DFORCE_DEBUG_VERSION"] + }, { "label": "HashLink / Debug (Straight to Animation Editor)", "target": "hl", diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index f8b3d7ac3..f6d85e56e 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -46,7 +46,7 @@ class SongMenuItem extends FlxSpriteGroup public var hsvShader(default, set):HSVShader; - var diffRatingSprite:FlxSprite; + // var diffRatingSprite:FlxSprite; public function new(x:Float, y:Float) { @@ -65,13 +65,13 @@ class SongMenuItem extends FlxSpriteGroup var rank:String = FlxG.random.getObject(ranks); ranking = new FlxSprite(capsule.width * 0.84, 30); - ranking.loadGraphic(Paths.image('freeplay/ranks/' + rank)); - ranking.scale.x = ranking.scale.y = realScaled; + // ranking.loadGraphic(Paths.image('freeplay/ranks/' + rank)); + // ranking.scale.x = ranking.scale.y = realScaled; // ranking.alpha = 0.75; - ranking.visible = false; - ranking.origin.set(capsule.origin.x - ranking.x, capsule.origin.y - ranking.y); - add(ranking); - grpHide.add(ranking); + // ranking.visible = false; + // ranking.origin.set(capsule.origin.x - ranking.x, capsule.origin.y - ranking.y); + // add(ranking); + // grpHide.add(ranking); switch (rank) { @@ -81,9 +81,9 @@ class SongMenuItem extends FlxSpriteGroup grayscaleShader = new Grayscale(1); - diffRatingSprite = new FlxSprite(145, 90).loadGraphic(Paths.image('freeplay/diffRatings/diff00')); - diffRatingSprite.shader = grayscaleShader; - diffRatingSprite.origin.set(capsule.origin.x - diffRatingSprite.x, capsule.origin.y - diffRatingSprite.y); + // diffRatingSprite = new FlxSprite(145, 90).loadGraphic(Paths.image('freeplay/diffRatings/diff00')); + // diffRatingSprite.shader = grayscaleShader; + // diffRatingSprite.origin.set(capsule.origin.x - diffRatingSprite.x, capsule.origin.y - diffRatingSprite.y); // TODO: Readd once ratings are fully implemented // add(diffRatingSprite); // grpHide.add(diffRatingSprite); @@ -118,8 +118,8 @@ class SongMenuItem extends FlxSpriteGroup function updateDifficultyRating(newRating:Int):Void { var ratingPadded:String = newRating < 10 ? '0$newRating' : '$newRating'; - diffRatingSprite.loadGraphic(Paths.image('freeplay/diffRatings/diff${ratingPadded}')); - diffRatingSprite.visible = false; + // diffRatingSprite.loadGraphic(Paths.image('freeplay/diffRatings/diff${ratingPadded}')); + // diffRatingSprite.visible = false; } function set_hsvShader(value:HSVShader):HSVShader From d346c9387cdb1001977a9dcf6b7d691069cafbcf Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 16 Apr 2024 19:42:52 -0400 Subject: [PATCH 23/43] Fix a crash in the Results state. also nudge GF over to the spot she's in in the FLA --- source/funkin/play/ResultState.hx | 66 +++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index c05257338..591020955 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -80,34 +80,34 @@ class ResultState extends MusicBeatSubState bgFlash.visible = false; add(bgFlash); - var bfGfExcellent:FlxAtlasSprite = new FlxAtlasSprite(380, -170, Paths.animateAtlas("resultScreen/resultsBoyfriendExcellent", "shared")); - bfGfExcellent.visible = false; - add(bfGfExcellent); + // var bfGfExcellent:FlxAtlasSprite = new FlxAtlasSprite(380, -170, Paths.animateAtlas("resultScreen/resultsBoyfriendExcellent", "shared")); + // bfGfExcellent.visible = false; + // add(bfGfExcellent); + // + // var bfPerfect:FlxAtlasSprite = new FlxAtlasSprite(370, -180, Paths.animateAtlas("resultScreen/resultsBoyfriendPerfect", "shared")); + // bfPerfect.visible = false; + // add(bfPerfect); + // + // var bfSHIT:FlxAtlasSprite = new FlxAtlasSprite(0, 20, Paths.animateAtlas("resultScreen/resultsBoyfriendSHIT", "shared")); + // bfSHIT.visible = false; + // add(bfSHIT); + // + // bfGfExcellent.anim.onComplete = () -> { + // bfGfExcellent.anim.curFrame = 28; + // bfGfExcellent.anim.play(); // unpauses this anim, since it's on PlayOnce! + // }; + // + // bfPerfect.anim.onComplete = () -> { + // bfPerfect.anim.curFrame = 136; + // bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! + // }; + // + // bfSHIT.anim.onComplete = () -> { + // bfSHIT.anim.curFrame = 150; + // bfSHIT.anim.play(); // unpauses this anim, since it's on PlayOnce! + // }; - var bfPerfect:FlxAtlasSprite = new FlxAtlasSprite(370, -180, Paths.animateAtlas("resultScreen/resultsBoyfriendPerfect", "shared")); - bfPerfect.visible = false; - add(bfPerfect); - - var bfSHIT:FlxAtlasSprite = new FlxAtlasSprite(0, 20, Paths.animateAtlas("resultScreen/resultsBoyfriendSHIT", "shared")); - bfSHIT.visible = false; - add(bfSHIT); - - bfGfExcellent.anim.onComplete = () -> { - bfGfExcellent.anim.curFrame = 28; - bfGfExcellent.anim.play(); // unpauses this anim, since it's on PlayOnce! - }; - - bfPerfect.anim.onComplete = () -> { - bfPerfect.anim.curFrame = 136; - bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! - }; - - bfSHIT.anim.onComplete = () -> { - bfSHIT.anim.curFrame = 150; - bfSHIT.anim.play(); // unpauses this anim, since it's on PlayOnce! - }; - - var gf:FlxSprite = FunkinSprite.createSparrow(500, 300, 'resultScreen/resultGirlfriendGOOD'); + var gf:FlxSprite = FunkinSprite.createSparrow(625, 325, 'resultScreen/resultGirlfriendGOOD'); gf.animation.addByPrefix("clap", "Girlfriend Good Anim", 24, false); gf.visible = false; gf.animation.finishCallback = _ -> { @@ -268,9 +268,9 @@ class ResultState extends MusicBeatSubState switch (resultsVariation) { - case SHIT: - bfSHIT.visible = true; - bfSHIT.playAnimation(""); + // case SHIT: + // bfSHIT.visible = true; + // bfSHIT.playAnimation(""); case NORMAL: boyfriend.animation.play('fall'); @@ -292,9 +292,9 @@ class ResultState extends MusicBeatSubState gf.animation.play('clap', true); gf.visible = true; }); - case PERFECT: - bfPerfect.visible = true; - bfPerfect.playAnimation(""); + // case PERFECT: + // bfPerfect.visible = true; + // bfPerfect.playAnimation(""); // bfGfExcellent.visible = true; // bfGfExcellent.playAnimation(""); From 80a558ac08119b3cf427f6714bb1bc3596ad8c6e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 16 Apr 2024 19:57:19 -0400 Subject: [PATCH 24/43] Fix an issue where changing focus would pause some sounds but not others. --- source/funkin/audio/FunkinSound.hx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 8c1bf3b41..df05cc3ef 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -223,11 +223,12 @@ class FunkinSound extends FlxSound implements ICloneable // already paused before we lost focus. if (_lostFocus && !_alreadyPaused) { + trace('Resuming audio (${this._label}) on focus!'); resume(); } else { - trace('Not resuming audio on focus!'); + trace('Not resuming audio (${this._label}) on focus!'); } _lostFocus = false; } @@ -402,6 +403,12 @@ class FunkinSound extends FlxSound implements ICloneable sound.group = FlxG.sound.defaultSoundGroup; sound.persist = true; + // Make sure to add the sound to the list. + // If it's already in, it won't get re-added. + // If it's not in the list (it gets removed by FunkinSound.playMusic()), + // it will get re-added (then if this was called by playMusic(), removed again) + FlxG.sound.list.add(sound); + // Call onLoad() because the sound already loaded if (onLoad != null && sound._sound != null) onLoad(); From b9824848560d426247d4bf33403786e7898ab0fe Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 16 Apr 2024 20:19:20 -0400 Subject: [PATCH 25/43] Properly fix the menu background to use the correct line colors. --- assets | 2 +- source/funkin/ui/mainmenu/MainMenuState.hx | 10 ++-------- source/funkin/ui/options/OptionsState.hx | 3 +-- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/assets b/assets index 1b12b6c66..f3d6cf30d 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 1b12b6c6666af6c84addf5aa0795546aa0d04185 +Subproject commit f3d6cf30dee60a237a6773d8140bd1661f62bd4e diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 1a4686c5b..d2d8adeca 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -57,12 +57,7 @@ class MainMenuState extends MusicBeatState persistentUpdate = false; persistentDraw = true; - var bg = FunkinSprite.create('menuDesat'); - - bg.color = 0xFFFDE871; - // This line accounts for the fact that the base color of menuDesat is #EFEFEF. - flixel.util.FlxColorTransformUtil.setOffsets(bg.colorTransform, 30, 27, 13, 0.0); - + var bg:FlxSprite = new FlxSprite(Paths.image('menuBG')); bg.scrollFactor.x = 0; bg.scrollFactor.y = 0.17; bg.setGraphicSize(Std.int(bg.width * 1.2)); @@ -73,7 +68,7 @@ class MainMenuState extends MusicBeatState camFollow = new FlxObject(0, 0, 1, 1); add(camFollow); - magenta = new FlxSprite(Paths.image('menuDesat')); + magenta = new FlxSprite(Paths.image('menuBGMagenta')); magenta.scrollFactor.x = bg.scrollFactor.x; magenta.scrollFactor.y = bg.scrollFactor.y; magenta.setGraphicSize(Std.int(bg.width)); @@ -81,7 +76,6 @@ class MainMenuState extends MusicBeatState magenta.x = bg.x; magenta.y = bg.y; magenta.visible = false; - magenta.color = 0xFFfd719b; // TODO: Why doesn't this line compile I'm going fucking feral diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index 0f33a0780..a00b28dbb 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -23,8 +23,7 @@ class OptionsState extends MusicBeatState override function create() { - var menuBG = new FlxSprite().loadGraphic(Paths.image('menuDesat')); - menuBG.color = 0xFFea71fd; + var menuBG = new FlxSprite().loadGraphic(Paths.image('menuBGBlue')); menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); menuBG.updateHitbox(); menuBG.screenCenter(); From 9a284c34e9fafa6ebb920e038551d25e34cede9b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Apr 2024 13:45:36 -0400 Subject: [PATCH 26/43] assets update for submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6e098afdc..39c221849 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6e098afdcc30c8508afc09bc3e57b502821029ab +Subproject commit 39c22184988e1b22bd63b07d83c30ece588e85df From 366bebc94cca62f36dadee505bf390cf0eb26446 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Apr 2024 13:58:35 -0400 Subject: [PATCH 27/43] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 837a8639b..1266cb1c0 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 837a8639bd7abe4aa8786dc3790e8d4576f04f28 +Subproject commit 1266cb1c0c5078158df52b2b36205b332ccde019 From f385379935b64706b10c6847f9628d8f4b032947 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Apr 2024 14:01:19 -0400 Subject: [PATCH 28/43] assets update for submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 837a8639b..069c9bf45 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 837a8639bd7abe4aa8786dc3790e8d4576f04f28 +Subproject commit 069c9bf45f197ebe0b38483d11bb30c15bbb5eca From 30d052f6ee4431ab295bc0aed758ffe202f56b3b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Apr 2024 14:05:38 -0400 Subject: [PATCH 29/43] assets update for submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 235d2695c..a24f42932 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 235d2695c6de11b0daa49277a602d1045d45e510 +Subproject commit a24f42932fbe9032d28be1603f197fb50c938276 From 3fa60cd2283037f338d2fd90107c69388466d856 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sun, 7 Apr 2024 21:41:40 +0100 Subject: [PATCH 30/43] update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index a24f42932..31dfbf9d5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit a24f42932fbe9032d28be1603f197fb50c938276 +Subproject commit 31dfbf9d545ea897e58d0257381cbdf8e4281d3c From 351cb8cbaa6ea0c5570563a40c24c24219af4fed Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Tue, 9 Apr 2024 03:56:28 +0100 Subject: [PATCH 31/43] popupstuff changes + make combopopup able to be edited outside of playstate --- source/funkin/play/PlayState.hx | 2 +- source/funkin/play/components/PopUpStuff.hx | 25 ++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 2e023dccd..9f6e5a16b 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -498,7 +498,7 @@ class PlayState extends MusicBeatSubState /** * The combo popups. Includes the real-time combo counter and the rating. */ - var comboPopUps:PopUpStuff; + public var comboPopUps:PopUpStuff; /** * PROPERTIES diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 724bf0cb9..b062b22cf 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -10,6 +10,8 @@ import funkin.util.TimerUtil; class PopUpStuff extends FlxTypedGroup { + public var offsets:Array = [0, 0]; + override public function new() { super(); @@ -29,9 +31,9 @@ class PopUpStuff extends FlxTypedGroup rating.scrollFactor.set(0.2, 0.2); rating.zIndex = 1000; - rating.x = FlxG.width * 0.50; + rating.x = (FlxG.width * 0.474) + offsets[0]; // rating.x -= FlxG.camera.scroll.x * 0.2; - rating.y = FlxG.camera.height * 0.4 - 60; + rating.y = (FlxG.camera.height * 0.45 - 60) + offsets[1]; rating.acceleration.y = 550; rating.velocity.y -= FlxG.random.int(140, 175); rating.velocity.x -= FlxG.random.int(0, 10); @@ -40,16 +42,19 @@ class PopUpStuff extends FlxTypedGroup if (PlayState.instance.currentStageId.startsWith('school')) { - rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); + rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.65)); rating.antialiasing = false; } else { - rating.setGraphicSize(Std.int(rating.width * 0.7)); + rating.setGraphicSize(Std.int(rating.width * 0.65)); rating.antialiasing = true; } rating.updateHitbox(); + rating.x -= rating.width / 2; + rating.y -= rating.height / 2; + FlxTween.tween(rating, {alpha: 0}, 0.2, { onComplete: function(tween:FlxTween) { @@ -77,8 +82,8 @@ class PopUpStuff extends FlxTypedGroup pixelShitPart2 = '-pixel'; } var comboSpr:FunkinSprite = FunkinSprite.create(pixelShitPart1 + 'combo' + pixelShitPart2); - comboSpr.y = FlxG.camera.height * 0.4 + 80; - comboSpr.x = FlxG.width * 0.50; + comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1]; + comboSpr.x = (FlxG.width * 0.507) + offsets[0]; // comboSpr.x -= FlxG.camera.scroll.x * 0.2; comboSpr.acceleration.y = 600; @@ -133,14 +138,14 @@ class PopUpStuff extends FlxTypedGroup } else { - numScore.setGraphicSize(Std.int(numScore.width * 0.5)); + numScore.setGraphicSize(Std.int(numScore.width * 0.45)); numScore.antialiasing = true; } numScore.updateHitbox(); - numScore.x = comboSpr.x - (43 * daLoop); //- 90; - numScore.acceleration.y = FlxG.random.int(200, 300); - numScore.velocity.y -= FlxG.random.int(140, 160); + numScore.x = comboSpr.x - (36 * daLoop) - 65; //- 90; + numScore.acceleration.y = FlxG.random.int(250, 300); + numScore.velocity.y -= FlxG.random.int(130, 150); numScore.velocity.x = FlxG.random.float(-5, 5); add(numScore); From b3869f6504a3f098ce0b01111975cc4dc2081a8c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Apr 2024 14:16:57 -0400 Subject: [PATCH 32/43] assets update for submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 31dfbf9d5..a24f42932 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 31dfbf9d545ea897e58d0257381cbdf8e4281d3c +Subproject commit a24f42932fbe9032d28be1603f197fb50c938276 From 49a81189c40b35fc77ed62eba0b2914fbc4e23dc Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Apr 2024 15:00:12 -0400 Subject: [PATCH 33/43] use funkinaction in controls.hx --- source/funkin/input/Controls.hx | 72 ++++++++++++++++----------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index d76c26153..14b226d88 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -30,42 +30,42 @@ 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); - var _ui_down = new FlxActionDigital(Action.UI_DOWN); - var _ui_upP = new FlxActionDigital(Action.UI_UP_P); - var _ui_leftP = new FlxActionDigital(Action.UI_LEFT_P); - var _ui_rightP = new FlxActionDigital(Action.UI_RIGHT_P); - var _ui_downP = new FlxActionDigital(Action.UI_DOWN_P); - var _ui_upR = new FlxActionDigital(Action.UI_UP_R); - var _ui_leftR = new FlxActionDigital(Action.UI_LEFT_R); - var _ui_rightR = new FlxActionDigital(Action.UI_RIGHT_R); - var _ui_downR = new FlxActionDigital(Action.UI_DOWN_R); - var _note_up = new FlxActionDigital(Action.NOTE_UP); - var _note_left = new FlxActionDigital(Action.NOTE_LEFT); - var _note_right = new FlxActionDigital(Action.NOTE_RIGHT); - var _note_down = new FlxActionDigital(Action.NOTE_DOWN); - var _note_upP = new FlxActionDigital(Action.NOTE_UP_P); - var _note_leftP = new FlxActionDigital(Action.NOTE_LEFT_P); - var _note_rightP = new FlxActionDigital(Action.NOTE_RIGHT_P); - var _note_downP = new FlxActionDigital(Action.NOTE_DOWN_P); - var _note_upR = new FlxActionDigital(Action.NOTE_UP_R); - var _note_leftR = new FlxActionDigital(Action.NOTE_LEFT_R); - var _note_rightR = new FlxActionDigital(Action.NOTE_RIGHT_R); - var _note_downR = new FlxActionDigital(Action.NOTE_DOWN_R); - var _accept = new FlxActionDigital(Action.ACCEPT); - var _back = new FlxActionDigital(Action.BACK); - var _pause = new FlxActionDigital(Action.PAUSE); - var _reset = new FlxActionDigital(Action.RESET); - var _screenshot = new FlxActionDigital(Action.SCREENSHOT); - var _cutscene_advance = new FlxActionDigital(Action.CUTSCENE_ADVANCE); - var _debug_menu = new FlxActionDigital(Action.DEBUG_MENU); - var _debug_chart = new FlxActionDigital(Action.DEBUG_CHART); - var _debug_stage = new FlxActionDigital(Action.DEBUG_STAGE); - var _volume_up = new FlxActionDigital(Action.VOLUME_UP); - var _volume_down = new FlxActionDigital(Action.VOLUME_DOWN); - var _volume_mute = new FlxActionDigital(Action.VOLUME_MUTE); + var _ui_up = new FunkinAction(Action.UI_UP); + var _ui_left = new FunkinAction(Action.UI_LEFT); + var _ui_right = new FunkinAction(Action.UI_RIGHT); + var _ui_down = new FunkinAction(Action.UI_DOWN); + var _ui_upP = new FunkinAction(Action.UI_UP_P); + var _ui_leftP = new FunkinAction(Action.UI_LEFT_P); + var _ui_rightP = new FunkinAction(Action.UI_RIGHT_P); + var _ui_downP = new FunkinAction(Action.UI_DOWN_P); + var _ui_upR = new FunkinAction(Action.UI_UP_R); + var _ui_leftR = new FunkinAction(Action.UI_LEFT_R); + var _ui_rightR = new FunkinAction(Action.UI_RIGHT_R); + var _ui_downR = new FunkinAction(Action.UI_DOWN_R); + var _note_up = new FunkinAction(Action.NOTE_UP); + var _note_left = new FunkinAction(Action.NOTE_LEFT); + var _note_right = new FunkinAction(Action.NOTE_RIGHT); + var _note_down = new FunkinAction(Action.NOTE_DOWN); + var _note_upP = new FunkinAction(Action.NOTE_UP_P); + var _note_leftP = new FunkinAction(Action.NOTE_LEFT_P); + var _note_rightP = new FunkinAction(Action.NOTE_RIGHT_P); + var _note_downP = new FunkinAction(Action.NOTE_DOWN_P); + var _note_upR = new FunkinAction(Action.NOTE_UP_R); + var _note_leftR = new FunkinAction(Action.NOTE_LEFT_R); + var _note_rightR = new FunkinAction(Action.NOTE_RIGHT_R); + var _note_downR = new FunkinAction(Action.NOTE_DOWN_R); + var _accept = new FunkinAction(Action.ACCEPT); + var _back = new FunkinAction(Action.BACK); + var _pause = new FunkinAction(Action.PAUSE); + var _reset = new FunkinAction(Action.RESET); + var _screenshot = new FunkinAction(Action.SCREENSHOT); + var _cutscene_advance = new FunkinAction(Action.CUTSCENE_ADVANCE); + var _debug_menu = new FunkinAction(Action.DEBUG_MENU); + var _debug_chart = new FunkinAction(Action.DEBUG_CHART); + var _debug_stage = new FunkinAction(Action.DEBUG_STAGE); + var _volume_up = new FunkinAction(Action.VOLUME_UP); + var _volume_down = new FunkinAction(Action.VOLUME_DOWN); + var _volume_mute = new FunkinAction(Action.VOLUME_MUTE); var byName:Map = new Map(); From 57df7db5f10a7017a8602c576bf7a26f15d65198 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Apr 2024 15:10:43 -0400 Subject: [PATCH 34/43] add small #if web define --- source/funkin/audio/visualize/ABotVis.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 1188d389f..5874b8921 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -83,8 +83,9 @@ class ABotVis extends FlxTypedSpriteGroup override function draw() { + #if web if (analyzer != null) drawFFT(); - + #end super.draw(); } From 7826c7987118356eee1875eb2fc18c8170620647 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Apr 2024 15:11:20 -0400 Subject: [PATCH 35/43] assets update for submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index f98e9c66a..daf702a6e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f98e9c66aa06b978fd8f418c9fae3c8d4c163897 +Subproject commit daf702a6ec8b60f1922261872cc74eb107fece06 From 4671a9172cfbb261329dc21a983c7e1a3ae05bd9 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 20 Apr 2024 23:48:27 -0400 Subject: [PATCH 36/43] Fix the NG logo overlapping the text --- source/funkin/ui/title/TitleState.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index e76e66003..d122bf7c1 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -188,6 +188,7 @@ class TitleState extends MusicBeatState ngSpr.animation.add('idle', [0, 1], 4); ngSpr.animation.play('idle'); ngSpr.setGraphicSize(Std.int(ngSpr.width * 0.55)); + ngSpr.y += 25; } else { From 5f26eaacd38c1827b0a340edb2d343eb9cb6e145 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 21 Apr 2024 17:23:27 -0400 Subject: [PATCH 37/43] Fix issue where some FlxAnimate symbols wouldn't render on HTML5 --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 91beb40b0..6ee95f984 100644 --- a/hmm.json +++ b/hmm.json @@ -37,7 +37,7 @@ "name": "flxanimate", "type": "git", "dir": null, - "ref": "9bacdd6", + "ref": "17e0d59", "url": "https://github.com/FunkinCrew/flxanimate" }, { From d760a0d209acb9de769e4cf3a480a98ed5123421 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 21 Apr 2024 17:23:48 -0400 Subject: [PATCH 38/43] Add Ctrl-Alt-Shift-W as a debug hotkey to unlock all Darnell songs in Freeplay --- source/funkin/ui/mainmenu/MainMenuState.hx | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 0a164cf86..f053d39fe 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -328,6 +328,31 @@ class MainMenuState extends MusicBeatState FlxG.state.openSubState(new DebugMenuSubState()); } + #if (debug || FORCE_DEBUG_VERSION) + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.W) + { + // Give the user a score of 1 point on Weekend 1 story mode. + // This makes the level count as cleared and displays the songs in Freeplay. + funkin.save.Save.instance.setLevelScore('weekend1', 'easy', + { + score: 1, + tallies: + { + sick: 0, + good: 0, + bad: 0, + shit: 0, + missed: 0, + combo: 0, + maxCombo: 0, + totalNotesHit: 0, + totalNotes: 0, + }, + accuracy: 0, + }); + } + #end + if (FlxG.sound.music.volume < 0.8) { FlxG.sound.music.volume += 0.5 * elapsed; From b23ea585610f3410d4914f5b0754c2b2b4733333 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 22 Apr 2024 21:24:15 -0400 Subject: [PATCH 39/43] Fix Weekend 1 audio issue --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index daf702a6e..5a743b52e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit daf702a6ec8b60f1922261872cc74eb107fece06 +Subproject commit 5a743b52ed0a1e80c489b580a3af0470c31dcf9c From 66b45b526f74f92a6711acccf75dfa00af8e2c7c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 22 Apr 2024 21:24:44 -0400 Subject: [PATCH 40/43] Fix issue where controller couldn't switch difficulties in Story Menu --- source/funkin/ui/story/StoryMenuState.hx | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 5881ef624..d4ffa961d 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -344,6 +344,17 @@ class StoryMenuState extends MusicBeatState changeDifficulty(0); } + // TODO: Querying UI_RIGHT_P (justPressed) after UI_RIGHT always returns false. Fix it! + if (controls.UI_RIGHT_P) + { + changeDifficulty(1); + } + + if (controls.UI_LEFT_P) + { + changeDifficulty(-1); + } + if (controls.UI_RIGHT) { rightDifficultyArrow.animation.play('press'); @@ -362,16 +373,6 @@ class StoryMenuState extends MusicBeatState leftDifficultyArrow.animation.play('idle'); } - if (controls.UI_RIGHT_P) - { - changeDifficulty(1); - } - - if (controls.UI_LEFT_P) - { - changeDifficulty(-1); - } - if (FlxG.keys.justPressed.TAB && modeText.visible) { switchMode(!displayingModdedLevels); From 6edd9e8c6af01ce3985abb2a0f255108b4f08e85 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 22 Apr 2024 22:30:29 -0400 Subject: [PATCH 41/43] Make cars stop moving while the game is paused. --- assets | 2 +- source/funkin/util/FlxTweenUtil.hx | 36 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 source/funkin/util/FlxTweenUtil.hx diff --git a/assets b/assets index 5a743b52e..e1a3527e0 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5a743b52ed0a1e80c489b580a3af0470c31dcf9c +Subproject commit e1a3527e098910d34763b6a2f7f3f4242d13f2b9 diff --git a/source/funkin/util/FlxTweenUtil.hx b/source/funkin/util/FlxTweenUtil.hx new file mode 100644 index 000000000..57c8f0cfe --- /dev/null +++ b/source/funkin/util/FlxTweenUtil.hx @@ -0,0 +1,36 @@ +package funkin.util; + +import flixel.addons.plugin.taskManager.FlxTask; +import flixel.tweens.FlxTween; +import flixel.tweens.FlxEase; + +class FlxTweenUtil +{ + public static function pauseTween(tween:FlxTween):Void + { + if (tween != null) + { + tween.active = false; + } + } + + public static function resumeTween(tween:FlxTween):Void + { + if (tween != null) + { + tween.active = true; + } + } + + public static function pauseTweensOf(Object:Dynamic, ?FieldPaths:Array):Void + { + @:privateAccess + FlxTween.globalManager.forEachTweensOf(Object, FieldPaths, pauseTween); + } + + public static function resumeTweensOf(Object:Dynamic, ?FieldPaths:Array):Void + { + @:privateAccess + FlxTween.globalManager.forEachTweensOf(Object, FieldPaths, resumeTween); + } +} From 1e5153f133f47cf705f6a3e8718933b7c13982c6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 22 Apr 2024 23:04:57 -0400 Subject: [PATCH 42/43] Fix an issue where zooming in the camera would persist to results screen --- source/funkin/play/ResultState.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 591020955..acce8645a 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -64,6 +64,9 @@ class ResultState extends MusicBeatSubState loop: resultsVariation != SHIT }); + // Reset the camera zoom on the results screen. + FlxG.camera.zoom = 1.0; + // TEMP-ish, just used to sorta "cache" the 3000x3000 image! var cacheBullShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/soundSystem")); add(cacheBullShit); From 46f2dec67213c96a728b020ff9caf922c527af9f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 23 Apr 2024 04:08:00 -0400 Subject: [PATCH 43/43] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index e1a3527e0..9676d4941 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit e1a3527e098910d34763b6a2f7f3f4242d13f2b9 +Subproject commit 9676d494146008bb99cd718fadffa3610a659ad4