1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-01-01 09:48:14 +00:00

Chart wizard plus shader fixes

This commit is contained in:
Eric Myllyoja 2022-12-08 19:33:47 -05:00
parent fbf92acf23
commit 19b2f3799a
10 changed files with 213 additions and 56 deletions

View file

@ -11,14 +11,14 @@
"name": "flixel",
"type": "git",
"dir": null,
"ref": "6728df7",
"ref": "8ff2aa9",
"url": "https://github.com/MasterEric/flixel"
},
{
"name": "flixel-addons",
"type": "git",
"dir": null,
"ref": "a3877f0",
"ref": "157eaf3",
"url": "https://github.com/MasterEric/flixel-addons"
},
{

View file

@ -129,6 +129,7 @@ class Conductor
*/
public static function forceBPM(bpm:Float)
{
trace('[CONDUCTOR] Forcing BPM to ' + bpm);
Conductor.bpmOverride = bpm;
}
@ -213,10 +214,8 @@ class Conductor
}
}
public static function mapTimeChanges(currentChart:SongDifficulty)
public static function mapTimeChanges(songTimeChanges:Array<SongTimeChange>)
{
var songTimeChanges:Array<SongTimeChange> = currentChart.timeChanges;
timeChanges = [];
for (currentTimeChange in songTimeChanges)

View file

@ -7,30 +7,38 @@ import flixel.system.FlxSound;
// when needed
class VoicesGroup extends FlxTypedGroup<FlxSound>
{
public var time(default, set):Float = 0;
public var time(get, set):Float;
public var volume(default, set):Float = 1;
public var volume(get, set):Float;
public var pitch(default, set):Float = 1;
public var pitch(get, set):Float;
// make it a group that you add to?
public function new(song:String, ?files:Array<String> = null)
public function new()
{
super();
}
// TODO: Remove this.
public static function build(song:String, ?files:Array<String> = null):VoicesGroup
{
var result = new VoicesGroup();
if (files == null)
{
// Add an empty voice.
add(new FlxSound());
return;
result.add(new FlxSound());
return result;
}
for (sndFile in files)
{
var snd:FlxSound = new FlxSound().loadEmbedded(Paths.voices(song, '$sndFile'));
FlxG.sound.list.add(snd); // adds it to sound group for proper volumes
add(snd); // adds it to main group for other shit
result.add(snd); // adds it to main group for other shit
}
return result;
}
/**
@ -83,6 +91,14 @@ class VoicesGroup extends FlxTypedGroup<FlxSound>
});
}
function get_time():Float
{
if (getFirstAlive() != null)
return getFirstAlive().time;
else
return 0;
}
function set_time(time:Float):Float
{
forEachAlive(function(snd)
@ -94,6 +110,14 @@ class VoicesGroup extends FlxTypedGroup<FlxSound>
return time;
}
function get_volume():Float
{
if (getFirstAlive() != null)
return getFirstAlive().volume;
else
return 1;
}
// in PlayState, adjust the code so that it only mutes the player1 vocal tracks?
function set_volume(volume:Float):Float
{
@ -105,9 +129,20 @@ class VoicesGroup extends FlxTypedGroup<FlxSound>
return volume;
}
function get_pitch():Float
{
#if FLX_PITCH
if (getFirstAlive() != null)
return getFirstAlive().pitch;
else
#end
return 1;
}
function set_pitch(val:Float):Float
{
#if HAS_PITCH
#if FLX_PITCH
trace('Setting audio pitch to ' + val);
forEachAlive(function(snd)
{
snd.pitch = val;

View file

@ -445,7 +445,7 @@ class ChartingState extends MusicBeatState
add(playheadTest);
// WONT WORK FOR TUTORIAL OR TEST SONG!!! REDO LATER
vocals = new VoicesGroup(daSong, _song.voiceList);
vocals = VoicesGroup.build(daSong, _song.voiceList);
// vocals = new FlxSound().loadEmbedded(Paths.voices(daSong));
// FlxG.sound.list.add(vocals);

View file

@ -35,7 +35,7 @@ class Cursor
static final CURSOR_GRABBING_PARAMS:CursorParams = {
graphic: "assets/images/cursor/cursor-grabbing.png",
scale: 1.0,
offsetX: 8,
offsetX: 32,
offsetY: 0,
};
static var assetCursorGrabbing:BitmapData = null;

View file

@ -354,7 +354,7 @@ class PlayState extends MusicBeatState
if (currentSong_NEW != null)
{
Conductor.mapTimeChanges(currentChart);
Conductor.mapTimeChanges(currentChart.timeChanges);
// Conductor.bpm = currentChart.getStartingBPM();
// TODO: Support for dialog.
@ -1029,9 +1029,9 @@ class PlayState extends MusicBeatState
currentSong.song = currentSong.song;
if (currentSong.needsVoices)
vocals = new VoicesGroup(currentSong.song, currentSong.voiceList);
vocals = VoicesGroup.build(currentSong.song, currentSong.voiceList);
else
vocals = new VoicesGroup(currentSong.song, null);
vocals = VoicesGroup.build(currentSong.song, null);
vocals.members[0].onComplete = function()
{

View file

@ -45,6 +45,11 @@ class Song // implements IPlayStateScriptedClass
populateFromMetadata();
}
public function getRawMetadata():Array<SongMetadata>
{
return _metadata;
}
/**
* Populate the song data from the provided metadata,
* including data from individual difficulties. Does not load chart data.
@ -246,7 +251,7 @@ class SongDifficulty
public function buildVocals(charId:String = "bf"):VoicesGroup
{
var result:VoicesGroup = new VoicesGroup(this.song.songId, this.buildVoiceList());
var result:VoicesGroup = VoicesGroup.build(this.song.songId, this.buildVoiceList());
return result;
}
}

View file

@ -96,12 +96,12 @@ class SongDataParser
if (songCache.exists(songId))
{
var song:Song = songCache.get(songId);
trace('[STAGEDATA] Successfully fetch song: ${songId}');
trace('[SONGDATA] Successfully fetch song: ${songId}');
return song;
}
else
{
trace('[STAGEDATA] Failed to fetch song, not found in cache: ${songId}');
trace('[SONGDATA] Failed to fetch song, not found in cache: ${songId}');
return null;
}
}

View file

@ -110,6 +110,25 @@ class ChartEditorDialogHandler
}
// TODO: Get the list of songs and insert them as links into the "Create From Song" section.
var linkTemplateDadBattle:Link = dialog.findComponent('splashTemplateDadBattle', Link);
linkTemplateDadBattle.onClick = (_event) ->
{
dialog.hideDialog(DialogButton.CANCEL);
// Load song from template
state.loadSongAsTemplate('dadbattle');
}
var linkTemplateBopeebo:Link = dialog.findComponent('splashTemplateBopeebo', Link);
linkTemplateBopeebo.onClick = (_event) ->
{
dialog.hideDialog(DialogButton.CANCEL);
// Load song from template
state.loadSongAsTemplate('bopeebo');
}
var splashTemplateContainer:VBox = dialog.findComponent('splashTemplateContainer', VBox);
return dialog;
}
@ -237,7 +256,7 @@ class ChartEditorDialogHandler
var dialogBPM:NumberStepper = dialog.findComponent('dialogBPM', NumberStepper);
dialogBPM.onChange = (event:UIEvent) ->
{
if (event.value == null)
if (event.value == null || event.value <= 0)
return;
var timeChanges = state.currentSongMetadata.timeChanges;
@ -249,6 +268,9 @@ class ChartEditorDialogHandler
{
timeChanges[0].bpm = event.value;
}
Conductor.forceBPM(event.value);
state.currentSongMetadata.timeChanges = timeChanges;
};
@ -388,9 +410,9 @@ class ChartEditorDialogHandler
{
if (selectedFile != null)
{
trace('Selected file: ' + selectedFile);
vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n$selectedFile';
// state.loadVocalsFromBytes(selectedFile.bytes);
trace('Selected file: ' + selectedFile.name + "~" + selectedFile.fullPath);
vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n${selectedFile.name}';
state.loadVocalsFromBytes(selectedFile.bytes);
removeDropHandler(onDropFile);
}
});

View file

@ -1,5 +1,7 @@
package funkin.ui.debug.charting;
import funkin.play.song.SongData.SongDataParser;
import funkin.play.song.Song;
import lime.media.AudioBuffer;
import funkin.input.Cursor;
import flixel.FlxSprite;
@ -433,7 +435,7 @@ class ChartEditorState extends HaxeUIState
* The audio track for the vocals.
* TODO: Replace with a VocalSoundGroup.
*/
var audioVocalTrack:FlxSound;
var audioVocalTrackGroup:VoicesGroup;
/**
* CHART DATA
@ -758,7 +760,9 @@ class ChartEditorState extends HaxeUIState
// TODO: We should be loading the music later when the user requests it.
// loadDefaultMusic();
ChartEditorDialogHandler.openWelcomeDialog(this, false);
// TODO: Change to false.
var canCloseInitialDialog = true;
ChartEditorDialogHandler.openWelcomeDialog(this, canCloseInitialDialog);
}
function buildDefaultSongData()
@ -771,6 +775,8 @@ class ChartEditorState extends HaxeUIState
// Initialize the song chart data.
songChartData = new Map<String, SongChartData>();
audioVocalTrackGroup = new VoicesGroup();
}
/**
@ -933,7 +939,7 @@ class ChartEditorState extends HaxeUIState
playbarHeadDragging = true;
// If we were dragging the playhead while the song was playing, resume playing.
if (audioVocalTrack.playing)
if (audioInstTrack != null && audioInstTrack.playing)
{
playbarHeadDraggingWasPlaying = true;
stopAudioPlayback();
@ -1057,16 +1063,35 @@ class ChartEditorState extends HaxeUIState
});
setUISelected('menubarItemMetronomeEnabled', shouldPlayMetronome);
var instVolumeLabel:Label = findComponent('menubarLabelVolumeInstrumental', Label);
addUIChangeListener('menubarItemVolumeInstrumental', (event:UIEvent) ->
{
var volume:Float = event.value / 100.0;
audioInstTrack.volume = volume;
if (audioInstTrack != null)
audioInstTrack.volume = volume;
instVolumeLabel.text = 'Instrumental - ${event.value}%';
});
var vocalsVolumeLabel:Label = findComponent('menubarLabelVolumeVocals', Label);
addUIChangeListener('menubarItemVolumeVocals', (event:UIEvent) ->
{
var volume:Float = event.value / 100.0;
audioVocalTrack.volume = volume;
if (audioVocalTrackGroup != null)
audioVocalTrackGroup.volume = volume;
vocalsVolumeLabel.text = 'Vocals - ${event.value}%';
});
var playbackSpeedLabel:Label = findComponent('menubarLabelPlaybackSpeed', Label);
addUIChangeListener('menubarItemPlaybackSpeed', (event:UIEvent) ->
{
var pitch = event.value * 2.0 / 100.0;
#if FLX_PITCH
if (audioInstTrack != null)
audioInstTrack.pitch = pitch;
if (audioVocalTrackGroup != null)
audioVocalTrackGroup.pitch = pitch;
#end
playbackSpeedLabel.text = 'Playback Speed - ${pitch}x';
});
addUIChangeListener('menubarItemToggleToolboxTools', (event:UIEvent) ->
@ -2242,8 +2267,8 @@ class ChartEditorState extends HaxeUIState
var oldStepTime = Conductor.currentStepTime;
Conductor.update(audioInstTrack.time);
// Resync vocals.
if (Math.abs(audioInstTrack.time - audioVocalTrack.time) > 100)
audioVocalTrack.time = audioInstTrack.time;
if (Math.abs(audioInstTrack.time - audioVocalTrackGroup.time) > 100)
audioVocalTrackGroup.time = audioInstTrack.time;
var diffStepTime = Conductor.currentStepTime - oldStepTime;
// Move the playhead.
@ -2257,8 +2282,8 @@ class ChartEditorState extends HaxeUIState
Conductor.update(audioInstTrack.time);
// Resync vocals.
if (audioVocalTrack != null && Math.abs(audioInstTrack.time - audioVocalTrack.time) > 100)
audioVocalTrack.time = audioInstTrack.time;
if (audioVocalTrackGroup != null && Math.abs(audioInstTrack.time - audioVocalTrackGroup.time) > 100)
audioVocalTrackGroup.time = audioInstTrack.time;
// We need time in fractional steps here to allow the song to actually play.
// Also account for a potentially offset playhead.
@ -2281,16 +2306,20 @@ class ChartEditorState extends HaxeUIState
{
if (audioInstTrack != null)
audioInstTrack.play();
if (audioVocalTrack != null)
audioVocalTrack.play();
if (audioVocalTrackGroup != null)
audioVocalTrackGroup.play();
if (audioVocalTrackGroup != null)
audioVocalTrackGroup.play();
}
function stopAudioPlayback()
{
if (audioInstTrack != null)
audioInstTrack.pause();
if (audioVocalTrack != null)
audioVocalTrack.pause();
if (audioVocalTrackGroup != null)
audioVocalTrackGroup.pause();
if (audioVocalTrackGroup != null)
audioVocalTrackGroup.pause();
}
function toggleAudioPlayback()
@ -2418,8 +2447,12 @@ class ChartEditorState extends HaxeUIState
*/
public function loadInstrumentalFromPath(path:String):Void
{
#if sys
var fileBytes:haxe.io.Bytes = sys.io.File.getBytes(path);
loadInstrumentalFromBytes(fileBytes);
#else
trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way.");
#end
}
/**
@ -2440,6 +2473,14 @@ class ChartEditorState extends HaxeUIState
postLoadInstrumental();
}
public function loadInstrumentalFromAsset(path:String):Void
{
var vocalTrack = FlxG.sound.load(path, 1.0, false);
audioInstTrack = vocalTrack;
postLoadInstrumental();
}
function postLoadInstrumental()
{
// Prevent the time from skipping back to 0 when the song ends.
@ -2447,14 +2488,10 @@ class ChartEditorState extends HaxeUIState
{
if (audioInstTrack != null)
audioInstTrack.pause();
if (audioVocalTrack != null)
audioVocalTrack.pause();
if (audioVocalTrackGroup != null)
audioVocalTrackGroup.pause();
};
var DAD_BATTLE_BPM = 180;
var BOPEEBO_BPM = 100;
Conductor.forceBPM(DAD_BATTLE_BPM);
songLength = Std.int(Conductor.getTimeInSteps(audioInstTrack.length) * GRID_SIZE);
gridTiledSprite.height = songLength;
@ -2470,20 +2507,79 @@ class ChartEditorState extends HaxeUIState
}
/**
* Load a music track for playback.
* Loads a vocal track from an absolute file path.
*/
function loadDefaultMusic()
public function loadVocalsFromPath(path:String):Void
{
// TODO: How to load music by selecting with a file dialog?
audioInstTrack = FlxG.sound.play(Paths.inst('dadbattle'), 1.0, false);
audioInstTrack.autoDestroy = false;
audioInstTrack.pause();
#if sys
var fileBytes:haxe.io.Bytes = sys.io.File.getBytes(path);
loadVocalsFromBytes(fileBytes);
#else
trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way.");
#end
}
audioVocalTrack = FlxG.sound.play(Paths.voices('dadbattle'), 1.0, false);
audioVocalTrack.autoDestroy = false;
audioVocalTrack.pause();
public function loadVocalsFromAsset(path:String):Void
{
var vocalTrack = FlxG.sound.load(path, 1.0, false);
audioVocalTrackGroup.add(vocalTrack);
}
postLoadInstrumental();
/**
* Loads a vocal track from audio byte data.
*/
public function loadVocalsFromBytes(bytes:haxe.io.Bytes):Void
{
var openflSound = new openfl.media.Sound();
openflSound.loadCompressedDataFromByteArray(openfl.utils.ByteArray.fromBytes(bytes), bytes.length);
var vocalTrack = FlxG.sound.load(openflSound, 1.0, false);
audioVocalTrackGroup.add(vocalTrack);
// Tell the user the load was successful.
// TODO: Un-bork this.
// showNotification('Loaded instrumental track successfully.');
}
/**
* Fetch's a song's existing chart and audio and loads it, replacing the current song.
*/
public function loadSongAsTemplate(songId:String)
{
var song:Song = SongDataParser.fetchSong(songId);
if (song == null)
{
// showNotification('Failed to load song template.');
return;
}
// Load the song metadata.
var rawSongMetadata:Array<SongMetadata> = song.getRawMetadata();
this.songMetadata = new Map<String, SongMetadata>();
for (metadata in rawSongMetadata)
{
var variation = (metadata.variation == null || metadata.variation == '') ? 'default' : metadata.variation;
this.songMetadata.set(variation, metadata);
}
this.songChartData = new Map<String, SongChartData>();
for (metadata in rawSongMetadata)
{
var variation = (metadata.variation == null || metadata.variation == '') ? 'default' : metadata.variation;
this.songChartData.set(variation, SongDataParser.parseSongChartData(songId, metadata.variation));
}
Conductor.mapTimeChanges(currentSongMetadata.timeChanges);
loadInstrumentalFromAsset(Paths.inst(songId));
loadVocalsFromAsset(Paths.voices(songId));
// Apply BPM
// showNotification('Loaded song ${songId}.');
}
/**
@ -2498,8 +2594,8 @@ class ChartEditorState extends HaxeUIState
// Update the songPosition in the audio tracks.
if (audioInstTrack != null)
audioInstTrack.time = scrollPositionInMs + playheadPositionInMs;
if (audioVocalTrack != null)
audioVocalTrack.time = scrollPositionInMs + playheadPositionInMs;
if (audioVocalTrackGroup != null)
audioVocalTrackGroup.time = scrollPositionInMs + playheadPositionInMs;
// We need to update the note sprites because we changed the scroll position.
noteDisplayDirty = true;