mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-14 19:25:16 -05:00
feat: Added smoother scrolling when using the Chart Editor
smoother drag / movement in chart editor playbarHead movement fixie
This commit is contained in:
parent
144ba00377
commit
20d9016984
1 changed files with 31 additions and 78 deletions
|
@ -94,6 +94,7 @@ import funkin.ui.mainmenu.MainMenuState;
|
||||||
import funkin.ui.transition.LoadingState;
|
import funkin.ui.transition.LoadingState;
|
||||||
import funkin.util.Constants;
|
import funkin.util.Constants;
|
||||||
import funkin.util.FileUtil;
|
import funkin.util.FileUtil;
|
||||||
|
import funkin.util.MathUtil;
|
||||||
import funkin.util.logging.CrashHandler;
|
import funkin.util.logging.CrashHandler;
|
||||||
import funkin.util.SortUtil;
|
import funkin.util.SortUtil;
|
||||||
import funkin.util.WindowUtil;
|
import funkin.util.WindowUtil;
|
||||||
|
@ -244,7 +245,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
/**
|
/**
|
||||||
* Duration, in seconds, for the scroll easing animation.
|
* Duration, in seconds, for the scroll easing animation.
|
||||||
*/
|
*/
|
||||||
public static final SCROLL_EASE_DURATION:Float = 0.2;
|
public static final SCROLL_EASE_DURATION:Float = 0.4;
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
||||||
|
@ -773,9 +774,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current process that is lerping the scroll position.
|
* The current process that is lerping the scroll position.
|
||||||
* Used to cancel the previous lerp if the user scrolls again.
|
|
||||||
*/
|
*/
|
||||||
var currentScrollEase:Null<VarTween>;
|
var currentScrollEase:Null<Float>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The position where the user middle clicked to place a scroll anchor.
|
* The position where the user middle clicked to place a scroll anchor.
|
||||||
|
@ -2707,6 +2707,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
playbarHeadLayout.playbarHead.width = FlxG.width;
|
playbarHeadLayout.playbarHead.width = FlxG.width;
|
||||||
playbarHeadLayout.playbarHead.height = 10;
|
playbarHeadLayout.playbarHead.height = 10;
|
||||||
playbarHeadLayout.playbarHead.styleString = 'padding-left: 0px; padding-right: 0px; border-left: 0px; border-right: 0px;';
|
playbarHeadLayout.playbarHead.styleString = 'padding-left: 0px; padding-right: 0px; border-left: 0px; border-right: 0px;';
|
||||||
|
playbarHeadLayout.playbarHead.min = 0;
|
||||||
|
|
||||||
playbarHeadLayout.playbarHead.onDragStart = function(_:DragEvent) {
|
playbarHeadLayout.playbarHead.onDragStart = function(_:DragEvent) {
|
||||||
playbarHeadDragging = true;
|
playbarHeadDragging = true;
|
||||||
|
@ -2723,13 +2724,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playbarHeadLayout.playbarHead.onDrag = function(_:DragEvent) {
|
playbarHeadLayout.playbarHead.onDrag = function(d:DragEvent) {
|
||||||
if (playbarHeadDragging)
|
if (playbarHeadDragging)
|
||||||
{
|
{
|
||||||
// Set the song position to where the playhead was moved to.
|
|
||||||
scrollPositionInPixels = (songLengthInPixels) * playbarHeadLayout.playbarHead.value / 100;
|
|
||||||
// Update the conductor and audio tracks to match.
|
// Update the conductor and audio tracks to match.
|
||||||
moveSongToScrollPosition();
|
currentScrollEase = d.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2740,6 +2739,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
if (playbarHeadDraggingWasPlaying)
|
if (playbarHeadDraggingWasPlaying)
|
||||||
{
|
{
|
||||||
playbarHeadDraggingWasPlaying = false;
|
playbarHeadDraggingWasPlaying = false;
|
||||||
|
|
||||||
// Disabled code to resume song playback on drag.
|
// Disabled code to resume song playback on drag.
|
||||||
// startAudioPlayback();
|
// startAudioPlayback();
|
||||||
}
|
}
|
||||||
|
@ -3417,10 +3417,14 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
audioInstTrack.time = -Conductor.instance.instrumentalOffset;
|
audioInstTrack.time = -Conductor.instance.instrumentalOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!audioInstTrack.isPlaying && currentScrollEase != scrollPositionInPixels) easeSongToScrollPosition(currentScrollEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioInstTrack != null && audioInstTrack.isPlaying)
|
if (audioInstTrack != null && audioInstTrack.isPlaying)
|
||||||
{
|
{
|
||||||
|
currentScrollEase = scrollPositionInPixels;
|
||||||
|
|
||||||
if (FlxG.keys.pressed.ALT)
|
if (FlxG.keys.pressed.ALT)
|
||||||
{
|
{
|
||||||
// If middle mouse panning during song playback, we move ONLY the playhead, without scrolling. Neat!
|
// If middle mouse panning during song playback, we move ONLY the playhead, without scrolling. Neat!
|
||||||
|
@ -4057,27 +4061,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
shouldPause = true;
|
shouldPause = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(scrollAmount) > GRID_SIZE * 8)
|
shouldEase = true;
|
||||||
{
|
if (shouldPause) stopAudioPlayback();
|
||||||
shouldEase = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resync the conductor and audio tracks.
|
// Resync the conductor and audio tracks.
|
||||||
if (scrollAmount != 0 || playheadAmount != 0)
|
if (playheadAmount != 0) this.playheadPositionInPixels += playheadAmount;
|
||||||
{
|
|
||||||
this.playheadPositionInPixels += playheadAmount;
|
if (scrollAmount != 0) currentScrollEase += scrollAmount;
|
||||||
if (shouldEase)
|
|
||||||
{
|
|
||||||
easeSongToScrollPosition(this.scrollPositionInPixels + scrollAmount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Apply the scroll amount.
|
|
||||||
this.scrollPositionInPixels += scrollAmount;
|
|
||||||
moveSongToScrollPosition();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (shouldPause) stopAudioPlayback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4333,15 +4323,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
{
|
{
|
||||||
// Scroll up.
|
// Scroll up.
|
||||||
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY;
|
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY;
|
||||||
scrollPositionInPixels -= diff * 0.5; // Too fast!
|
currentScrollEase -= diff * 0.5; // Too fast!
|
||||||
moveSongToScrollPosition();
|
|
||||||
}
|
}
|
||||||
else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0))
|
else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0))
|
||||||
{
|
{
|
||||||
// Scroll down.
|
// Scroll down.
|
||||||
var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0);
|
var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0);
|
||||||
scrollPositionInPixels += diff * 0.5; // Too fast!
|
currentScrollEase += (diff * 0.5); // Too fast!
|
||||||
moveSongToScrollPosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the selection box.
|
// Render the selection box.
|
||||||
|
@ -4480,8 +4468,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.viewY, (notePreview?.y ?? 0.0), (notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0),
|
var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.viewY, (notePreview?.y ?? 0.0), (notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0),
|
||||||
0, songLengthInPixels);
|
0, songLengthInPixels);
|
||||||
|
|
||||||
scrollPositionInPixels = clickedPosInPixels;
|
currentScrollEase = clickedPosInPixels;
|
||||||
moveSongToScrollPosition();
|
|
||||||
}
|
}
|
||||||
else if (scrollAnchorScreenPos != null)
|
else if (scrollAnchorScreenPos != null)
|
||||||
{
|
{
|
||||||
|
@ -4540,15 +4527,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
{
|
{
|
||||||
// Scroll up.
|
// Scroll up.
|
||||||
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY;
|
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY;
|
||||||
scrollPositionInPixels -= diff * 0.5; // Too fast!
|
currentScrollEase -= (diff * 0.5);
|
||||||
moveSongToScrollPosition();
|
|
||||||
}
|
}
|
||||||
else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0))
|
else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0))
|
||||||
{
|
{
|
||||||
// Scroll down.
|
// Scroll down.
|
||||||
var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0);
|
var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0);
|
||||||
scrollPositionInPixels += diff * 0.5; // Too fast!
|
currentScrollEase += (diff * 0.5);
|
||||||
moveSongToScrollPosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate distance between the position dragged to and the original position.
|
// Calculate distance between the position dragged to and the original position.
|
||||||
|
@ -5142,18 +5127,15 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
{
|
{
|
||||||
if (playbarHeadLayout == null) throw "ERROR: Tried to handle playbar, but playbarHeadLayout is null!";
|
if (playbarHeadLayout == null) throw "ERROR: Tried to handle playbar, but playbarHeadLayout is null!";
|
||||||
|
|
||||||
|
// Move the playhead to match the song position, if we aren't dragging it.
|
||||||
|
playbarHeadLayout.playbarHead.pos = currentScrollEase;
|
||||||
|
|
||||||
|
playbarHeadLayout.playbarHead.max = songLengthInPixels;
|
||||||
|
|
||||||
// Make sure the playbar is never nudged out of the correct spot.
|
// Make sure the playbar is never nudged out of the correct spot.
|
||||||
playbarHeadLayout.x = 4;
|
playbarHeadLayout.x = 4;
|
||||||
playbarHeadLayout.y = FlxG.height - 48 - 8;
|
playbarHeadLayout.y = FlxG.height - 48 - 8;
|
||||||
|
|
||||||
// Move the playhead to match the song position, if we aren't dragging it.
|
|
||||||
if (!playbarHeadDragging)
|
|
||||||
{
|
|
||||||
var songPosPercent = scrollPositionInPixels / (songLengthInPixels) * 100;
|
|
||||||
|
|
||||||
if (playbarHeadLayout.playbarHead.value != songPosPercent) playbarHeadLayout.playbarHead.value = songPosPercent;
|
|
||||||
}
|
|
||||||
|
|
||||||
var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
|
var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
|
||||||
var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2).substr(0, 2);
|
var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2).substr(0, 2);
|
||||||
var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2);
|
var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2);
|
||||||
|
@ -6134,43 +6116,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
*/
|
*/
|
||||||
function easeSongToScrollPosition(targetScrollPosition:Float):Void
|
function easeSongToScrollPosition(targetScrollPosition:Float):Void
|
||||||
{
|
{
|
||||||
if (currentScrollEase != null) cancelScrollEase(currentScrollEase);
|
currentScrollEase = Math.max(0, targetScrollPosition);
|
||||||
|
currentScrollEase = Math.min(currentScrollEase, songLengthInPixels);
|
||||||
currentScrollEase = FlxTween.tween(this, {scrollPositionInPixels: targetScrollPosition}, SCROLL_EASE_DURATION,
|
scrollPositionInPixels = MathUtil.smoothLerp(scrollPositionInPixels, currentScrollEase, FlxG.elapsed, SCROLL_EASE_DURATION, 1 / 1000);
|
||||||
{
|
|
||||||
ease: FlxEase.quintInOut,
|
|
||||||
onUpdate: this.onScrollEaseUpdate,
|
|
||||||
onComplete: this.cancelScrollEase,
|
|
||||||
type: ONESHOT
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback function executed every frame that the scroll position is being eased.
|
|
||||||
* @param _
|
|
||||||
*/
|
|
||||||
function onScrollEaseUpdate(_:FlxTween):Void
|
|
||||||
{
|
|
||||||
moveSongToScrollPosition();
|
moveSongToScrollPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback function executed when cancelling an existing scroll position ease.
|
|
||||||
* Ensures that the ease is immediately cancelled and the scroll position is set to the target value.
|
|
||||||
*/
|
|
||||||
function cancelScrollEase(_:FlxTween):Void
|
|
||||||
{
|
|
||||||
if (currentScrollEase != null)
|
|
||||||
{
|
|
||||||
@:privateAccess
|
|
||||||
var targetScrollPosition:Float = currentScrollEase._properties.scrollPositionInPixels;
|
|
||||||
|
|
||||||
currentScrollEase.cancel();
|
|
||||||
currentScrollEase = null;
|
|
||||||
this.scrollPositionInPixels = targetScrollPosition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fix the current scroll position after exiting the PlayState used when testing.
|
* Fix the current scroll position after exiting the PlayState used when testing.
|
||||||
*/
|
*/
|
||||||
|
@ -6351,6 +6302,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
{
|
{
|
||||||
if (audioInstTrack == null) return;
|
if (audioInstTrack == null) return;
|
||||||
|
|
||||||
|
currentScrollEase = this.scrollPositionInPixels;
|
||||||
|
|
||||||
if (audioInstTrack.isPlaying)
|
if (audioInstTrack.isPlaying)
|
||||||
{
|
{
|
||||||
// Pause
|
// Pause
|
||||||
|
|
Loading…
Reference in a new issue