FIX MEASURE TICKS GRAAAAAAAAAAAHH!!!!!!
This commit is contained in:
@@ -608,6 +608,7 @@ class Conductor
|
||||
else
|
||||
{
|
||||
var resultMeasureTime:Float = 0;
|
||||
ms = ms < 0 ? 0 : ms;
|
||||
|
||||
var lastTimeChange:SongTimeChange = timeChanges[0];
|
||||
var i:Int = -1;
|
||||
@@ -654,6 +655,7 @@ class Conductor
|
||||
else
|
||||
{
|
||||
var resultMs:Float = 0;
|
||||
measureTime = measureTime < 0 ? 0 : measureTime;
|
||||
|
||||
var lastTimeChange:SongTimeChange = timeChanges[0];
|
||||
var i:Int = -1;
|
||||
@@ -701,6 +703,7 @@ class Conductor
|
||||
else
|
||||
{
|
||||
var resultStep:Float = 0;
|
||||
ms = ms < 0 ? 0 : ms;
|
||||
|
||||
var lastTimeChange:SongTimeChange = timeChanges[0];
|
||||
var i:Int = -1;
|
||||
@@ -744,6 +747,7 @@ class Conductor
|
||||
else
|
||||
{
|
||||
var resultMs:Float = 0;
|
||||
stepTime = stepTime < 0 ? 0 : stepTime;
|
||||
|
||||
var lastTimeChange:SongTimeChange = timeChanges[0];
|
||||
var i:Int = -1;
|
||||
@@ -809,6 +813,30 @@ class Conductor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a time in milliseconds, return the time change that time is inside of.
|
||||
* @param ms The time in milliseconds.
|
||||
* @return The resulting time change.
|
||||
*/
|
||||
public function getTimeChange(ms:Float):SongTimeChange
|
||||
{
|
||||
if (timeChanges.length == 0)
|
||||
{
|
||||
return new SongTimeChange(0, 100);
|
||||
}
|
||||
var i:Int = 0;
|
||||
ms = ms < 0 ? 0 : ms;
|
||||
for (timeChange in timeChanges)
|
||||
{
|
||||
i++;
|
||||
if ((i == timeChanges.length && ms >= timeChange.timeStamp) || (ms >= timeChange.timeStamp && ms < timeChanges[i].timeStamp))
|
||||
{
|
||||
return timeChange;
|
||||
}
|
||||
}
|
||||
return new SongTimeChange(0, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Conductor fields to the Flixel debugger variable display.
|
||||
* @param conductorToUse The conductor to use. Defaults to `Conductor.instance`.
|
||||
|
||||
@@ -179,12 +179,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
/**
|
||||
* The height of the note selection buttons above the grid.
|
||||
*/
|
||||
public static final NOTE_SELECT_BUTTON_HEIGHT:Int = 24;
|
||||
public static final NOTE_SELECT_BUTTON_HEIGHT:Int = 32;
|
||||
|
||||
/**
|
||||
* The amount of padding between the menu bar and the chart grid when fully scrolled up.
|
||||
*/
|
||||
public static final GRID_TOP_PAD:Int = NOTE_SELECT_BUTTON_HEIGHT + 12;
|
||||
public static final GRID_TOP_PAD:Int = NOTE_SELECT_BUTTON_HEIGHT + 4;
|
||||
|
||||
/**
|
||||
* The initial vertical position of the chart grid.
|
||||
@@ -199,7 +199,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
/**
|
||||
* The Y position of the note preview area.
|
||||
*/
|
||||
public static final NOTE_PREVIEW_Y_POS:Int = GRID_INITIAL_Y_POS - NOTE_SELECT_BUTTON_HEIGHT - 4;
|
||||
public static final NOTE_PREVIEW_Y_POS:Int = GRID_INITIAL_Y_POS - NOTE_SELECT_BUTTON_HEIGHT + 4;
|
||||
|
||||
/**
|
||||
* The X position of the note grid.
|
||||
@@ -410,8 +410,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
setNotePreviewViewportBounds(calculateNotePreviewViewportBounds());
|
||||
refreshNotePreviewPlayheadPosition();
|
||||
|
||||
// Update the measure tick display.
|
||||
if (measureTicks != null) measureTicks.y = gridTiledSprite?.y ?? 0.0;
|
||||
if (measureTicks != null) handleMeasureTickPosition();
|
||||
return this.scrollPositionInPixels;
|
||||
}
|
||||
|
||||
@@ -2064,6 +2063,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
*/
|
||||
var playbarEnd:Button;
|
||||
|
||||
/**
|
||||
* The button above the grid that does nothing currently. Used for covering up the measure ticks being cut off :)
|
||||
* Constructed manually and added to the layout so we can control its position.
|
||||
*/
|
||||
var buttonSelectDummy:Button;
|
||||
|
||||
/**
|
||||
* The button above the grid that selects all notes on the opponent's side.
|
||||
* Constructed manually and added to the layout so we can control its position.
|
||||
@@ -2889,7 +2894,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
buttonSelectOpponent.allowFocus = false;
|
||||
buttonSelectOpponent.text = "Opponent"; // Default text.
|
||||
buttonSelectOpponent.x = GRID_X_POS;
|
||||
buttonSelectOpponent.y = GRID_INITIAL_Y_POS - NOTE_SELECT_BUTTON_HEIGHT - 8;
|
||||
buttonSelectOpponent.y = GRID_INITIAL_Y_POS - NOTE_SELECT_BUTTON_HEIGHT;
|
||||
buttonSelectOpponent.width = GRID_SIZE * 4;
|
||||
buttonSelectOpponent.height = NOTE_SELECT_BUTTON_HEIGHT;
|
||||
buttonSelectOpponent.tooltip = "Click to set selection to all notes on this side.\nShift-click to add all notes on this side to selection.";
|
||||
@@ -2955,6 +2960,15 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
performCommand(new SetItemSelectionCommand([], currentSongChartEventData));
|
||||
}
|
||||
}
|
||||
|
||||
buttonSelectDummy = new Button();
|
||||
buttonSelectDummy.allowFocus = false;
|
||||
buttonSelectDummy.x = buttonSelectOpponent.x - GRID_SIZE;
|
||||
buttonSelectDummy.y = buttonSelectEvent.y;
|
||||
buttonSelectDummy.width = GRID_SIZE;
|
||||
buttonSelectDummy.height = NOTE_SELECT_BUTTON_HEIGHT;
|
||||
buttonSelectDummy.zIndex = 110;
|
||||
add(buttonSelectDummy);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4373,13 +4387,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
}
|
||||
}
|
||||
|
||||
// An odd way to fix this since measureTicks contains more than just the gray sidebar now.
|
||||
var gridPlayheadScrollArea:FlxRect = FlxRect.weak(measureTicks?.x ?? -100, MENU_BAR_HEIGHT + GRID_TOP_PAD, GRID_SIZE, 597);
|
||||
|
||||
if (FlxG.mouse.justPressed)
|
||||
{
|
||||
if (scrollAnchorScreenPos != null)
|
||||
{
|
||||
scrollAnchorScreenPos = null;
|
||||
}
|
||||
else if (measureTicks != null && FlxG.mouse.overlaps(measureTicks) && !isCursorOverHaxeUI)
|
||||
else if (measureTicks != null && gridPlayheadScrollArea.containsXY(FlxG.mouse.viewX, FlxG.mouse.viewY) && !isCursorOverHaxeUI)
|
||||
{
|
||||
gridPlayheadScrollAreaPressed = true;
|
||||
// Stop audio playback while dragging on the grid playhead.
|
||||
@@ -5671,7 +5688,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
var xOffset = 45 - (healthIconBF.width / 2);
|
||||
healthIconBF.x = (gridTiledSprite == null) ? (0) : (GRID_X_POS + gridTiledSprite.width + xOffset);
|
||||
var yOffset = 30 - (healthIconBF.height / 2);
|
||||
healthIconBF.y = (gridTiledSprite == null) ? (0) : (GRID_INITIAL_Y_POS - NOTE_SELECT_BUTTON_HEIGHT) + yOffset;
|
||||
healthIconBF.y = (gridTiledSprite == null) ? (0) : (GRID_INITIAL_Y_POS - NOTE_SELECT_BUTTON_HEIGHT + 8) + yOffset;
|
||||
}
|
||||
|
||||
// Visibly center the Dad health icon.
|
||||
@@ -5680,7 +5697,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
var xOffset = 75 + (healthIconDad.width / 2);
|
||||
healthIconDad.x = (gridTiledSprite == null) ? (0) : (GRID_X_POS - xOffset);
|
||||
var yOffset = 30 - (healthIconDad.height / 2);
|
||||
healthIconDad.y = (gridTiledSprite == null) ? (0) : (GRID_INITIAL_Y_POS - NOTE_SELECT_BUTTON_HEIGHT) + yOffset;
|
||||
healthIconDad.y = (gridTiledSprite == null) ? (0) : (GRID_INITIAL_Y_POS - NOTE_SELECT_BUTTON_HEIGHT + 8) + yOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6295,10 +6312,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
{
|
||||
gridTiledSprite.height = songLengthInPixels;
|
||||
}
|
||||
if (measureTicks != null)
|
||||
{
|
||||
measureTicks.setHeight(songLengthInPixels);
|
||||
}
|
||||
|
||||
// Remove any notes past the end of the song.
|
||||
var songCutoffPointSteps:Float = songLengthInSteps - 0.1;
|
||||
@@ -6586,11 +6599,50 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Conductor instance and checkes for time signature changes.
|
||||
*/
|
||||
function updateSongTime():Void
|
||||
{
|
||||
var oldTimeSignatureNum:Int = Conductor.instance.timeSignatureNumerator;
|
||||
var oldTimeSignatureDen:Int = Conductor.instance.timeSignatureDenominator;
|
||||
Conductor.instance.update(audioInstTrack.time);
|
||||
if (Conductor.instance.timeSignatureNumerator != oldTimeSignatureNum
|
||||
|| Conductor.instance.timeSignatureDenominator != oldTimeSignatureDen)
|
||||
{
|
||||
updateTimeSignature();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the measure tick bitmap forcibly to make sure it's correct.
|
||||
*/
|
||||
function updateTimeSignature():Void
|
||||
{
|
||||
this.updateTheme();
|
||||
this.updateMeasureTicks(true);
|
||||
gridTiledSprite.loadGraphic(gridBitmap);
|
||||
measureTicks.reloadTickBitmap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle positioning the measure ticks sprite.
|
||||
*/
|
||||
function handleMeasureTickPosition():Void
|
||||
{
|
||||
this.updateMeasureTicks();
|
||||
var currentMeasureTime = Conductor.instance.getMeasureTimeInMs(Math.floor(Conductor.instance.getTimeInMeasures(scrollPositionInMs)));
|
||||
var currentMeasurePos = currentMeasureTime < 0 ? 0 : Conductor.instance.getTimeInSteps(currentMeasureTime) * GRID_SIZE;
|
||||
measureTicks.y = gridTiledSprite?.y + currentMeasurePos;
|
||||
// Make sure the measure tick bitmap does not past the grid itself.
|
||||
var totalMeasureTicksHeight:Float = currentMeasurePos + measureTickBitmap.height;
|
||||
if (totalMeasureTicksHeight >= songLengthInPixels)
|
||||
{
|
||||
var spillOver:Float = totalMeasureTicksHeight - songLengthInPixels;
|
||||
measureTicks.setClipRect(new FlxRect(0, 0, measureTickBitmap.width, measureTickBitmap.height - spillOver));
|
||||
}
|
||||
else
|
||||
{
|
||||
measureTicks.setClipRect(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6706,18 +6758,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
}
|
||||
}
|
||||
|
||||
function updateSongTime():Void
|
||||
{
|
||||
var oldTimeSignatureNum:Int = Conductor.instance.timeSignatureNumerator;
|
||||
var oldTimeSignatureDen:Int = Conductor.instance.timeSignatureDenominator;
|
||||
Conductor.instance.update(audioInstTrack.time);
|
||||
if (Conductor.instance.timeSignatureNumerator != oldTimeSignatureNum
|
||||
|| Conductor.instance.timeSignatureDenominator != oldTimeSignatureDen)
|
||||
{
|
||||
updateTimeSignature();
|
||||
}
|
||||
}
|
||||
|
||||
function stopAudioPlayback():Void
|
||||
{
|
||||
if (audioInstTrack != null) audioInstTrack.pause();
|
||||
|
||||
@@ -55,6 +55,7 @@ class AddNewTimeChangeCommand implements ChartEditorCommand
|
||||
|
||||
state.updateSongTime(); // basically will update the time signature for the editor if necessary.
|
||||
state.updateGridHeight();
|
||||
state.updateTimeSignature();
|
||||
}
|
||||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
@@ -79,6 +80,7 @@ class AddNewTimeChangeCommand implements ChartEditorCommand
|
||||
|
||||
state.updateSongTime();
|
||||
state.updateGridHeight();
|
||||
state.updateTimeSignature();
|
||||
}
|
||||
|
||||
public function shouldAddToHistory(state:ChartEditorState):Bool
|
||||
|
||||
@@ -73,6 +73,7 @@ class ModifyTimeChangeCommand implements ChartEditorCommand
|
||||
|
||||
state.updateSongTime();
|
||||
state.updateGridHeight();
|
||||
state.updateTimeSignature();
|
||||
}
|
||||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
@@ -105,6 +106,7 @@ class ModifyTimeChangeCommand implements ChartEditorCommand
|
||||
|
||||
state.updateSongTime();
|
||||
state.updateGridHeight();
|
||||
state.updateTimeSignature();
|
||||
}
|
||||
|
||||
public function shouldAddToHistory(state:ChartEditorState):Bool
|
||||
@@ -118,7 +120,6 @@ class ModifyTimeChangeCommand implements ChartEditorCommand
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
return
|
||||
'TimeChange ${timeChangeIndex}: ${targetTimeStamp} : BPM: ${targetBPM} in ${targetNumerator}/${targetDenominator}';
|
||||
return 'TimeChange ${timeChangeIndex}: ${targetTimeStamp} : BPM: ${targetBPM} in ${targetNumerator}/${targetDenominator}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class RemoveTimeChangeCommand implements ChartEditorCommand
|
||||
}
|
||||
else
|
||||
{
|
||||
removedTimeChange = timeChanges.splice(timeChangeIndex , 1);
|
||||
removedTimeChange = timeChanges.splice(timeChangeIndex, 1);
|
||||
}
|
||||
|
||||
state.currentSongMetadata.timeChanges = timeChanges;
|
||||
@@ -48,6 +48,7 @@ class RemoveTimeChangeCommand implements ChartEditorCommand
|
||||
|
||||
state.updateSongTime();
|
||||
state.updateGridHeight();
|
||||
state.updateTimeSignature();
|
||||
}
|
||||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
@@ -71,6 +72,7 @@ class RemoveTimeChangeCommand implements ChartEditorCommand
|
||||
|
||||
state.updateSongTime();
|
||||
state.updateGridHeight();
|
||||
state.updateTimeSignature();
|
||||
}
|
||||
|
||||
public function shouldAddToHistory(state:ChartEditorState):Bool
|
||||
@@ -81,7 +83,8 @@ class RemoveTimeChangeCommand implements ChartEditorCommand
|
||||
public function toString():String
|
||||
{
|
||||
if (removedTimeChange != null && removedTimeChange.length > 0) return
|
||||
'TimeChange ${timeChangeIndex} : ${removedTimeChange[0].timeStamp} : BPM: ${removedTimeChange[0].bpm} in ${removedTimeChange[0].timeSignatureNum}/${removedTimeChange[0].timeSignatureDen} removed'
|
||||
else return 'huh?';
|
||||
'TimeChange ${timeChangeIndex} : ${removedTimeChange[0].timeStamp} : BPM: ${removedTimeChange[0].bpm} in ${removedTimeChange[0].timeSignatureNum}/${removedTimeChange[0].timeSignatureDen} removed'
|
||||
else
|
||||
return 'huh?';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package funkin.ui.debug.charting.components;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.display.FlxTiledSprite;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
@@ -11,9 +11,11 @@ class ChartEditorMeasureTicks extends FlxTypedSpriteGroup<FlxSprite>
|
||||
{
|
||||
var chartEditorState:ChartEditorState;
|
||||
|
||||
var tickTiledSprite:FlxTiledSprite;
|
||||
var measureTicksSprite:FlxSprite;
|
||||
var measureNumbers:Array<FlxText> = [];
|
||||
|
||||
public var measureLengthsInPixels:Array<Int> = [];
|
||||
|
||||
override function set_y(value:Float):Float
|
||||
{
|
||||
var result = super.set_y(value);
|
||||
@@ -29,8 +31,8 @@ class ChartEditorMeasureTicks extends FlxTypedSpriteGroup<FlxSprite>
|
||||
|
||||
this.chartEditorState = chartEditorState;
|
||||
|
||||
tickTiledSprite = new FlxTiledSprite(chartEditorState.measureTickBitmap, chartEditorState.measureTickBitmap.width, 1000, false, true);
|
||||
add(tickTiledSprite);
|
||||
measureTicksSprite = new FlxSprite(0, 0);
|
||||
add(measureTicksSprite);
|
||||
|
||||
for (i in 0...5)
|
||||
{
|
||||
@@ -45,40 +47,39 @@ class ChartEditorMeasureTicks extends FlxTypedSpriteGroup<FlxSprite>
|
||||
|
||||
public function reloadTickBitmap():Void
|
||||
{
|
||||
tickTiledSprite.loadGraphic(chartEditorState.measureTickBitmap);
|
||||
measureTicksSprite.loadGraphic(chartEditorState.measureTickBitmap);
|
||||
}
|
||||
|
||||
public function setClipRect(rect:Null<FlxRect>):Void
|
||||
{
|
||||
measureTicksSprite.clipRect = rect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all 5 measure numbers, since that's the most we can really see at a time, even if barely.
|
||||
* Please excuse the horror you're about to witness.
|
||||
* Welp, you gotta go back in commits to see it now.
|
||||
*/
|
||||
function updateMeasureNumber()
|
||||
{
|
||||
var currentPixelScrollPositionInMs = Conductor.instance?.getStepTimeInMs((this.chartEditorState?.scrollPositionInPixels + 1) / ChartEditorState.GRID_SIZE);
|
||||
var measureNumberInViewport = Math.floor(Conductor.instance?.getTimeInMeasures(currentPixelScrollPositionInMs));
|
||||
if (measureLengthsInPixels.length == 0 || measureLengthsInPixels == null) return;
|
||||
|
||||
var currentMeasure:Int = Math.floor(Conductor.instance?.getTimeInMeasures(chartEditorState.scrollPositionInMs));
|
||||
for (i in 0...measureNumbers.length)
|
||||
{
|
||||
var measureNumber:FlxText = measureNumbers[i];
|
||||
if (measureNumber == null) continue;
|
||||
|
||||
var measureNumberPosition = Math.floor(Conductor.instance?.getTimeInSteps(Conductor.instance?.getMeasureTimeInMs(measureNumberInViewport +
|
||||
i)) * ChartEditorState.GRID_SIZE);
|
||||
|
||||
measureNumber.y = measureNumberPosition + this.y;
|
||||
var measureNumberPosition = measureLengthsInPixels[i];
|
||||
measureNumber.y = this.y + measureNumberPosition;
|
||||
|
||||
// Show the measure number only if it isn't beneath the end of the note grid.
|
||||
// Using measureNumber + 1 because the cut-off bar at the bottom is technically a bar, but it looks bad if a measure number shows up there.
|
||||
var fixedMeasureNumberValue = measureNumberInViewport + i + 1;
|
||||
var fixedMeasureNumberValue = currentMeasure + i + 1;
|
||||
if (fixedMeasureNumberValue < Math.ceil(Conductor.instance?.getTimeInMeasures(chartEditorState.songLengthInMs)))
|
||||
measureNumber.text = '${fixedMeasureNumberValue}';
|
||||
else
|
||||
measureNumber.text = '';
|
||||
}
|
||||
}
|
||||
|
||||
public function setHeight(songLengthInPixels:Float):Void
|
||||
{
|
||||
tickTiledSprite.height = songLengthInPixels;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import flixel.addons.display.FlxSliceSprite;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.data.song.SongData.SongTimeChange;
|
||||
import funkin.ui.debug.charting.ChartEditorState.ChartEditorTheme;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.geom.Rectangle;
|
||||
@@ -73,6 +74,9 @@ class ChartEditorThemeHandler
|
||||
|
||||
static final TOTAL_COLUMN_COUNT:Int = ChartEditorState.STRUMLINE_SIZE * 2 + 1;
|
||||
|
||||
// Used for checking in updateMeasureTicks() so we don't have to redraw it everytime if the current measure is the same as before.
|
||||
static var previousMeasure:Int = -69;
|
||||
|
||||
/**
|
||||
* When the theme is changed, this function updates all of the UI elements to match the new theme.
|
||||
* @param state The ChartEditorState to update.
|
||||
@@ -174,58 +178,6 @@ class ChartEditorThemeHandler
|
||||
ChartEditorState.GRID_SELECTION_BORDER_WIDTH, state.gridBitmap.height),
|
||||
selectionBorderColor);
|
||||
|
||||
// Draw horizontal dividers between the measures.
|
||||
|
||||
var gridMeasureDividerColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: GRID_MEASURE_DIVIDER_COLOR_LIGHT;
|
||||
case Dark: GRID_MEASURE_DIVIDER_COLOR_DARK;
|
||||
default: GRID_MEASURE_DIVIDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
// Divider at top
|
||||
state.gridBitmap.fillRect(new Rectangle(0, 0, state.gridBitmap.width, GRID_MEASURE_DIVIDER_WIDTH / 2), gridMeasureDividerColor);
|
||||
// Divider at bottom
|
||||
var dividerLineBY:Float = state.gridBitmap.height - (GRID_MEASURE_DIVIDER_WIDTH / 2);
|
||||
state.gridBitmap.fillRect(new Rectangle(0, dividerLineBY, state.gridBitmap.width, GRID_MEASURE_DIVIDER_WIDTH / 2), gridMeasureDividerColor);
|
||||
|
||||
// Draw horizontal dividers between the beats.
|
||||
|
||||
var gridBeatDividerColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: GRID_BEAT_DIVIDER_COLOR_LIGHT;
|
||||
case Dark: GRID_BEAT_DIVIDER_COLOR_DARK;
|
||||
default: GRID_BEAT_DIVIDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
// Selection borders horizontally in the middle.
|
||||
for (i in 1...(Conductor.instance.stepsPerMeasure))
|
||||
{
|
||||
// There may be a different number of beats per measure, but there's always 4 steps per beat.
|
||||
if ((i % Constants.STEPS_PER_BEAT) == 0)
|
||||
{
|
||||
state.gridBitmap.fillRect(new Rectangle(0, (ChartEditorState.GRID_SIZE * i) - (GRID_BEAT_DIVIDER_WIDTH / 2), state.gridBitmap.width,
|
||||
GRID_BEAT_DIVIDER_WIDTH),
|
||||
gridBeatDividerColor);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw vertical dividers between the strumlines.
|
||||
|
||||
var gridStrumlineDividerColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: GRID_STRUMLINE_DIVIDER_COLOR_LIGHT;
|
||||
case Dark: GRID_STRUMLINE_DIVIDER_COLOR_DARK;
|
||||
default: GRID_STRUMLINE_DIVIDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
// Divider at 1 * (Strumline Size)
|
||||
var dividerLineAX:Float = ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE) - (GRID_STRUMLINE_DIVIDER_WIDTH / 2);
|
||||
state.gridBitmap.fillRect(new Rectangle(dividerLineAX, 0, GRID_STRUMLINE_DIVIDER_WIDTH, state.gridBitmap.height), gridStrumlineDividerColor);
|
||||
// Divider at 2 * (Strumline Size)
|
||||
var dividerLineBX:Float = ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE * 2) - (GRID_STRUMLINE_DIVIDER_WIDTH / 2);
|
||||
state.gridBitmap.fillRect(new Rectangle(dividerLineBX, 0, GRID_STRUMLINE_DIVIDER_WIDTH, state.gridBitmap.height), gridStrumlineDividerColor);
|
||||
|
||||
if (state.gridTiledSprite != null)
|
||||
{
|
||||
state.gridTiledSprite.loadGraphic(state.gridBitmap);
|
||||
@@ -234,41 +186,111 @@ class ChartEditorThemeHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Vertical measure ticks.
|
||||
* Draw the measure ticks left of the grid. This also includes the horizontal beat and measure dividers as well as the vertical strumline dividers.
|
||||
*/
|
||||
static function updateMeasureTicks(state:ChartEditorState):Void
|
||||
public static function updateMeasureTicks(state:ChartEditorState, force:Bool = false):Void
|
||||
{
|
||||
var measureTickWidth:Int = 6;
|
||||
var beatTickWidth:Int = 4;
|
||||
var stepTickWidth:Int = 2;
|
||||
var measuresToCheck:Int = 5;
|
||||
|
||||
// Draw the measure ticks.
|
||||
var ticksWidth:Int = Std.int(ChartEditorState.GRID_SIZE); // 1 grid squares wide.
|
||||
var ticksHeight:Int = Std.int(ChartEditorState.GRID_SIZE * Conductor.instance.stepsPerMeasure); // 1 measure tall.
|
||||
state.measureTickBitmap = new BitmapData(ticksWidth, ticksHeight, true);
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, 0, ticksWidth, ticksHeight), GRID_BEAT_DIVIDER_COLOR_DARK);
|
||||
var currentMeasure:Int = Math.floor(Conductor.instance.getTimeInMeasures(state.scrollPositionInMs));
|
||||
if (previousMeasure == currentMeasure && !force) return;
|
||||
if (currentMeasure < 0) currentMeasure = previousMeasure = 0;
|
||||
|
||||
// Draw the measure ticks.
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, 0, state.measureTickBitmap.width, measureTickWidth / 2), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
|
||||
var bottomTickY:Float = state.measureTickBitmap.height - (measureTickWidth / 2);
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, bottomTickY, state.measureTickBitmap.width, measureTickWidth / 2), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
|
||||
// Make the bitmap.
|
||||
var ticksWidth:Int = Std.int(ChartEditorState.GRID_SIZE);
|
||||
var linesWidth:Int = Std.int(ChartEditorState.GRID_SIZE * TOTAL_COLUMN_COUNT);
|
||||
state.measureTickBitmap = new BitmapData(ticksWidth + linesWidth, 4096, true, 0x00FFFFFF);
|
||||
|
||||
// Draw the beat and step ticks. No need for two seperate loops thankfully.
|
||||
// This'll be fun to update when beat tuplets become functional.
|
||||
for (i in 1...(Conductor.instance.stepsPerMeasure))
|
||||
// Draw the vertical grey sidebar.
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, 0, ticksWidth, 4096), GRID_BEAT_DIVIDER_COLOR_DARK);
|
||||
|
||||
// Then draw the ticks and dividers themselves.
|
||||
var totalTicksHeight:Int = 0;
|
||||
var measureLengthsInPixels:Array<Int> = [];
|
||||
for (measure in 0...measuresToCheck)
|
||||
{
|
||||
if ((i % Constants.STEPS_PER_BEAT) == 0) // If we're on a beat, draw a beat tick.
|
||||
var currentTimeInMs:Float = Conductor.instance.getMeasureTimeInMs(currentMeasure + measure)
|
||||
+ 10; // Manual adjustment as it can get the wrong time change without this.
|
||||
var currentTimeChange:SongTimeChange = Conductor.instance.getTimeChange(currentTimeInMs);
|
||||
var stepsPerMeasure:Int = Constants.STEPS_PER_BEAT * currentTimeChange.timeSignatureNum;
|
||||
var ticksHeight:Int = Std.int(ChartEditorState.GRID_SIZE * stepsPerMeasure);
|
||||
|
||||
// Draw horizontal dividers between the measures.
|
||||
var gridMeasureDividerColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
var beatTickY:Float = state.measureTickBitmap.height * i / Conductor.instance.stepsPerMeasure - (beatTickWidth / 2);
|
||||
var beatTickLength:Float = state.measureTickBitmap.width * 2 / 3;
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, beatTickY, beatTickLength, beatTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
|
||||
}
|
||||
else // Else, draw a step tick.
|
||||
case Light: GRID_MEASURE_DIVIDER_COLOR_LIGHT;
|
||||
case Dark: GRID_MEASURE_DIVIDER_COLOR_DARK;
|
||||
default: GRID_MEASURE_DIVIDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
// Divider at top
|
||||
state.measureTickBitmap.fillRect(new Rectangle(ticksWidth, totalTicksHeight, linesWidth, GRID_MEASURE_DIVIDER_WIDTH / 2), gridMeasureDividerColor);
|
||||
// Divider at bottom
|
||||
var dividerLineBY:Float = ticksHeight - (GRID_MEASURE_DIVIDER_WIDTH / 2);
|
||||
state.measureTickBitmap.fillRect(new Rectangle(ticksWidth, totalTicksHeight + dividerLineBY, linesWidth, GRID_MEASURE_DIVIDER_WIDTH / 2),
|
||||
gridMeasureDividerColor);
|
||||
|
||||
// Measure ticks.
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, totalTicksHeight, ticksWidth, measureTickWidth / 2), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
|
||||
var bottomTickY:Float = ticksHeight - (measureTickWidth / 2);
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, totalTicksHeight + bottomTickY, ticksWidth, measureTickWidth / 2), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
|
||||
|
||||
// Draw horizontal dividers between the beats, this is done inside the following loop.
|
||||
var gridBeatDividerColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
var stepTickY:Float = state.measureTickBitmap.height * i / Conductor.instance.stepsPerMeasure - (stepTickWidth / 2);
|
||||
var stepTickLength:Float = state.measureTickBitmap.width * 1 / 3;
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, stepTickY, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
|
||||
case Light: GRID_BEAT_DIVIDER_COLOR_LIGHT;
|
||||
case Dark: GRID_BEAT_DIVIDER_COLOR_DARK;
|
||||
default: GRID_BEAT_DIVIDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
// Draw the beat ticks and dividers, and step ticks. No need for two seperate loops thankfully.
|
||||
for (i in 1...stepsPerMeasure)
|
||||
{
|
||||
if ((i % Constants.STEPS_PER_BEAT) == 0) // If we're on a beat, draw a beat tick and divider.
|
||||
{
|
||||
var beatTickY:Float = totalTicksHeight + ChartEditorState.GRID_SIZE * i - (beatTickWidth / 2);
|
||||
var beatTickLength:Float = ticksWidth * 2 / 3;
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, beatTickY, beatTickLength, beatTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
|
||||
|
||||
// Horizontal divider.
|
||||
state.measureTickBitmap.fillRect(new Rectangle(ticksWidth, totalTicksHeight + (ChartEditorState.GRID_SIZE * i) - (GRID_BEAT_DIVIDER_WIDTH / 2),
|
||||
linesWidth, GRID_BEAT_DIVIDER_WIDTH),
|
||||
gridBeatDividerColor);
|
||||
}
|
||||
else // Else, draw a step tick.
|
||||
{
|
||||
var stepTickY:Float = totalTicksHeight + ChartEditorState.GRID_SIZE * i - (stepTickWidth / 2);
|
||||
var stepTickLength:Float = ticksWidth * 1 / 3;
|
||||
state.measureTickBitmap.fillRect(new Rectangle(0, stepTickY, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
|
||||
}
|
||||
}
|
||||
measureLengthsInPixels.push(totalTicksHeight);
|
||||
totalTicksHeight += ticksHeight;
|
||||
}
|
||||
previousMeasure = currentMeasure;
|
||||
|
||||
// Finally, draw vertical dividers between the strumlines.
|
||||
var gridStrumlineDividerColor:FlxColor = switch (state.currentTheme)
|
||||
{
|
||||
case Light: GRID_STRUMLINE_DIVIDER_COLOR_LIGHT;
|
||||
case Dark: GRID_STRUMLINE_DIVIDER_COLOR_DARK;
|
||||
default: GRID_STRUMLINE_DIVIDER_COLOR_LIGHT;
|
||||
};
|
||||
|
||||
// Divider at 1 * (Strumline Size)
|
||||
var dividerLineAX:Float = ticksWidth + ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE) - (GRID_STRUMLINE_DIVIDER_WIDTH / 2);
|
||||
state.measureTickBitmap.fillRect(new Rectangle(dividerLineAX, 0, GRID_STRUMLINE_DIVIDER_WIDTH, state.measureTickBitmap.height), gridStrumlineDividerColor);
|
||||
// Divider at 2 * (Strumline Size)
|
||||
var dividerLineBX:Float = ticksWidth + ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE * 2) - (GRID_STRUMLINE_DIVIDER_WIDTH / 2);
|
||||
state.measureTickBitmap.fillRect(new Rectangle(dividerLineBX, 0, GRID_STRUMLINE_DIVIDER_WIDTH, state.measureTickBitmap.height), gridStrumlineDividerColor);
|
||||
|
||||
if (state.measureTicks != null)
|
||||
{
|
||||
state.measureTicks.measureLengthsInPixels = measureLengthsInPixels;
|
||||
state.measureTicks.reloadTickBitmap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user