Merge pull request #237 from FunkinCrew/feature/chart-editor-metronome-slider

Metronome slider and scroll anchor
This commit is contained in:
Cameron Taylor 2023-12-07 18:10:02 -05:00 committed by GitHub
commit 90cf1edad1
6 changed files with 335 additions and 69 deletions

2
assets

@ -1 +1 @@
Subproject commit 830127dcc38e4f0fc35b162bd0f696a77679b046 Subproject commit d063a6c6a0fd05df02ed04456203b5d7e71e3de8

View file

@ -49,7 +49,7 @@
"name": "haxeui-core", "name": "haxeui-core",
"type": "git", "type": "git",
"dir": null, "dir": null,
"ref": "91ed8d7867c52af5ea2a9513204057d69ab33c8e", "ref": "5d4ac180f85b39e72624f4b8d17925d91ebe4278",
"url": "https://github.com/haxeui/haxeui-core" "url": "https://github.com/haxeui/haxeui-core"
}, },
{ {

View file

@ -142,12 +142,14 @@ class Cursor
}; };
static var assetCursorCell:Null<BitmapData> = null; static var assetCursorCell:Null<BitmapData> = null;
// DESIRED CURSOR: Resize NS (vertical) public static final CURSOR_SCROLL_PARAMS:CursorParams =
// DESIRED CURSOR: Resize EW (horizontal) {
// DESIRED CURSOR: Resize NESW (diagonal) graphic: "assets/images/cursor/cursor-scroll.png",
// DESIRED CURSOR: Resize NWSE (diagonal) scale: 0.2,
// DESIRED CURSOR: Help (Cursor with question mark) offsetX: -15,
// DESIRED CURSOR: Menu (Cursor with menu icon) offsetY: -15,
};
static var assetCursorScroll:Null<BitmapData> = null;
static function set_cursorMode(value:Null<CursorMode>):Null<CursorMode> static function set_cursorMode(value:Null<CursorMode>):Null<CursorMode>
{ {
@ -304,6 +306,18 @@ class Cursor
applyCursorParams(assetCursorCell, CURSOR_CELL_PARAMS); applyCursorParams(assetCursorCell, CURSOR_CELL_PARAMS);
} }
case Scroll:
if (assetCursorScroll == null)
{
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_SCROLL_PARAMS.graphic);
assetCursorScroll = bitmapData;
applyCursorParams(assetCursorScroll, CURSOR_SCROLL_PARAMS);
}
else
{
applyCursorParams(assetCursorScroll, CURSOR_SCROLL_PARAMS);
}
default: default:
setCursorGraphic(null); setCursorGraphic(null);
} }
@ -487,6 +501,21 @@ class Cursor
applyCursorParams(assetCursorCell, CURSOR_CELL_PARAMS); applyCursorParams(assetCursorCell, CURSOR_CELL_PARAMS);
} }
case Scroll:
if (assetCursorScroll == null)
{
var future:Future<BitmapData> = Assets.loadBitmapData(CURSOR_SCROLL_PARAMS.graphic);
future.onComplete(function(bitmapData:BitmapData) {
assetCursorScroll = bitmapData;
applyCursorParams(assetCursorScroll, CURSOR_SCROLL_PARAMS);
});
future.onError(onCursorError.bind(Scroll));
}
else
{
applyCursorParams(assetCursorScroll, CURSOR_SCROLL_PARAMS);
}
default: default:
loadCursorGraphic(null); loadCursorGraphic(null);
} }
@ -517,6 +546,7 @@ class Cursor
registerHaxeUICursor('zoom-out', CURSOR_ZOOM_OUT_PARAMS); registerHaxeUICursor('zoom-out', CURSOR_ZOOM_OUT_PARAMS);
registerHaxeUICursor('crosshair', CURSOR_CROSSHAIR_PARAMS); registerHaxeUICursor('crosshair', CURSOR_CROSSHAIR_PARAMS);
registerHaxeUICursor('cell', CURSOR_CELL_PARAMS); registerHaxeUICursor('cell', CURSOR_CELL_PARAMS);
registerHaxeUICursor('scroll', CURSOR_SCROLL_PARAMS);
} }
public static function registerHaxeUICursor(id:String, params:CursorParams):Void public static function registerHaxeUICursor(id:String, params:CursorParams):Void
@ -539,6 +569,7 @@ enum CursorMode
ZoomOut; ZoomOut;
Crosshair; Crosshair;
Cell; Cell;
Scroll;
} }
/** /**

View file

@ -105,7 +105,7 @@ abstract Save(RawSaveData)
theme: ChartEditorTheme.Light, theme: ChartEditorTheme.Light,
playtestStartTime: false, playtestStartTime: false,
downscroll: false, downscroll: false,
metronomeEnabled: true, metronomeVolume: 1.0,
hitsoundsEnabledPlayer: true, hitsoundsEnabledPlayer: true,
hitsoundsEnabledOpponent: true, hitsoundsEnabledOpponent: true,
instVolume: 1.0, instVolume: 1.0,
@ -279,21 +279,38 @@ abstract Save(RawSaveData)
return this.optionsChartEditor.theme; return this.optionsChartEditor.theme;
} }
public var chartEditorMetronomeEnabled(get, set):Bool; public var chartEditorMetronomeVolume(get, set):Float;
function get_chartEditorMetronomeEnabled():Bool function get_chartEditorMetronomeVolume():Float
{ {
if (this.optionsChartEditor.metronomeEnabled == null) this.optionsChartEditor.metronomeEnabled = true; if (this.optionsChartEditor.metronomeVolume == null) this.optionsChartEditor.metronomeVolume = 1.0;
return this.optionsChartEditor.metronomeEnabled; return this.optionsChartEditor.metronomeVolume;
} }
function set_chartEditorMetronomeEnabled(value:Bool):Bool function set_chartEditorMetronomeVolume(value:Float):Float
{ {
// Set and apply. // Set and apply.
this.optionsChartEditor.metronomeEnabled = value; this.optionsChartEditor.metronomeVolume = value;
flush(); flush();
return this.optionsChartEditor.metronomeEnabled; return this.optionsChartEditor.metronomeVolume;
}
public var chartEditorHitsoundVolume(get, set):Float;
function get_chartEditorHitsoundVolume():Float
{
if (this.optionsChartEditor.hitsoundVolume == null) this.optionsChartEditor.hitsoundVolume = 1.0;
return this.optionsChartEditor.hitsoundVolume;
}
function set_chartEditorHitsoundVolume(value:Float):Float
{
// Set and apply.
this.optionsChartEditor.hitsoundVolume = value;
flush();
return this.optionsChartEditor.hitsoundVolume;
} }
public var chartEditorHitsoundsEnabledPlayer(get, set):Bool; public var chartEditorHitsoundsEnabledPlayer(get, set):Bool;
@ -981,10 +998,16 @@ typedef SaveDataChartEditorOptions =
var ?downscroll:Bool; var ?downscroll:Bool;
/** /**
* Metronome sounds in the Chart Editor. * Metronome volume in the Chart Editor.
* @default `true` * @default `1.0`
*/ */
var ?metronomeEnabled:Bool; var ?metronomeVolume:Float;
/**
* Hitsound volume in the Chart Editor.
* @default `1.0`
*/
var ?hitsoundVolume:Float;
/** /**
* If true, playtest songs from the current position in the Chart Editor. * If true, playtest songs from the current position in the Chart Editor.

View file

@ -92,6 +92,7 @@ import haxe.ui.backend.flixel.UIRuntimeState;
import haxe.ui.backend.flixel.UIState; import haxe.ui.backend.flixel.UIState;
import haxe.ui.components.DropDown; import haxe.ui.components.DropDown;
import haxe.ui.components.Label; import haxe.ui.components.Label;
import haxe.ui.components.Button;
import haxe.ui.components.NumberStepper; import haxe.ui.components.NumberStepper;
import haxe.ui.components.Slider; import haxe.ui.components.Slider;
import haxe.ui.components.TextField; import haxe.ui.components.TextField;
@ -100,6 +101,7 @@ import haxe.ui.containers.Frame;
import haxe.ui.containers.menus.Menu; import haxe.ui.containers.menus.Menu;
import haxe.ui.containers.menus.MenuBar; import haxe.ui.containers.menus.MenuBar;
import haxe.ui.containers.menus.MenuItem; import haxe.ui.containers.menus.MenuItem;
import haxe.ui.containers.menus.MenuCheckBox;
import haxe.ui.containers.TreeView; import haxe.ui.containers.TreeView;
import haxe.ui.containers.TreeViewNode; import haxe.ui.containers.TreeViewNode;
import haxe.ui.core.Component; import haxe.ui.core.Component;
@ -603,9 +605,14 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Audio // Audio
/** /**
* Whether to play a metronome sound while the playhead is moving. * Whether to play a metronome sound while the playhead is moving, and what volume.
*/ */
var isMetronomeEnabled:Bool = true; var metronomeVolume:Float = 1.0;
/**
* The volume to play hitsounds at.
*/
var hitsoundVolume:Float = 1.0;
/** /**
* Whether hitsounds are enabled for the player. * Whether hitsounds are enabled for the player.
@ -653,6 +660,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
*/ */
var currentScrollEase:Null<VarTween>; var currentScrollEase:Null<VarTween>;
/**
* The position where the user middle clicked to place a scroll anchor.
* Scroll each frame with speed based on the distance between the mouse and the scroll anchor.
* `null` if no scroll anchor is present.
*/
var scrollAnchorScreenPos:Null<FlxPoint> = null;
// Note Placement // Note Placement
/** /**
@ -1230,98 +1244,257 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var playbarHeadLayout:Null<ChartEditorPlaybarHead> = null; var playbarHeadLayout:Null<ChartEditorPlaybarHead> = null;
// NOTE: All the components below are automatically assigned via HaxeUI macros. // NOTE: All the components below are automatically assigned via HaxeUI macros.
/** /**
* The menubar at the top of the screen. * The menubar at the top of the screen.
*/ */
// var menubar:MenuBar; var menubar:MenuBar;
/** /**
* The `File -> New Chart` menu item. * The `File -> New Chart` menu item.
*/ */
// var menubarItemNewChart:MenuItem; var menubarItemNewChart:MenuItem;
/** /**
* The `File -> Open Chart` menu item. * The `File -> Open Chart` menu item.
*/ */
// var menubarItemOpenChart:MenuItem; var menubarItemOpenChart:MenuItem;
/** /**
* The `File -> Open Recent` menu. * The `File -> Open Recent` menu.
*/ */
// var menubarOpenRecent:Menu; var menubarOpenRecent:Menu;
/** /**
* The `File -> Save Chart` menu item. * The `File -> Save Chart` menu item.
*/ */
// var menubarItemSaveChart:MenuItem; var menubarItemSaveChart:MenuItem;
/** /**
* The `File -> Save Chart As` menu item. * The `File -> Save Chart As` menu item.
*/ */
// var menubarItemSaveChartAs:MenuItem; var menubarItemSaveChartAs:MenuItem;
/** /**
* The `File -> Preferences` menu item. * The `File -> Preferences` menu item.
*/ */
// var menubarItemPreferences:MenuItem; var menubarItemPreferences:MenuItem;
/** /**
* The `File -> Exit` menu item. * The `File -> Exit` menu item.
*/ */
// var menubarItemExit:MenuItem; var menubarItemExit:MenuItem;
/** /**
* The `Edit -> Undo` menu item. * The `Edit -> Undo` menu item.
*/ */
// var menubarItemUndo:MenuItem; var menubarItemUndo:MenuItem;
/** /**
* The `Edit -> Redo` menu item. * The `Edit -> Redo` menu item.
*/ */
// var menubarItemRedo:MenuItem; var menubarItemRedo:MenuItem;
/** /**
* The `Edit -> Cut` menu item. * The `Edit -> Cut` menu item.
*/ */
// var menubarItemCut:MenuItem; var menubarItemCut:MenuItem;
/** /**
* The `Edit -> Copy` menu item. * The `Edit -> Copy` menu item.
*/ */
// var menubarItemCopy:MenuItem; var menubarItemCopy:MenuItem;
/** /**
* The `Edit -> Paste` menu item. * The `Edit -> Paste` menu item.
*/ */
// var menubarItemPaste:MenuItem; var menubarItemPaste:MenuItem;
/** /**
* The `Edit -> Paste Unsnapped` menu item. * The `Edit -> Paste Unsnapped` menu item.
*/ */
// var menubarItemPasteUnsnapped:MenuItem; var menubarItemPasteUnsnapped:MenuItem;
/** /**
* The `Edit -> Delete` menu item. * The `Edit -> Delete` menu item.
*/ */
// var menubarItemDelete:MenuItem; var menubarItemDelete:MenuItem;
/**
* The `Edit -> Flip Notes` menu item.
*/
var menubarItemFlipNotes:MenuItem;
/**
* The `Edit -> Select All` menu item.
*/
var menubarItemSelectAll:MenuItem;
/**
* The `Edit -> Select Inverse` menu item.
*/
var menubarItemSelectInverse:MenuItem;
/**
* The `Edit -> Select None` menu item.
*/
var menubarItemSelectNone:MenuItem;
/**
* The `Edit -> Select Region` menu item.
*/
var menubarItemSelectRegion:MenuItem;
/**
* The `Edit -> Select Before Cursor` menu item.
*/
var menubarItemSelectBeforeCursor:MenuItem;
/**
* The `Edit -> Select After Cursor` menu item.
*/
var menubarItemSelectAfterCursor:MenuItem;
/**
* The `Edit -> Decrease Note Snap Precision` menu item.
*/
var menuBarItemNoteSnapDecrease:MenuItem;
/**
* The `Edit -> Decrease Note Snap Precision` menu item.
*/
var menuBarItemNoteSnapIncrease:MenuItem;
/**
* The `View -> Downscroll` menu item.
*/
var menubarItemDownscroll:MenuCheckBox;
/**
* The `View -> Increase Difficulty` menu item.
*/
var menubarItemDifficultyUp:MenuItem;
/**
* The `View -> Decrease Difficulty` menu item.
*/
var menubarItemDifficultyDown:MenuItem;
/**
* The `Audio -> Play/Pause` menu item.
*/
var menubarItemPlayPause:MenuItem;
/**
* The `Audio -> Load Instrumental` menu item.
*/
var menubarItemLoadInstrumental:MenuItem;
/**
* The `Audio -> Load Vocals` menu item.
*/
var menubarItemLoadVocals:MenuItem;
/**
* The `Audio -> Metronome Volume` label.
*/
var menubarLabelVolumeMetronome:Label;
/**
* The `Audio -> Metronome Volume` slider.
*/
var menubarItemVolumeMetronome:Slider;
/**
* The `Audio -> Enable Player Hitsounds` menu checkbox.
*/
var menubarItemPlayerHitsounds:MenuCheckBox;
/**
* The `Audio -> Enable Opponent Hitsounds` menu checkbox.
*/
var menubarItemOpponentHitsounds:MenuCheckBox;
/**
* The `Audio -> Hitsound Volume` label.
*/
var menubarLabelVolumeHitsounds:Label;
/**
* The `Audio -> Hitsound Volume` slider.
*/
var menubarItemVolumeHitsounds:Slider;
/**
* The `Audio -> Instrumental Volume` label.
*/
var menubarLabelVolumeInstrumental:Label;
/**
* The `Audio -> Instrumental Volume` slider.
*/
var menubarItemVolumeInstrumental:Slider;
/**
* The `Audio -> Vocal Volume` label.
*/
var menubarLabelVolumeVocals:Label;
/**
* The `Audio -> Vocal Volume` slider.
*/
var menubarItemVolumeVocals:Slider;
/**
* The `Audio -> Playback Speed` label.
*/
var menubarLabelPlaybackSpeed:Label;
/**
* The `Audio -> Playback Speed` slider.
*/
var menubarItemPlaybackSpeed:Slider;
/** /**
* The label by the playbar telling the song position. * The label by the playbar telling the song position.
*/ */
// var playbarSongPos:Label; var playbarSongPos:Label;
/** /**
* The label by the playbar telling the song time remaining. * The label by the playbar telling the song time remaining.
*/ */
// var playbarSongRemaining:Label; var playbarSongRemaining:Label;
/** /**
* The label by the playbar telling the note snap. * The label by the playbar telling the note snap.
*/ */
// var playbarNoteSnap:Label; var playbarNoteSnap:Label;
/** /**
* The button by the playbar to jump to the start of the song. * The button by the playbar to jump to the start of the song.
*/ */
// var playbarStart:Button; var playbarStart:Button;
/** /**
* The button by the playbar to jump backwards in the song. * The button by the playbar to jump backwards in the song.
*/ */
// var playbarBack:Button; var playbarBack:Button;
/** /**
* The button by the playbar to play or pause the song. * The button by the playbar to play or pause the song.
*/ */
// var playbarPlay:Button; var playbarPlay:Button;
/** /**
* The button by the playbar to jump forwards in the song. * The button by the playbar to jump forwards in the song.
*/ */
// var playbarForward:Button; var playbarForward:Button;
/** /**
* The button by the playbar to jump to the end of the song. * The button by the playbar to jump to the end of the song.
*/ */
// var playbarEnd:Button; var playbarEnd:Button;
/** /**
* RENDER OBJECTS * RENDER OBJECTS
*/ */
@ -1659,7 +1832,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
isViewDownscroll = save.chartEditorDownscroll; isViewDownscroll = save.chartEditorDownscroll;
playtestStartTime = save.chartEditorPlaytestStartTime; playtestStartTime = save.chartEditorPlaytestStartTime;
currentTheme = save.chartEditorTheme; currentTheme = save.chartEditorTheme;
isMetronomeEnabled = save.chartEditorMetronomeEnabled; metronomeVolume = save.chartEditorMetronomeVolume;
hitsoundVolume = save.chartEditorHitsoundVolume;
hitsoundsEnabledPlayer = save.chartEditorHitsoundsEnabledPlayer; hitsoundsEnabledPlayer = save.chartEditorHitsoundsEnabledPlayer;
hitsoundsEnabledOpponent = save.chartEditorHitsoundsEnabledOpponent; hitsoundsEnabledOpponent = save.chartEditorHitsoundsEnabledOpponent;
@ -1687,7 +1861,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
save.chartEditorDownscroll = isViewDownscroll; save.chartEditorDownscroll = isViewDownscroll;
save.chartEditorPlaytestStartTime = playtestStartTime; save.chartEditorPlaytestStartTime = playtestStartTime;
save.chartEditorTheme = currentTheme; save.chartEditorTheme = currentTheme;
save.chartEditorMetronomeEnabled = isMetronomeEnabled; save.chartEditorMetronomeVolume = metronomeVolume;
save.chartEditorHitsoundVolume = hitsoundVolume;
save.chartEditorHitsoundsEnabledPlayer = hitsoundsEnabledPlayer; save.chartEditorHitsoundsEnabledPlayer = hitsoundsEnabledPlayer;
save.chartEditorHitsoundsEnabledOpponent = hitsoundsEnabledOpponent; save.chartEditorHitsoundsEnabledOpponent = hitsoundsEnabledOpponent;
@ -2254,8 +2429,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
menubarItemLoadInstrumental.onClick = _ -> this.openUploadInstDialog(true); menubarItemLoadInstrumental.onClick = _ -> this.openUploadInstDialog(true);
menubarItemLoadVocals.onClick = _ -> this.openUploadVocalsDialog(true); menubarItemLoadVocals.onClick = _ -> this.openUploadVocalsDialog(true);
menubarItemMetronomeEnabled.onChange = event -> isMetronomeEnabled = event.value; menubarItemVolumeMetronome.onChange = event -> {
menubarItemMetronomeEnabled.selected = isMetronomeEnabled; var volume:Float = (event?.value ?? 0) / 100.0;
metronomeVolume = volume;
menubarLabelVolumeMetronome.text = 'Metronome - ${Std.int(event.value)}%';
};
menubarItemVolumeMetronome.value = Std.int(metronomeVolume * 100);
menubarItemPlayerHitsounds.onChange = event -> hitsoundsEnabledPlayer = event.value; menubarItemPlayerHitsounds.onChange = event -> hitsoundsEnabledPlayer = event.value;
menubarItemPlayerHitsounds.selected = hitsoundsEnabledPlayer; menubarItemPlayerHitsounds.selected = hitsoundsEnabledPlayer;
@ -2263,6 +2442,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
menubarItemOpponentHitsounds.onChange = event -> hitsoundsEnabledOpponent = event.value; menubarItemOpponentHitsounds.onChange = event -> hitsoundsEnabledOpponent = event.value;
menubarItemOpponentHitsounds.selected = hitsoundsEnabledOpponent; menubarItemOpponentHitsounds.selected = hitsoundsEnabledOpponent;
menubarItemVolumeHitsound.onChange = event -> {
var volume:Float = (event?.value ?? 0) / 100.0;
hitsoundVolume = volume;
menubarLabelVolumeHitsound.text = 'Hitsound - ${Std.int(event.value)}%';
};
menubarItemVolumeHitsound.value = Std.int(hitsoundVolume * 100);
menubarItemVolumeInstrumental.onChange = event -> { menubarItemVolumeInstrumental.onChange = event -> {
var volume:Float = (event?.value ?? 0) / 100.0; var volume:Float = (event?.value ?? 0) / 100.0;
if (audioInstTrack != null) audioInstTrack.volume = volume; if (audioInstTrack != null) audioInstTrack.volume = volume;
@ -2471,7 +2657,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// dispatchEvent gets called here. // dispatchEvent gets called here.
if (!super.beatHit()) return false; if (!super.beatHit()) return false;
if (isMetronomeEnabled && this.subState == null && (audioInstTrack != null && audioInstTrack.playing)) if (metronomeVolume > 0.0 && this.subState == null && (audioInstTrack != null && audioInstTrack.playing))
{ {
playMetronomeTick(Conductor.currentBeat % 4 == 0); playMetronomeTick(Conductor.currentBeat % 4 == 0);
} }
@ -2512,7 +2698,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
{ {
if (audioInstTrack != null && audioInstTrack.playing) if (audioInstTrack != null && audioInstTrack.playing)
{ {
if (FlxG.mouse.pressedMiddle) 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!
@ -2912,6 +3098,21 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var shouldPause:Bool = false; // Whether to pause the song when scrolling. var shouldPause:Bool = false; // Whether to pause the song when scrolling.
var shouldEase:Bool = false; // Whether to ease the scroll. var shouldEase:Bool = false; // Whether to ease the scroll.
// Handle scroll anchor
if (scrollAnchorScreenPos != null)
{
var currentScreenPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
var distance = currentScreenPos - scrollAnchorScreenPos;
var verticalDistance = distance.y;
// How much scrolling should be done based on the distance of the cursor from the anchor.
final ANCHOR_SCROLL_SPEED = 0.2;
scrollAmount = ANCHOR_SCROLL_SPEED * verticalDistance;
shouldPause = true;
}
// Mouse Wheel = Scroll // Mouse Wheel = Scroll
if (FlxG.mouse.wheel != 0 && !FlxG.keys.pressed.CONTROL) if (FlxG.mouse.wheel != 0 && !FlxG.keys.pressed.CONTROL)
{ {
@ -2991,18 +3192,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
shouldPause = true; shouldPause = true;
} }
// Middle Mouse + Drag = Scroll but move the playhead the same amount.
if (FlxG.mouse.pressedMiddle)
{
if (FlxG.mouse.deltaY != 0)
{
// Scroll down by the amount dragged.
scrollAmount += -FlxG.mouse.deltaY;
// Move the playhead by the same amount in the other direction so it is stationary.
playheadAmount += FlxG.mouse.deltaY;
}
}
// SHIFT + Scroll = Scroll Fast // SHIFT + Scroll = Scroll Fast
if (FlxG.keys.pressed.SHIFT) if (FlxG.keys.pressed.SHIFT)
{ {
@ -3014,7 +3203,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
scrollAmount /= 10; scrollAmount /= 10;
} }
// ALT = Move playhead instead. // Alt + Drag = Scroll but move the playhead the same amount.
if (FlxG.keys.pressed.ALT) if (FlxG.keys.pressed.ALT)
{ {
playheadAmount = scrollAmount; playheadAmount = scrollAmount;
@ -3136,9 +3325,26 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var overlapsSelection:Bool = FlxG.mouse.overlaps(renderedSelectionSquares); var overlapsSelection:Bool = FlxG.mouse.overlaps(renderedSelectionSquares);
if (FlxG.mouse.justPressedMiddle)
{
if (scrollAnchorScreenPos == null)
{
scrollAnchorScreenPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
selectionBoxStartPos = null;
}
else
{
scrollAnchorScreenPos = null;
}
}
if (FlxG.mouse.justPressed) if (FlxG.mouse.justPressed)
{ {
if (gridPlayheadScrollArea != null && FlxG.mouse.overlaps(gridPlayheadScrollArea)) if (scrollAnchorScreenPos != null)
{
scrollAnchorScreenPos = null;
}
else if (gridPlayheadScrollArea != null && FlxG.mouse.overlaps(gridPlayheadScrollArea))
{ {
gridPlayheadScrollAreaPressed = true; gridPlayheadScrollAreaPressed = true;
} }
@ -3147,7 +3353,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Clicked note preview // Clicked note preview
notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
} }
else if (!overlapsGrid || overlapsSelectionBorder) else if (!isCursorOverHaxeUI && (!overlapsGrid || overlapsSelectionBorder))
{ {
selectionBoxStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); selectionBoxStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
// Drawing selection box. // Drawing selection box.
@ -3430,6 +3636,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
scrollPositionInPixels = clickedPosInPixels; scrollPositionInPixels = clickedPosInPixels;
moveSongToScrollPosition(); moveSongToScrollPosition();
} }
else if (scrollAnchorScreenPos != null)
{
// Cursor should be a scroll anchor.
targetCursorMode = Scroll;
}
else if (dragTargetNote != null || dragTargetEvent != null) else if (dragTargetNote != null || dragTargetEvent != null)
{ {
if (FlxG.mouse.justReleased) if (FlxG.mouse.justReleased)
@ -4514,7 +4725,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
*/ */
function playMetronomeTick(high:Bool = false):Void function playMetronomeTick(high:Bool = false):Void
{ {
this.playSound(Paths.sound('chartingSounds/metronome${high ? '1' : '2'}')); this.playSound(Paths.sound('chartingSounds/metronome${high ? '1' : '2'}'), metronomeVolume);
} }
function switchToCurrentInstrumental():Void function switchToCurrentInstrumental():Void
@ -5015,9 +5226,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
switch (noteData.getStrumlineIndex()) switch (noteData.getStrumlineIndex())
{ {
case 0: // Player case 0: // Player
if (hitsoundsEnabledPlayer) this.playSound(Paths.sound('chartingSounds/hitNotePlayer')); if (hitsoundsEnabledPlayer) this.playSound(Paths.sound('chartingSounds/hitNotePlayer'), hitsoundVolume);
case 1: // Opponent case 1: // Opponent
if (hitsoundsEnabledOpponent) this.playSound(Paths.sound('chartingSounds/hitNoteOpponent')); if (hitsoundsEnabledOpponent) this.playSound(Paths.sound('chartingSounds/hitNoteOpponent'), hitsoundVolume);
} }
} }
} }

View file

@ -202,7 +202,7 @@ class ChartEditorAudioHandler
* Automatically cleans up after itself and recycles previous FlxSound instances if available, for performance. * Automatically cleans up after itself and recycles previous FlxSound instances if available, for performance.
* @param path The path to the sound effect. Use `Paths` to build this. * @param path The path to the sound effect. Use `Paths` to build this.
*/ */
public static function playSound(_state:ChartEditorState, path:String):Void public static function playSound(_state:ChartEditorState, path:String, volume:Float = 1.0):Void
{ {
var snd:FlxSound = FlxG.sound.list.recycle(FlxSound) ?? new FlxSound(); var snd:FlxSound = FlxG.sound.list.recycle(FlxSound) ?? new FlxSound();
var asset:Null<FlxSoundAsset> = FlxG.sound.cache(path); var asset:Null<FlxSoundAsset> = FlxG.sound.cache(path);
@ -214,6 +214,7 @@ class ChartEditorAudioHandler
snd.loadEmbedded(asset); snd.loadEmbedded(asset);
snd.autoDestroy = true; snd.autoDestroy = true;
FlxG.sound.list.add(snd); FlxG.sound.list.add(snd);
snd.volume = volume;
snd.play(); snd.play();
} }