Fix a bug where hitsounds could play in the chart editor several times.
This commit is contained in:
parent
25016f45f9
commit
1bc3b4bef5
|
@ -405,6 +405,7 @@ class Conductor
|
|||
// Take into account instrumental and file format song offsets.
|
||||
songPos += applyOffsets ? (instrumentalOffset + formatOffset + audioVisualOffset) : 0;
|
||||
|
||||
var oldSongPos = this.songPosition;
|
||||
var oldMeasure:Float = this.currentMeasure;
|
||||
var oldBeat:Float = this.currentBeat;
|
||||
var oldStep:Float = this.currentStep;
|
||||
|
@ -430,7 +431,8 @@ class Conductor
|
|||
else if (currentTimeChange != null && this.songPosition > 0.0)
|
||||
{
|
||||
// roundDecimal prevents representing 8 as 7.9999999
|
||||
this.currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * Constants.STEPS_PER_BEAT) + (this.songPosition - currentTimeChange.timeStamp) / stepLengthMs, 6);
|
||||
this.currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * Constants.STEPS_PER_BEAT)
|
||||
+ (this.songPosition - currentTimeChange.timeStamp) / stepLengthMs, 6);
|
||||
this.currentBeatTime = currentStepTime / Constants.STEPS_PER_BEAT;
|
||||
this.currentMeasureTime = currentStepTime / stepsPerMeasure;
|
||||
this.currentStep = Math.floor(currentStepTime);
|
||||
|
|
|
@ -223,12 +223,12 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
|
|||
// already paused before we lost focus.
|
||||
if (_lostFocus && !_alreadyPaused)
|
||||
{
|
||||
trace('Resuming audio (${this._label}) on focus!');
|
||||
// trace('Resuming audio (${this._label}) on focus!');
|
||||
resume();
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('Not resuming audio (${this._label}) on focus!');
|
||||
// trace('Not resuming audio (${this._label}) on focus!');
|
||||
}
|
||||
_lostFocus = false;
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
|
|||
*/
|
||||
override function onFocusLost():Void
|
||||
{
|
||||
trace('Focus lost, pausing audio!');
|
||||
// trace('Focus lost, pausing audio!');
|
||||
_lostFocus = true;
|
||||
_alreadyPaused = _paused;
|
||||
pause();
|
||||
|
@ -297,6 +297,11 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
|
|||
return sound;
|
||||
}
|
||||
|
||||
public override function toString():String
|
||||
{
|
||||
return 'FunkinSound(${this._label}, ${this.time})';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `FunkinSound` object and loads it as the current music track.
|
||||
*
|
||||
|
|
|
@ -178,9 +178,10 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
|
|||
|
||||
function get_time():Float
|
||||
{
|
||||
if (getFirstAlive() != null)
|
||||
var firstAlive:Null<FunkinSound> = getFirstAlive();
|
||||
if (firstAlive != null)
|
||||
{
|
||||
return getFirstAlive().time;
|
||||
return firstAlive.time;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -260,7 +261,7 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
|
|||
function set_pitch(val:Float):Float
|
||||
{
|
||||
#if FLX_PITCH
|
||||
trace('Setting audio pitch to ' + val);
|
||||
// trace('Setting audio pitch to ' + val);
|
||||
forEachAlive(function(snd:FunkinSound) {
|
||||
snd.pitch = val;
|
||||
});
|
||||
|
|
|
@ -2254,9 +2254,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
|
||||
function setupWelcomeMusic()
|
||||
{
|
||||
this.welcomeMusic.loadEmbedded(Paths.music('chartEditorLoop/chartEditorLoop'));
|
||||
FlxG.sound.list.add(this.welcomeMusic);
|
||||
this.welcomeMusic.looped = true;
|
||||
this.welcomeMusic = FunkinSound.load(Paths.music('chartEditorLoop/chartEditorLoop'), 1.0, true);
|
||||
}
|
||||
|
||||
public function loadPreferences():Void
|
||||
|
@ -3385,17 +3383,22 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
{
|
||||
// If middle mouse panning during song playback, we move ONLY the playhead, without scrolling. Neat!
|
||||
|
||||
var oldStepTime:Float = Conductor.instance.currentStepTime;
|
||||
var oldSongPosition:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
|
||||
Conductor.instance.update(audioInstTrack.time);
|
||||
handleHitsounds(oldSongPosition, Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
|
||||
// Resync vocals.
|
||||
if (Math.abs(audioInstTrack.time - audioVocalTrackGroup.time) > 100)
|
||||
{
|
||||
audioVocalTrackGroup.time = audioInstTrack.time;
|
||||
}
|
||||
|
||||
var oldStepTime:Float = Conductor.instance.currentStepTime;
|
||||
var oldSongPosition:Float = Conductor.instance.songPosition;
|
||||
trace(audioInstTrack);
|
||||
Conductor.instance.update(audioInstTrack.time);
|
||||
|
||||
var diffStepTime:Float = Conductor.instance.currentStepTime - oldStepTime;
|
||||
|
||||
var newSongPosition:Float = Conductor.instance.songPosition;
|
||||
handleHitsounds(oldSongPosition, newSongPosition);
|
||||
|
||||
// Move the playhead.
|
||||
playheadPositionInPixels += diffStepTime * GRID_SIZE;
|
||||
|
||||
|
@ -3404,19 +3407,23 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
else
|
||||
{
|
||||
// Else, move the entire view.
|
||||
var oldSongPosition:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
|
||||
Conductor.instance.update(audioInstTrack.time);
|
||||
handleHitsounds(oldSongPosition, Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
|
||||
|
||||
// Resync vocals.
|
||||
if (Math.abs(audioInstTrack.time - audioVocalTrackGroup.time) > 100)
|
||||
{
|
||||
audioVocalTrackGroup.time = audioInstTrack.time;
|
||||
}
|
||||
|
||||
var oldSongPosition:Float = Conductor.instance.songPosition;
|
||||
Conductor.instance.update(audioInstTrack.time);
|
||||
|
||||
// We need time in fractional steps here to allow the song to actually play.
|
||||
// Also account for a potentially offset playhead.
|
||||
scrollPositionInPixels = (Conductor.instance.currentStepTime + Conductor.instance.instrumentalOffsetSteps) * GRID_SIZE - playheadPositionInPixels;
|
||||
|
||||
var newSongPosition:Float = Conductor.instance.songPosition;
|
||||
handleHitsounds(oldSongPosition, newSongPosition);
|
||||
|
||||
// DO NOT move song to scroll position here specifically.
|
||||
|
||||
// We need to update the note sprites.
|
||||
|
@ -3631,7 +3638,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
// If a new event is needed, call buildEventSprite.
|
||||
var eventSprite:ChartEditorEventSprite = renderedEvents.recycle(() -> new ChartEditorEventSprite(this), false, true);
|
||||
eventSprite.parentState = this;
|
||||
trace('Creating new Event... (${renderedEvents.members.length})');
|
||||
// trace('Creating new Event... (${renderedEvents.members.length})');
|
||||
|
||||
// The event sprite handles animation playback and positioning.
|
||||
eventSprite.eventData = eventData;
|
||||
|
@ -6278,12 +6285,31 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true when a hitsound is played, then set to false the frame after.
|
||||
* Used to prevent doubling up on hitsounds.
|
||||
*/
|
||||
var playedHitsoundLastFrame:Bool = false;
|
||||
|
||||
/**
|
||||
* Handle the playback of hitsounds.
|
||||
*/
|
||||
function handleHitsounds(oldSongPosition:Float, newSongPosition:Float):Void
|
||||
{
|
||||
if (!hitsoundsEnabled) return;
|
||||
if (oldSongPosition == newSongPosition) return;
|
||||
|
||||
// Don't play hitsounds when moving backwards in time.
|
||||
// This prevents issues caused by FlxSound occasionally jumping backwards in time at the start of playback.
|
||||
if (newSongPosition < oldSongPosition) return;
|
||||
|
||||
// Skip hitsounds this frame if they were already played one frame ago.
|
||||
if (playedHitsoundLastFrame)
|
||||
{
|
||||
// trace('IGNORING hitsound (${oldSongPosition} -> ${newSongPosition}), already played last check!');
|
||||
playedHitsoundLastFrame = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Assume notes are sorted by time.
|
||||
for (noteData in currentSongChartNoteData)
|
||||
|
@ -6293,7 +6319,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
if (noteData.time < oldSongPosition) // Note is in the past.
|
||||
continue;
|
||||
|
||||
if (noteData.time > newSongPosition) // Note is in the future.
|
||||
if (noteData.time >= newSongPosition) // Note is in the future.
|
||||
return; // Assume all notes are also in the future.
|
||||
|
||||
// Note was just hit.
|
||||
|
@ -6318,6 +6344,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
case 1: // Opponent
|
||||
if (hitsoundVolumeOpponent > 0) this.playSound(Paths.sound('chartingSounds/hitNoteOpponent'), hitsoundVolumeOpponent);
|
||||
}
|
||||
|
||||
playedHitsoundLastFrame = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ class ChartEditorAudioHandler
|
|||
if (instId == '') instId = 'default';
|
||||
var instTrackData:Null<Bytes> = state.audioInstTrackData.get(instId);
|
||||
var perfStart:Float = TimerUtil.start();
|
||||
var instTrack:Null<FunkinSound> = SoundUtil.buildSoundFromBytes(instTrackData);
|
||||
var instTrack:Null<FunkinSound> = SoundUtil.buildSoundFromBytes(instTrackData, 'chartEditor-inst${instId == '' ? '' : '-${instId}'}');
|
||||
trace('Built instrumental track in ${TimerUtil.seconds(perfStart)} seconds.');
|
||||
if (instTrack == null) return false;
|
||||
|
||||
|
@ -205,7 +205,7 @@ class ChartEditorAudioHandler
|
|||
var trackId:String = '${charId}${instId == '' ? '' : '-${instId}'}';
|
||||
var vocalTrackData:Null<Bytes> = state.audioVocalTrackData.get(trackId);
|
||||
var perfStart:Float = TimerUtil.start();
|
||||
var vocalTrack:Null<FunkinSound> = SoundUtil.buildSoundFromBytes(vocalTrackData);
|
||||
var vocalTrack:Null<FunkinSound> = SoundUtil.buildSoundFromBytes(vocalTrackData, 'chartEditor-vocals-${charId}${instId == '' ? '' : '-${instId}'}');
|
||||
trace('Built vocal track in ${TimerUtil.seconds(perfStart)}.');
|
||||
|
||||
if (state.audioVocalTrackGroup == null) state.audioVocalTrackGroup = new VoicesGroup();
|
||||
|
|
|
@ -12,13 +12,15 @@ class SoundUtil
|
|||
* @param input The byte data.
|
||||
* @return The playable sound, or `null` if loading failed.
|
||||
*/
|
||||
public static function buildSoundFromBytes(input:Null<Bytes>):Null<FunkinSound>
|
||||
public static function buildSoundFromBytes(input:Null<Bytes>, label:String = 'unknown'):Null<FunkinSound>
|
||||
{
|
||||
if (input == null) return null;
|
||||
|
||||
var openflSound:OpenFLSound = new OpenFLSound();
|
||||
openflSound.loadCompressedDataFromByteArray(openfl.utils.ByteArray.fromBytes(input), input.length);
|
||||
var output:FunkinSound = FunkinSound.load(openflSound, 1.0, false);
|
||||
@:privateAccess
|
||||
output._label = label;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue