diff --git a/assets/images/editors/ui/context-icons.png b/assets/images/editors/ui/context-icons.png new file mode 100644 index 00000000..73b8ff97 Binary files /dev/null and b/assets/images/editors/ui/context-icons.png differ diff --git a/assets/sounds/editors/charter/hitsound.mp3 b/assets/sounds/editors/charter/hitsound.mp3 new file mode 100644 index 00000000..67cbc251 Binary files /dev/null and b/assets/sounds/editors/charter/hitsound.mp3 differ diff --git a/assets/sounds/editors/charter/hitsound.ogg b/assets/sounds/editors/charter/hitsound.ogg new file mode 100644 index 00000000..c037ff13 Binary files /dev/null and b/assets/sounds/editors/charter/hitsound.ogg differ diff --git a/assets/sounds/editors/charter/metronome.mp3 b/assets/sounds/editors/charter/metronome.mp3 new file mode 100644 index 00000000..4a823020 Binary files /dev/null and b/assets/sounds/editors/charter/metronome.mp3 differ diff --git a/assets/sounds/editors/charter/metronome.ogg b/assets/sounds/editors/charter/metronome.ogg new file mode 100644 index 00000000..e1718864 Binary files /dev/null and b/assets/sounds/editors/charter/metronome.ogg differ diff --git a/buildnumber.txt b/buildnumber.txt index 389f0444..f01b197d 100644 --- a/buildnumber.txt +++ b/buildnumber.txt @@ -1 +1,5 @@ -2675 \ No newline at end of file +<<<<<<< HEAD +2675 +======= +2674 +>>>>>>> 18c107ab0aa092b608a060647e1ad05e34b93984 diff --git a/source/funkin/editors/UIDebugState.hx b/source/funkin/editors/UIDebugState.hx index d2179195..e72f6030 100644 --- a/source/funkin/editors/UIDebugState.hx +++ b/source/funkin/editors/UIDebugState.hx @@ -33,7 +33,7 @@ class UIDebugState extends UIState { null, { label: "Exit", - onSelect: () -> {FlxG.switchState(new funkin.menus.MainMenuState());} + onSelect: (t) -> {FlxG.switchState(new funkin.menus.MainMenuState());} } ] }, @@ -107,13 +107,13 @@ class UIDebugState extends UIState { openContextMenu([ { label: "Test 1", - onSelect: function() { + onSelect: function(t) { trace("Test 1 clicked"); } }, { label: "Test 2", - onSelect: function() { + onSelect: function(t) { trace("Test 2 clicked"); } }, @@ -122,7 +122,7 @@ class UIDebugState extends UIState { childs: [ { label: "Test 4", - onSelect: function() { + onSelect: function(t) { trace("Test 4 clicked"); } } diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 3cbbdbea..206107eb 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -1,5 +1,7 @@ package funkin.editors.charter; +import flixel.system.FlxSound; +import flixel.util.FlxSort; import flixel.math.FlxPoint; import funkin.editors.charter.CharterBackdrop.CharterBackdropDummy; import funkin.system.Conductor; @@ -32,6 +34,12 @@ class Charter extends UIState { public var topMenuSpr:UITopMenu; public var gridBackdrop:CharterBackdrop; public var gridBackdropDummy:CharterBackdropDummy; + public var conductorFollowerSpr:FlxSprite; + + public var hitsound:FlxSound; + public var metronome:FlxSound; + + public var vocals:FlxSound; /** * ACTUAL CHART DATA @@ -51,6 +59,9 @@ class Charter extends UIState { public var selection:Array = []; + public var undoList:Array = []; + public var redoList:Array = []; + public function new(song:String, diff:String) { super(); __song = song; @@ -60,6 +71,8 @@ class Charter extends UIState { public override function create() { super.create(); + trace('Entering Charter for song $__song with difficulty $__diff.'); + topMenu = [ { label: "File", @@ -78,10 +91,12 @@ class Charter extends UIState { label: "Edit", childs: [ { - label: "Undo" + label: "Undo", + onSelect: _edit_undo }, { - label: "Redo" + label: "Redo", + onSelect: _edit_redo }, null, { @@ -126,25 +141,38 @@ class Charter extends UIState { label: "Playback", childs: [ { - label: "Play/Pause" + label: "Play/Pause", + onSelect: _playback_play }, null, { - label: "Go back a section" + label: "Go back a section", + onSelect: _playback_back }, { - label: "Go forward a section" + label: "Go forward a section", + onSelect: _playback_forward }, null, { - label: "Go back to the start" + label: "Go back to the start", + onSelect: _playback_start + }, + null, + { + label: "Metronome", + onSelect: _playback_metronome + }, + { + label: "Visual metronome" } ] } ]; - trace('Entering Charter for song $__song with difficulty $__diff.'); + hitsound = FlxG.sound.load(Paths.sound('editors/charter/hitsound')); + metronome = FlxG.sound.load(Paths.sound('editors/charter/metronome')); charterCamera = FlxG.camera; uiCamera = new FlxCamera(); @@ -161,7 +189,11 @@ class Charter extends UIState { selectionBox.scrollFactor.set(1, 1); selectionBox.incorporeal = true; - selectionBox.cameras = notesGroup.cameras = gridBackdrop.cameras = [charterCamera]; + conductorFollowerSpr = new FlxSprite(0, 0).makeGraphic(1, 1, -1); + conductorFollowerSpr.scale.set(gridBackdrop.strumlinesAmount * 4 * 40, 4); + conductorFollowerSpr.updateHitbox(); + + conductorFollowerSpr.cameras = selectionBox.cameras = notesGroup.cameras = gridBackdrop.cameras = [charterCamera]; topMenuSpr = new UITopMenu(topMenu); @@ -171,6 +203,7 @@ class Charter extends UIState { // adds grid and notes so that they're ALWAYS behind the UI add(gridBackdrop); add(notesGroup); + add(conductorFollowerSpr); add(selectionBox); // add the ui group add(uiGroup); @@ -184,6 +217,9 @@ class Charter extends UIState { CoolUtil.loadSong(__song, __diff, false, false); Conductor.setupSong(PlayState.SONG); + + FlxG.sound.music = FlxG.sound.load(Paths.inst(__song, __diff)); + vocals = FlxG.sound.load(Paths.voices(__song, __diff)); for(strID=>strL in PlayState.SONG.strumLines) { for(note in strL.notes) { @@ -194,6 +230,12 @@ class Charter extends UIState { } } + public override function beatHit(curBeat:Int) { + super.beatHit(curBeat); + if (Options.charterMetronomeEnabled) + metronome.replay(); + } + /** * NOTE AND CHARTER GRID LOGIC HERE */ @@ -208,6 +250,8 @@ class Charter extends UIState { if (FlxG.mouse.justReleased) { if (FlxG.keys.pressed.CONTROL) selection.push(n); + else if (FlxG.keys.pressed.SHIFT) + selection.remove(n); else selection = [n]; } @@ -240,16 +284,28 @@ class Charter extends UIState { } if (FlxG.mouse.justReleased) { if (selectionBoxEnabled) { - var minX = Std.int(Math.round(selectionBox.x / 40)); - var minY = Math.round(selectionBox.y / 40) - 1; - var maxX = Std.int(Math.round((selectionBox.x + selectionBox.bWidth) / 40)); - var maxY = Math.round((selectionBox.y + selectionBox.bHeight) / 40); + var minX = Std.int(selectionBox.x / 40); + var minY = Std.int(selectionBox.y / 40); + var maxX = Std.int(Math.ceil((selectionBox.x + selectionBox.bWidth) / 40)); + var maxY = Math.ceil((selectionBox.y + selectionBox.bHeight) / 40); - selection = []; - notesGroup.forEach(function(n) { - if (n.id >= minX && n.id <= maxX && n.step >= minY && n.step <= maxY) - selection.push(n); - }); + if (FlxG.keys.pressed.SHIFT) { + notesGroup.forEach(function(n) { + if (n.id >= minX && n.id < maxX && n.step >= minY && n.step < maxY && selection.contains(n)) + selection.remove(n); + }); + } else if (FlxG.keys.pressed.CONTROL) { + notesGroup.forEach(function(n) { + if (n.id >= minX && n.id < maxX && n.step >= minY && n.step < maxY && !selection.contains(n)) + selection.push(n); + }); + } else { + selection = []; + notesGroup.forEach(function(n) { + if (n.id >= minX && n.id < maxX && n.step >= minY && n.step < maxY) + selection.push(n); + }); + } selectionBoxEnabled = false; } else { @@ -258,6 +314,7 @@ class Charter extends UIState { note.updatePos(FlxG.keys.pressed.SHIFT ? (mousePos.y / 40) : Std.int(mousePos.y / 40), Std.int(mousePos.x / 40), 0, 0); notesGroup.add(note); selection = [note]; + addToUndo(CPlaceNote(note)); } } if (FlxG.mouse.justReleasedRight) @@ -265,11 +322,109 @@ class Charter extends UIState { } selectionBox.visible = selectionBoxEnabled; } + + public function deleteNote(note:CharterNote):CharterNote { + if (note == null) return note; + + notesGroup.remove(note, true); + note.kill(); + addToUndo(CDeleteNotes([note])); + return null; + } + + public function deleteNotes(notes:Array) { + if (notes.length <= 0) return []; + + for(note in notes) { + notesGroup.remove(note, true); + note.kill(); + } + addToUndo(CDeleteNotes(notes)); + return []; + } + + // UNDO/REDO LOGIC + #if REGION + public inline function addToUndo(c:CharterChange) { + redoList = []; + undoList.insert(0, c); + while(undoList.length > Options.maxUndos) + undoList.pop(); + } + + function _edit_undo(_) { + selection = []; + var v = undoList.shift(); + switch(v) { + case null: + // do nothing + case CCreateNotes(notes): + for(n in notes) { + notesGroup.remove(n, true); + n.kill(); + } + case CDeleteNotes(notes): + for(n in notes) { + notesGroup.add(n); + n.revive(); + } + sortNotes(); + case CPlaceNote(note): + notesGroup.remove(note, true); + note.kill(); + } + if (v != null) + redoList.insert(0, v); + } + + function _playback_play(_) { + if (FlxG.sound.music.playing) { + FlxG.sound.music.pause(); + vocals.pause(); + } else { + FlxG.sound.music.time = vocals.time = Conductor.songPosition; + FlxG.sound.music.play(); + vocals.play(); + } + } + + function _edit_redo(_) { + selection = []; + var v = redoList.shift(); + switch(v) { + case null: + // do nothing + case CCreateNotes(notes): + for(n in notes) { + notesGroup.add(n); + n.revive(); + } + case CDeleteNotes(notes): + for(n in notes) { + notesGroup.remove(n, true); + n.kill(); + } + case CPlaceNote(note): + notesGroup.add(note); + note.revive(); + } + if (v != null) + undoList.insert(0, v); + } + + function _playback_metronome(t) { + t.icon = (Options.charterMetronomeEnabled = !Options.charterMetronomeEnabled) ? 1 : 0; + } #end + + public inline function sortNotes() + notesGroup.sort((i, c1, c2) -> FlxSort.byValues(i, c1.step, c2.step), FlxSort.ASCENDING); + #end + + var __crochet:Float; public override function update(elapsed:Float) { // TODO: do optimization like NoteGroup updateNoteLogic(elapsed); - super.update(elapsed); @@ -277,37 +432,65 @@ class Charter extends UIState { // TODO: canTypeText in case an ui input element is focused if (true) { - if (controls.LEFT) - FlxG.camera.scroll.x -= 250 * elapsed; - if (controls.RIGHT) - FlxG.camera.scroll.x += 250 * elapsed; - if (controls.UP) - FlxG.camera.scroll.y -= 250 * elapsed; - if (controls.DOWN) - FlxG.camera.scroll.y += 250 * elapsed; - if (FlxG.keys.justPressed.DELETE) - _edit_delete(); - } - } + _edit_delete(null); - public function deleteNote(note:CharterNote):CharterNote { - notesGroup.remove(note, true); - note.kill(); - note.destroy(); - return null; + if (FlxG.keys.pressed.CONTROL) { + if (FlxG.keys.justPressed.Z) + _edit_undo(null); + if (FlxG.keys.justPressed.Y) + _edit_redo(null); + } + + if (FlxG.keys.justPressed.SPACE) + _playback_play(null); + + __crochet = ((60 / Conductor.bpm) * 1000); + Conductor.songPosition -= __crochet * FlxG.mouse.wheel; + + if (FlxG.keys.justPressed.D) + _playback_forward(null); + if (FlxG.keys.justPressed.A) + _playback_back(null); + if (FlxG.keys.justPressed.HOME) + _playback_start(null); + if (FlxG.keys.justPressed.END) + _playback_end(null); + } + + Conductor.songPosition = FlxMath.bound(Conductor.songPosition, 0, FlxG.sound.music.length); + + conductorFollowerSpr.y = curStepFloat * 40; + charterCamera.scroll.set(conductorFollowerSpr.x + conductorFollowerSpr.scale.x - (FlxG.width / 2), conductorFollowerSpr.y - (FlxG.height * 0.25)); } // TOP MENU OPTIONS #if REGION - function _file_exit() { + function _file_exit(_) { FlxG.switchState(new CharterSelection()); } - function _edit_delete() { + function _edit_delete(_) { if (selection == null) return; - for(s in selection) - deleteNote(s); + selection = deleteNotes(selection); } + function _playback_back(_) { + Conductor.songPosition -= Conductor.beatsPerMesure * __crochet; + } + function _playback_forward(_) { + Conductor.songPosition += Conductor.beatsPerMesure * __crochet; + } + function _playback_start(_) { + Conductor.songPosition = 0; + } + function _playback_end(_) { + Conductor.songPosition = FlxG.sound.music.time; + } #end +} + +enum CharterChange { + CPlaceNote(note:CharterNote); + CCreateNotes(notes:Array); + CDeleteNotes(notes:Array); } \ No newline at end of file diff --git a/source/funkin/editors/charter/CharterNote.hx b/source/funkin/editors/charter/CharterNote.hx index d0aaccef..8e87dbc8 100644 --- a/source/funkin/editors/charter/CharterNote.hx +++ b/source/funkin/editors/charter/CharterNote.hx @@ -50,6 +50,20 @@ class CharterNote extends UISprite { }}); } + public override function kill() { + if (angleTween != null) { + angleTween.cancel(); + angle = switch(animation.curAnim.curFrame = (id % 4)) { + case 0: -90; + case 1: 180; + case 2: 0; + case 3: 90; + default: 0; // how is that even possible + }; + } + super.kill(); + } + public override function update(elapsed:Float) { super.update(elapsed); colorTransform.redMultiplier = colorTransform.greenMultiplier = colorTransform.blueMultiplier = selected ? 0.75 : 1; diff --git a/source/funkin/editors/ui/UIContextMenu.hx b/source/funkin/editors/ui/UIContextMenu.hx index 449d9e40..e6fad90e 100644 --- a/source/funkin/editors/ui/UIContextMenu.hx +++ b/source/funkin/editors/ui/UIContextMenu.hx @@ -78,7 +78,7 @@ class UIContextMenu extends MusicBeatSubstate { public function select(option:UIContextMenuOption) { var index = options.indexOf(option); if (option.onSelect != null) - option.onSelect(); + option.onSelect(option); if (callback != null) callback(this, index, option); close(); @@ -108,7 +108,7 @@ typedef UIContextMenuCallback = UIContextMenu->Int->UIContextMenuOption->Void; typedef UIContextMenuOption = { var label:String; var ?icon:Int; - var ?onSelect:Void->Void; + var ?onSelect:UIContextMenuOption->Void; var ?childs:Array; } diff --git a/source/funkin/macros/GitCommitMacro.hx b/source/funkin/macros/GitCommitMacro.hx new file mode 100644 index 00000000..b7227ba7 --- /dev/null +++ b/source/funkin/macros/GitCommitMacro.hx @@ -0,0 +1,16 @@ +package funkin.macros; + +class GitCommitMacro { + public static macro function getCommitNumber() { + #if display + return macro $v{0}; + #else + var proc = new Process('git', ['rev-list', 'HEAD', '--count'], false); + proc.exitCode(true); + + var c = Std.parseInt(proc.stdout.readLine()); + trace(c); + return macro $v{c}; + #end + } +} \ No newline at end of file diff --git a/source/funkin/options/Options.hx b/source/funkin/options/Options.hx index 1a14a7a1..b701614d 100644 --- a/source/funkin/options/Options.hx +++ b/source/funkin/options/Options.hx @@ -37,6 +37,10 @@ class Options */ public static var editorSFX:Bool = true; public static var resizableEditors:Bool = true; + public static var maxUndos:Int = 120; + + // CHARTER + public static var charterMetronomeEnabled:Bool = false; /** * PLAYER 1 CONTROLS diff --git a/source/funkin/system/Conductor.hx b/source/funkin/system/Conductor.hx index 0d3c19d9..491b1ccf 100644 --- a/source/funkin/system/Conductor.hx +++ b/source/funkin/system/Conductor.hx @@ -93,9 +93,6 @@ class Conductor @:dox(hide) public static var lastSongPos:Float = 0; - @:dox(hide) public static var lastSongPosTime:Float = 0; - @:dox(hide) public static var speed:Float = 0; - @:dox(hide) public static var destSpeed:Float = 0; @:dox(hide) public static var offset:Float = 0; /** @@ -107,7 +104,6 @@ class Conductor public static function reset() { songPosition = lastSongPos = curBeatFloat = curStepFloat = curBeat = curStep = 0; - speed = 1; bpmChangeMap = []; changeBPM(0); } @@ -154,27 +150,18 @@ class Conductor reset(); } - private static var __timeUntilUpdate:Float; - private static var __elapsedAL:Float; - private static function __updateSongPos(elapsed:Float, mainTime:Float) { + private static function __updateSongPos(elapsed:Float) { if (FlxG.sound.music == null || !FlxG.sound.music.playing) { - speed = destSpeed = 1; lastSongPos = FlxG.sound.music != null ? FlxG.sound.music.time : 0; - lastSongPosTime = mainTime; return; } - var lastPos = lastSongPos; if (lastSongPos != (lastSongPos = FlxG.sound.music.time)) { // update conductor - __timeUntilUpdate = -(lastSongPosTime - (lastSongPosTime = mainTime)); - __elapsedAL = (lastSongPos - lastPos); - destSpeed = FlxMath.bound(__timeUntilUpdate / __elapsedAL, 0.925, 1.075); songPosition = lastSongPos; } else { - songPosition += elapsed * 1000 * speed; + songPosition += elapsed * 1000; } - speed = FlxMath.lerp(speed, destSpeed, FlxMath.bound(elapsed, 0, 1)); } private static function onStateSwitch(newState:FlxState) { @@ -188,7 +175,7 @@ class Conductor private static function update() { if (FlxG.state != null && FlxG.state is MusicBeatState && cast(FlxG.state, MusicBeatState).cancelConductorUpdate) return; - __updateSongPos(FlxG.elapsed, Main.time); + __updateSongPos(FlxG.elapsed); if (bpm > 0) { // updates curbeat and stuff diff --git a/source/funkin/system/framerate/ConductorInfo.hx b/source/funkin/system/framerate/ConductorInfo.hx index 009f3224..2fdfa11c 100644 --- a/source/funkin/system/framerate/ConductorInfo.hx +++ b/source/funkin/system/framerate/ConductorInfo.hx @@ -13,7 +13,6 @@ class ConductorInfo extends FramerateCategory { _text += '\n - ${Conductor.curStep} steps'; _text += '\n - ${Conductor.curMeasure} measures'; _text += '\nCurrent BPM: ${Conductor.bpm}'; - _text += '\nCurrent speed: ${FlxMath.roundDecimal(Conductor.speed, 2)}x'; _text += '\nTime Signature: ${Conductor.beatsPerMesure}/${Conductor.stepsPerBeat}'; this.text.text = _text; diff --git a/source/funkin/system/framerate/SystemInfo.hx b/source/funkin/system/framerate/SystemInfo.hx index ae132f51..bdaef0ee 100644 --- a/source/funkin/system/framerate/SystemInfo.hx +++ b/source/funkin/system/framerate/SystemInfo.hx @@ -19,8 +19,13 @@ class SystemInfo extends FramerateCategory { #if windows var process = new HiddenProcess("wmic", ["cpu", "get", "name"]); if (process.exitCode() == 0) cpuName = process.stdout.readAll().toString().trim().split("\n")[1].trim(); +<<<<<<< HEAD #elseif mac var process = new HiddenProcess("sysctl -a | grep brand"); +======= + #elseif (mac) + var process = new sys.io.Process("sysctl -a | grep brand_string"); +>>>>>>> 18c107ab0aa092b608a060647e1ad05e34b93984 if (process.exitCode() == 0) cpuName = process.stdout.readAll().toString().trim().split(":")[1].trim(); #elseif linux var process = new HiddenProcess("cat", ["/proc/cpuinfo"]); diff --git a/source/funkin/utils/CoolUtil.hx b/source/funkin/utils/CoolUtil.hx index 1752362f..d96b3ed3 100644 --- a/source/funkin/utils/CoolUtil.hx +++ b/source/funkin/utils/CoolUtil.hx @@ -1,5 +1,6 @@ package funkin.utils; +import flixel.system.FlxSound; import funkin.system.Conductor; import flixel.system.FlxSoundGroup; import animateatlas.AtlasFrameMaker; @@ -410,6 +411,12 @@ class CoolUtil #end } + public static function replay(sound:FlxSound) { + sound.stop(); + sound.time = 0; + sound.play(); + } + public static inline function maxInt(p1:Int, p2:Int) return p1 < p2 ? p2 : p1; }