From d404d97d677646dfa065ffc2af56a455f4d2573c Mon Sep 17 00:00:00 2001 From: lunarcleint <88809950+lunarcleint@users.noreply.github.com> Date: Thu, 29 Feb 2024 18:15:57 -0700 Subject: [PATCH] draggable sustains --- source/funkin/editors/charter/Charter.hx | 109 ++++++++++++------ source/funkin/editors/charter/CharterNote.hx | 55 ++++++--- .../editors/charter/CharterNoteHoverer.hx | 12 +- 3 files changed, 118 insertions(+), 58 deletions(-) diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 290cf1db..a5a800ce 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -59,7 +59,7 @@ class Charter extends UIState { public var addEventSpr:CharterEventAdd; public var gridBackdropDummy:CharterBackdropDummy; - public var noteHoverer:CharterNote; + public var noteHoverer:CharterNoteHoverer; public var strumlineInfoBG:FlxSprite; public var strumlineAddButton:CharterStrumlineButton; @@ -577,47 +577,49 @@ class Charter extends UIState { * NOTE AND CHARTER GRID LOGIC HERE */ #if REGION - var gridActionType:CharterGridActionType = NONE; - var dragStartPos:FlxPoint = new FlxPoint(); - var selectionDragging:Bool = false; + public var gridActionType:CharterGridActionType = NONE; + public var dragStartPos:FlxPoint = new FlxPoint(); + public var mousePos:FlxPoint = new FlxPoint(); + public var selectionDragging:Bool = false; + + public function updateSelectionLogic() { + function select(s:ICharterSelectable) { + if (FlxG.keys.pressed.CONTROL) selection.push(s); + else if (FlxG.keys.pressed.SHIFT) selection.remove(s); + else selection = [s]; + } - public function updateNoteLogic(elapsed:Float) { for (group in [notesGroup, eventsGroup]) { - cast(group, FlxTypedGroup).forEach(function(n) { - n.selected = false; - if (n.hovered && gridActionType == NONE) { - if (FlxG.mouse.justReleased) { - if (FlxG.keys.pressed.CONTROL) - selection.push(cast n); - else if (FlxG.keys.pressed.SHIFT) - selection.remove(cast n); - else - selection = [cast n]; - } + cast(group, FlxTypedGroup).forEach(function(s) { + s.selected = false; + if (gridActionType == NONE) { + if (s is CharterNote) { + var n:CharterNote = cast s; - if (FlxG.mouse.justReleasedRight) { - var mousePos = FlxG.mouse.getScreenPosition(uiCamera); - if (!selection.contains(cast n)) - selection = [cast n]; - closeCurrentContextMenu(); - openContextMenu(topMenu[1].childs, null, mousePos.x, mousePos.y); - mousePos.put(); - } + if (n.sustainDraggable) { // So it feels smoother :D -lunar + if (FlxG.mouse.justPressed && !selection.contains(s)) select(cast s); + } else if (FlxG.mouse.justReleased && s.hovered) select(cast s); + + } else if (FlxG.mouse.justReleased && s.hovered) select(cast s); } }); } selection = __fixSelection(selection); for(s in selection) s.selected = true; + } + + public function updateNoteLogic(elapsed:Float) { + updateSelectionLogic(); /** * NOTE DRAG HANDLING */ - var mousePos = FlxG.mouse.getWorldPosition(charterCamera); + mousePos = FlxG.mouse.getWorldPosition(charterCamera); if (!gridBackdropDummy.hoveredByChild && !FlxG.mouse.pressed) gridActionType = NONE; selectionBox.visible = false; switch(gridActionType) { - case BOX: + case BOX_SELECTION: if (gridBackdropDummy.hoveredByChild) { selectionBox.visible = true; if (FlxG.mouse.pressed) { @@ -652,7 +654,7 @@ class Charter extends UIState { // do nothing, locked if (!FlxG.mouse.pressed) gridActionType = NONE; - case DRAG: + case NOTE_DRAG: selectionDragging = FlxG.mouse.pressed; if (selectionDragging) { gridBackdrops.draggingObj = null; @@ -715,7 +717,7 @@ class Charter extends UIState { if (gridBackdropDummy.hovered) { // AUTO DETECT if (FlxG.mouse.pressed && (Math.abs(mousePos.x - dragStartPos.x) > 20 || Math.abs(mousePos.y - dragStartPos.y) > 20)) - gridActionType = BOX; + gridActionType = BOX_SELECTION; var id = Math.floor(mousePos.x / 40); var mouseOnGrid = id >= 0 && id < 4 * gridBackdrops.strumlinesAmount && mousePos.y >= 0; @@ -736,14 +738,21 @@ class Charter extends UIState { } } } else if (gridBackdropDummy.hoveredByChild) { - if (FlxG.mouse.pressed && (Math.abs(mousePos.x - dragStartPos.x) > 5 || Math.abs(mousePos.y - dragStartPos.y) > 5)) { + if (FlxG.mouse.pressed) { var noteHovered:Bool = false; - for(n in selection) - if (n.hovered) { - noteHovered = true; - break; - } - gridActionType = noteHovered ? DRAG : INVALID_DRAG; + for(n in selection) if (n.hovered) {noteHovered = true; break;} + + var noteSusDrag:Bool = false; + for(s in selection) { + if (!(s is CharterNote)) continue; + var n:CharterNote = cast s; + if (n.sustainDraggable) {noteSusDrag = true; break;} + } + + if ((Math.abs(mousePos.x - dragStartPos.x) > (noteSusDrag ? 1 : 5) || Math.abs(mousePos.y - dragStartPos.y) > (noteSusDrag ? 1 : 5))) { + if (noteHovered) gridActionType = noteHovered ? NOTE_DRAG : INVALID_DRAG; + if (noteSusDrag) gridActionType = SUSTAIN_DRAG; + } } } @@ -753,6 +762,29 @@ class Charter extends UIState { openContextMenu(topMenu[1].childs, null, mousePos.x, mousePos.y); mousePos.put(); } + case SUSTAIN_DRAG: + selectionDragging = FlxG.mouse.pressed; + if (selectionDragging) { + currentCursor = BUTTON; + selection.loop(function (n:CharterNote) { + n.tempSusLength = Math.max((mousePos.y-dragStartPos.y) / 40, -n.susLength); + }); + } else { + var undoChanges:Array = []; + selection.loop(function (n:CharterNote) { + var oldSusLen:Float = n.susLength; + + n.susLength += n.tempSusLength; + n.tempSusLength = 0; + + n.updatePos(n.step, n.id, n.susLength, n.type); + undoChanges.push({before: oldSusLen, after: n.susLength, note: n}); + }); + undos.addToUndo(CEditSustains(undoChanges)); + + gridActionType = NONE; + currentCursor = ARROW; + } } addEventSpr.selectable = !selectionBox.visible; @@ -766,6 +798,8 @@ class Charter extends UIState { if (event != null) addEventSpr.updateEdit(event); else addEventSpr.updatePos(FlxG.keys.pressed.SHIFT ? ((mousePos.y) / 40) : quantStepRounded(mousePos.y/40)); } else addEventSpr.sprAlpha = lerp(addEventSpr.sprAlpha, 0, 0.25); + + noteHoverer.showHoverer = Charter.instance.gridBackdropDummy.hovered; } public function quantStep(step:Float):Float { @@ -1780,9 +1814,10 @@ interface ICharterSelectable { enum abstract CharterGridActionType(Int) { var NONE = 0; - var BOX = 1; - var DRAG = 2; + var BOX_SELECTION = 1; + var NOTE_DRAG = 2; var INVALID_DRAG = 3; + var SUSTAIN_DRAG = 4; } typedef PlaytestInfo = { diff --git a/source/funkin/editors/charter/CharterNote.hx b/source/funkin/editors/charter/CharterNote.hx index 0a9af564..0939c202 100644 --- a/source/funkin/editors/charter/CharterNote.hx +++ b/source/funkin/editors/charter/CharterNote.hx @@ -9,6 +9,8 @@ import flixel.util.FlxColor; class CharterNote extends UISprite implements ICharterSelectable { var angleTween:FlxTween; + var __doAnim:Bool = false; + var __animSpeed:Float = 1; private static var colors:Array = [ 0xFFC24B99, @@ -17,10 +19,12 @@ class CharterNote extends UISprite implements ICharterSelectable { 0xFFF9393F ]; - public var sustainSpr:FlxSprite; + public var sustainSpr:UISprite; + public var sustainHtibox:UISprite; + public var tempSusLength:Float = 0; + public var sustainDraggable:Bool = false; + public var typeText:UIText; - var __doAnim:Bool = false; - var __animSpeed:Float = 1; public var selected:Bool = false; public var draggable:Bool = true; @@ -34,15 +38,22 @@ class CharterNote extends UISprite implements ICharterSelectable { animation.play("note"); this.setUnstretchedGraphicSize(40, 40, false); - cursor = BUTTON; - moves = false; - - sustainSpr = new FlxSprite(10, 40); - sustainSpr.makeGraphic(1, 1, -1); + sustainSpr = new UISprite(10, 20); + sustainSpr.makeSolid(1, 1, -1); + sustainSpr.scale.set(10, 0); members.push(sustainSpr); + sustainHtibox = new UISprite(20, 40); + sustainHtibox.makeSolid(1, 1, -1); + sustainHtibox.scale.set(20, 20); + sustainHtibox.updateHitbox(); + members.push(sustainHtibox); + sustainHtibox.alpha = 0; + typeText = new UIText(x, y, 0, Std.string(type)); - //typeText.borderSize = 1.5; + + cursor = sustainSpr.cursor = sustainHtibox.cursor = BUTTON; + moves = false; } public override function updateButtonHandler() { @@ -82,11 +93,7 @@ class CharterNote extends UISprite implements ICharterSelectable { y = step * 40; - sustainSpr.scale.set(10, (40 * susLength) + (height/2)); - sustainSpr.updateHitbox(); - sustainSpr.exists = susLength != 0; - sustainSpr.alpha = alpha; - sustainSpr.follow(this, 15, 20); + sustainHtibox.exists = susLength == 0; if (angleTween != null) angleTween.cancel(); @@ -134,8 +141,24 @@ class CharterNote extends UISprite implements ICharterSelectable { var __passed:Bool = false; public override function update(elapsed:Float) { super.update(elapsed); - if (sustainSpr.exists) - sustainSpr.follow(this, 15, 20); + + sustainDraggable = false; + if (sustainHtibox.exists) { + sustainHtibox.follow(this, 10, height-10); + + UIState.state.updateSpriteRect(sustainHtibox); + sustainDraggable = UIState.state.isOverlapping(sustainHtibox, @:privateAccess sustainHtibox.__rect); + } + + sustainSpr.scale.set(10, CoolUtil.fpsLerp(sustainSpr.scale.y, (40 * (susLength+tempSusLength)) + ((susLength+tempSusLength) != 0 ? (height/2) : 0), 1/2)); + sustainSpr.updateHitbox(); + sustainSpr.follow(this, 15, 20); + + if (!hovered && !sustainDraggable && susLength != 0) { + UIState.state.updateSpriteRect(sustainSpr); + sustainDraggable = UIState.state.isOverlapping(sustainSpr, @:privateAccess sustainSpr.__rect); + } + if (typeText.exists) typeText.follow(this, 20 - (typeText.frameWidth/2), 20 - (typeText.frameHeight/2)); diff --git a/source/funkin/editors/charter/CharterNoteHoverer.hx b/source/funkin/editors/charter/CharterNoteHoverer.hx index e3648daf..c3baf50b 100644 --- a/source/funkin/editors/charter/CharterNoteHoverer.hx +++ b/source/funkin/editors/charter/CharterNoteHoverer.hx @@ -1,11 +1,13 @@ package funkin.editors.charter; class CharterNoteHoverer extends CharterNote { + public var showHoverer:Bool = false; + public function new() { super(); snappedToStrumline = selectable = autoAlpha = false; visible = sustainSpr.visible = false; - @:privateAccess __animSpeed = 1.25; typeText.visible = false; alpha = 0.4; + @:privateAccess __animSpeed = 1.25; typeText.visible = false; alpha = 0.4; sustainHtibox.exists = false; } @:noCompletion var __mousePos:FlxPoint = FlxPoint.get(); @@ -15,7 +17,7 @@ class CharterNoteHoverer extends CharterNote { switch (Charter.instance.gridActionType) { case NONE: var inBoundsY:Bool = (__mousePos.y > 0 && __mousePos.y < (Charter.instance.__endStep)*40); - if (__mousePos.x > 0 && __mousePos.x < Charter.instance.gridBackdrops.strumlinesAmount * 160 && inBoundsY) { + if ((__mousePos.x > 0 && __mousePos.x < Charter.instance.gridBackdrops.strumlinesAmount * 160 && inBoundsY) && showHoverer) { step = FlxMath.bound(FlxG.keys.pressed.SHIFT ? ((__mousePos.y-20) / 40) : Charter.instance.quantStep(__mousePos.y/40), 0, Charter.instance.__endStep-1); id = Math.floor(__mousePos.x / 40); y = step * 40; x = id * 40; visible = true; sustainSpr.visible = typeText.visible = false; angle = switch(animation.curAnim.curFrame = (id % 4)) { @@ -27,7 +29,7 @@ class CharterNoteHoverer extends CharterNote { }; } else visible = false; - case DRAG: + case NOTE_DRAG: visible = sustainSpr.visible = typeText.visible = true; __doAnim = false; default: visible = sustainSpr.visible = typeText.visible = false; __doAnim = false; @@ -38,8 +40,8 @@ class CharterNoteHoverer extends CharterNote { switch (Charter.instance.gridActionType) { case NONE: super.draw(); - case DRAG: - if (Charter.instance.gridActionType == DRAG) { + case NOTE_DRAG: + if (Charter.instance.gridActionType == NOTE_DRAG) { var verticalChange:Float = (__mousePos.y - Charter.instance.dragStartPos.y) / 40; var horizontalChange:Int = CoolUtil.floorInt((__mousePos.x - (Std.int(Charter.instance.dragStartPos.x / 40) * 40)) / 40);