CharterSelection Song Variations
This commit is contained in:
@@ -45,12 +45,15 @@
|
|||||||
<group name="CharterSelection" prefix="charterSelection.">
|
<group name="CharterSelection" prefix="charterSelection.">
|
||||||
<str id="desc">Select a song to modify the charts from.</str>
|
<str id="desc">Select a song to modify the charts from.</str>
|
||||||
<str id="acceptSong">Press ACCEPT to choose a difficulty to edit.</str>
|
<str id="acceptSong">Press ACCEPT to choose a difficulty to edit.</str>
|
||||||
|
<str id="acceptVariation">Press ACCEPT to choose a song variation to edit.</str>
|
||||||
<str id="acceptDifficulty">Press ACCEPT to edit the chart for the selected difficulty.</str>
|
<str id="acceptDifficulty">Press ACCEPT to edit the chart for the selected difficulty.</str>
|
||||||
<str id="selectDifficulty">Select a difficulty to continue.</str>
|
<str id="selectDifficulty">Select a difficulty to continue.</str>
|
||||||
<str id="newDifficulty">New Difficulty</str>
|
<str id="newDifficulty">New Difficulty</str>
|
||||||
<str id="newDifficultyDesc">Press ACCEPT to create a new chart difficulty.</str>
|
<str id="newDifficultyDesc">Press ACCEPT to create a new chart difficulty.</str>
|
||||||
<str id="newSong">New Song</str>
|
<str id="newSong">New Song</str>
|
||||||
<str id="newSongDesc">Press ACCEPT to create a new song.</str>
|
<str id="newSongDesc">Press ACCEPT to create a new song.</str>
|
||||||
|
<str id="newVariation">New Variation</str>
|
||||||
|
<str id="newVariationDesc">Press ACCEPT to create a new song variation.</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="ChartCreationScreen" prefix="chartCreation.">
|
<group name="ChartCreationScreen" prefix="chartCreation.">
|
||||||
@@ -104,6 +107,7 @@
|
|||||||
|
|
||||||
<str id="songData">Song Data</str>
|
<str id="songData">Song Data</str>
|
||||||
<str id="songName">Song Name</str>
|
<str id="songName">Song Name</str>
|
||||||
|
<str id="variation">Song Variation</str>
|
||||||
<str id="bpm">BPM</str>
|
<str id="bpm">BPM</str>
|
||||||
<str id="timeSignature">Time Signature</str>
|
<str id="timeSignature">Time Signature</str>
|
||||||
<str id="menusData">Menus Data (Freeplay/Story)</str>
|
<str id="menusData">Menus Data (Freeplay/Story)</str>
|
||||||
|
|||||||
@@ -600,32 +600,34 @@ class Charter extends UIState {
|
|||||||
PlayState.loadSong(__song, __diff, __variant, false, false);
|
PlayState.loadSong(__song, __diff, __variant, false, false);
|
||||||
__resetStatics();
|
__resetStatics();
|
||||||
}
|
}
|
||||||
Conductor.setupSong(PlayState.SONG);
|
|
||||||
noteTypes = PlayState.SONG.noteTypes;
|
|
||||||
|
|
||||||
FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff, PlayState.SONG.meta.instSuffix)));
|
var SONG = PlayState.SONG;
|
||||||
if (Assets.exists(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix)))
|
Conductor.setupSong(SONG);
|
||||||
vocals = FlxG.sound.load(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix));
|
noteTypes = SONG.noteTypes;
|
||||||
|
|
||||||
|
FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(SONG.meta.name, __diff, SONG.meta.instSuffix)));
|
||||||
|
if (Assets.exists(Paths.voices(SONG.meta.name, __diff, SONG.meta.vocalsSuffix)))
|
||||||
|
vocals = FlxG.sound.load(Paths.voices(SONG.meta.name, __diff, SONG.meta.vocalsSuffix));
|
||||||
else
|
else
|
||||||
vocals = new FlxSound();
|
vocals = new FlxSound();
|
||||||
|
|
||||||
vocals.muted = !PlayState.SONG.meta.needsVoices;
|
vocals.muted = !SONG.meta.needsVoices;
|
||||||
vocals.group = FlxG.sound.defaultMusicGroup;
|
vocals.group = FlxG.sound.defaultMusicGroup;
|
||||||
|
|
||||||
gridBackdrops.createGrids(PlayState.SONG.strumLines.length);
|
gridBackdrops.createGrids(SONG.strumLines.length);
|
||||||
|
|
||||||
for(strL in PlayState.SONG.strumLines)
|
for(strL in SONG.strumLines)
|
||||||
createStrumline(strumLines.members.length, strL, false, false);
|
createStrumline(strumLines.members.length, strL, false, false);
|
||||||
|
|
||||||
// create notes
|
// create notes
|
||||||
notesGroup.autoSort = false;
|
notesGroup.autoSort = false;
|
||||||
var noteCount:Int = 0;
|
var noteCount:Int = 0;
|
||||||
for (strL in PlayState.SONG.strumLines)
|
for (strL in SONG.strumLines)
|
||||||
noteCount += strL.notes.length;
|
noteCount += strL.notes.length;
|
||||||
notesGroup.preallocate(noteCount);
|
notesGroup.preallocate(noteCount);
|
||||||
|
|
||||||
var notesCreated:Int = 0;
|
var notesCreated:Int = 0;
|
||||||
for (i => strL in PlayState.SONG.strumLines)
|
for (i => strL in SONG.strumLines)
|
||||||
for (note in strL.notes) {
|
for (note in strL.notes) {
|
||||||
var n = new CharterNote();
|
var n = new CharterNote();
|
||||||
var t = Conductor.getStepForTime(note.time);
|
var t = Conductor.getStepForTime(note.time);
|
||||||
@@ -639,7 +641,7 @@ class Charter extends UIState {
|
|||||||
rightEventsGroup.autoSort = leftEventsGroup.autoSort = false;
|
rightEventsGroup.autoSort = leftEventsGroup.autoSort = false;
|
||||||
var lastLeftEvents:CharterEvent = null, lastRightEvents:CharterEvent = null;
|
var lastLeftEvents:CharterEvent = null, lastRightEvents:CharterEvent = null;
|
||||||
var lastLeftTime = Math.NaN, lastRightTime = Math.NaN;
|
var lastLeftTime = Math.NaN, lastRightTime = Math.NaN;
|
||||||
for (e in PlayState.SONG.events) if (e != null) {
|
for (e in SONG.events) if (e != null) {
|
||||||
if (e.global) {
|
if (e.global) {
|
||||||
if (lastRightEvents != null && lastRightTime == e.time) lastRightEvents.events.push(e);
|
if (lastRightEvents != null && lastRightTime == e.time) lastRightEvents.events.push(e);
|
||||||
else rightEventsGroup.add(lastRightEvents = new CharterEvent(Conductor.getStepForTime(lastRightTime = e.time), [e], e.global));
|
else rightEventsGroup.add(lastRightEvents = new CharterEvent(Conductor.getStepForTime(lastRightTime = e.time), [e], e.global));
|
||||||
@@ -685,10 +687,10 @@ class Charter extends UIState {
|
|||||||
var wavesToGenerate:Array<{name:String, sound:FlxSound}> = [];
|
var wavesToGenerate:Array<{name:String, sound:FlxSound}> = [];
|
||||||
|
|
||||||
if (FlxG.sound.music.loaded)
|
if (FlxG.sound.music.loaded)
|
||||||
wavesToGenerate.push({name: "Inst.ogg", sound: FlxG.sound.music});
|
wavesToGenerate.push({name: 'Inst${PlayState.SONG.meta.instSuffix}.ogg', sound: FlxG.sound.music});
|
||||||
|
|
||||||
if (vocals.loaded)
|
if (vocals.loaded)
|
||||||
wavesToGenerate.push({name: "Voices.ogg", sound: vocals});
|
wavesToGenerate.push({name: 'Voices${PlayState.SONG.meta.vocalsSuffix}.ogg', sound: vocals});
|
||||||
|
|
||||||
for (strumLine in strumLines)
|
for (strumLine in strumLines)
|
||||||
if (strumLine.vocals != null && strumLine.strumLine.vocalsSuffix != null && strumLine.strumLine.vocalsSuffix != "" && strumLine.vocals.loaded)
|
if (strumLine.vocals != null && strumLine.strumLine.vocalsSuffix != null && strumLine.strumLine.vocalsSuffix != "" && strumLine.vocals.loaded)
|
||||||
|
|||||||
@@ -150,20 +150,21 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
|||||||
Reflect.setProperty(customVals, vals.propertyText.label.text, vals.valueText.label.text);
|
Reflect.setProperty(customVals, vals.propertyText.label.text, vals.valueText.label.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayState.SONG.meta = {
|
var meta = PlayState.SONG.meta;
|
||||||
name: songNameTextBox.label.text,
|
if (meta == null) meta = {name: songNameTextBox.label.text};
|
||||||
bpm: bpmStepper.value,
|
else meta.name = songNameTextBox.label.text;
|
||||||
needsVoices: needsVoicesCheckbox.checked,
|
|
||||||
beatsPerMeasure: Std.int(beatsPerMeasureStepper.value),
|
meta.bpm = bpmStepper.value;
|
||||||
stepsPerBeat: Std.int(16 / denominatorStepper.value),
|
meta.needsVoices = needsVoicesCheckbox.checked;
|
||||||
displayName: displayNameTextBox.label.text,
|
meta.beatsPerMeasure = Std.int(beatsPerMeasureStepper.value);
|
||||||
icon: iconTextBox.label.text,
|
meta.stepsPerBeat = Std.int(16 / denominatorStepper.value);
|
||||||
color: colorWheel.curColor,
|
meta.displayName = displayNameTextBox.label.text;
|
||||||
opponentModeAllowed: opponentModeCheckbox.checked,
|
meta.icon = iconTextBox.label.text;
|
||||||
coopAllowed: coopAllowedCheckbox.checked,
|
meta.color = colorWheel.curColor;
|
||||||
difficulties: [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()],
|
meta.opponentModeAllowed = opponentModeCheckbox.checked;
|
||||||
customValues: customVals,
|
meta.coopAllowed = coopAllowedCheckbox.checked;
|
||||||
};
|
meta.difficulties = [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()];
|
||||||
|
meta.customValues = customVals;
|
||||||
|
|
||||||
Charter.instance.updateBPMEvents();
|
Charter.instance.updateBPMEvents();
|
||||||
Charter.instance.vocals.muted = !needsVoicesCheckbox.checked;
|
Charter.instance.vocals.muted = !needsVoicesCheckbox.checked;
|
||||||
|
|||||||
@@ -25,48 +25,65 @@ class CharterSelectionScreen extends EditorTreeMenuScreen {
|
|||||||
public var songList:Array<String> = [];
|
public var songList:Array<String> = [];
|
||||||
public var curSong:ChartMetaData;
|
public var curSong:ChartMetaData;
|
||||||
|
|
||||||
inline public function makeChartOption(d:String, name:String):TextOption {
|
inline public function makeChartOption(d:String, v:String, name:String):TextOption {
|
||||||
return new TextOption(d, getID('acceptDifficulty'), () -> FlxG.switchState(new Charter(name, d, null)));
|
return new TextOption(d, getID('acceptDifficulty'), FlxG.switchState.bind(new Charter(name, d, v)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline public function makeVariationOption(s:ChartMetaData):TextOption {
|
||||||
|
return new TextOption(s.variant, getID('acceptVariation'), " >", openSongOption.bind(s, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function openSongOption(s:ChartMetaData, first = true) {
|
||||||
|
curSong = s;
|
||||||
|
|
||||||
|
var isVariant = s.variant != null && s.variant != '';
|
||||||
|
var screen = new EditorTreeMenuScreen((first || !isVariant) ? (s.name + (isVariant ? ' (${s.variant})' : '')) : s.variant, getID('selectDifficulty'));
|
||||||
|
|
||||||
|
for (d in s.difficulties) if (d != '') screen.add(makeChartOption(d, isVariant ? s.variant : null, s.name));
|
||||||
|
screen.add(new Separator());
|
||||||
|
for (v in s.variants) if (s.metas.get(v) != null) screen.add(makeVariationOption(s.metas.get(v)));
|
||||||
|
|
||||||
|
#if sys
|
||||||
|
screen.insert(0, new NewOption(getID('newDifficulty'), getID('newDifficultyDesc'), () -> {
|
||||||
|
parent.openSubState(new ChartCreationScreen(saveChart));
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!first) screen.curSelected = 1;
|
||||||
|
else {
|
||||||
|
cast(screen.members[0], NewOption).itemHeight = 120;
|
||||||
|
screen.insert(1, new NewOption(getID('newVariation'), getID('newVariationDesc'), () -> {
|
||||||
|
parent.openSubState(new VariationCreationScreen(s, saveSong));
|
||||||
|
}));
|
||||||
|
screen.curSelected = 2;
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
parent.addMenu(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function makeSongOption(s:ChartMetaData):IconOption {
|
public function makeSongOption(s:ChartMetaData):IconOption {
|
||||||
songList.push(s.name.toLowerCase());
|
songList.push(s.name.toLowerCase());
|
||||||
|
|
||||||
var opt = new IconOption(s.name, getID('acceptSong'), s.icon, () -> {
|
var opt = new IconOption(s.name, getID('acceptSong'), s.icon, openSongOption.bind(s, true));
|
||||||
curSong = s;
|
opt.suffix = " >";
|
||||||
|
|
||||||
var screen = new EditorTreeMenuScreen(s.name, getID('selectDifficulty'), [
|
|
||||||
for (d in s.difficulties) if (d != '') makeChartOption(d, s.name)
|
|
||||||
]);
|
|
||||||
|
|
||||||
#if sys
|
|
||||||
screen.insert(0, new NewOption(getID('newDifficulty'), getID('newDifficultyDesc'), () -> {
|
|
||||||
parent.openSubState(new ChartCreationScreen(saveChart));
|
|
||||||
}));
|
|
||||||
screen.curSelected = 1;
|
|
||||||
#end
|
|
||||||
|
|
||||||
parent.addMenu(screen);
|
|
||||||
});
|
|
||||||
opt.suffix = ' >';
|
|
||||||
opt.editorFlashColor = s.color.getDefault(FlxColor.WHITE);
|
opt.editorFlashColor = s.color.getDefault(FlxColor.WHITE);
|
||||||
|
|
||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super('editor.chart.name', 'charterSelection.desc', 'charterSelection.', 'newSong', 'newSongDesc', () -> {
|
super('editor.chart.name', 'charterSelection.desc', 'charterSelection.', 'newSong', 'newSongDesc', #if sys () -> {
|
||||||
parent.openSubState(new SongCreationScreen(saveSong));
|
parent.openSubState(new SongCreationScreen(saveSong));
|
||||||
});
|
} #end);
|
||||||
freeplayList = FreeplaySonglist.get(false);
|
freeplayList = FreeplaySonglist.get(false);
|
||||||
|
|
||||||
for (i => s in freeplayList.songs) add(makeSongOption(s));
|
for (i => s in freeplayList.songs) add(makeSongOption(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if sys
|
#if sys
|
||||||
public function saveSong(creation:SongCreationData, ?callback:String -> SongCreationData -> Void) {
|
public function saveSong(creation:SongCreationData, ?callback:String -> Void) {
|
||||||
var songAlreadyExists:Bool = songList.contains(creation.meta.name.toLowerCase());
|
var variant = creation.meta.variant != null && creation.meta.variant != "" ? creation.meta.variant : null;
|
||||||
if (songAlreadyExists) {
|
if (songList.contains(creation.meta.name.toLowerCase()) || (variant != null && curSong != null && curSong.variants.contains(variant))) {
|
||||||
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.song-exists-title"), TU.translate("chartCreation.warnings.song-exists-body"), [
|
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.song-exists-title"), TU.translate("chartCreation.warnings.song-exists-body"), [
|
||||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
||||||
]));
|
]));
|
||||||
@@ -74,6 +91,7 @@ class CharterSelectionScreen extends EditorTreeMenuScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var songFolder:String = '${Paths.getAssetsRoot()}/songs/${creation.meta.name}';
|
var songFolder:String = '${Paths.getAssetsRoot()}/songs/${creation.meta.name}';
|
||||||
|
creation.meta = Chart.filterMetaForSaving(creation.meta);
|
||||||
|
|
||||||
#if sys
|
#if sys
|
||||||
// Make Directories
|
// Make Directories
|
||||||
@@ -82,24 +100,32 @@ class CharterSelectionScreen extends EditorTreeMenuScreen {
|
|||||||
sys.FileSystem.createDirectory('$songFolder/charts');
|
sys.FileSystem.createDirectory('$songFolder/charts');
|
||||||
|
|
||||||
// Save Files
|
// Save Files
|
||||||
CoolUtil.safeSaveFile('$songFolder/meta.json', Chart.makeMetaSaveable(creation.meta));
|
var instSuffix = creation.meta.instSuffix != null ? creation.meta.instSuffix : '', vocalsSuffix = creation.meta.vocalsSuffix != null ? creation.meta.vocalsSuffix : '';
|
||||||
if (creation.instBytes != null) sys.io.File.saveBytes('$songFolder/song/Inst.${Flags.SOUND_EXT}', creation.instBytes);
|
CoolUtil.safeSaveFile('$songFolder/meta${variant != null ? "-" + variant : ""}.json', Json.stringify(creation.meta, null, Flags.JSON_PRETTY_PRINT));
|
||||||
if (creation.voicesBytes != null) sys.io.File.saveBytes('$songFolder/song/Voices.${Flags.SOUND_EXT}', creation.voicesBytes);
|
if (creation.instBytes != null) sys.io.File.saveBytes('$songFolder/song/Inst$instSuffix.${Flags.SOUND_EXT}', creation.instBytes);
|
||||||
|
if (creation.voicesBytes != null) sys.io.File.saveBytes('$songFolder/song/Voices$vocalsSuffix.${Flags.SOUND_EXT}', creation.voicesBytes);
|
||||||
|
|
||||||
if (creation.playerVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Player.${Flags.SOUND_EXT}', creation.playerVocals);
|
if (creation.playerVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Player$vocalsSuffix.${Flags.SOUND_EXT}', creation.playerVocals);
|
||||||
if (creation.oppVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Opponent.${Flags.SOUND_EXT}', creation.oppVocals);
|
if (creation.oppVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Opponent$vocalsSuffix.${Flags.SOUND_EXT}', creation.oppVocals);
|
||||||
#end
|
#end
|
||||||
|
|
||||||
if (callback != null) callback(songFolder, creation);
|
if (callback != null) callback(songFolder);
|
||||||
|
|
||||||
// Add to List
|
// Add to List
|
||||||
freeplayList.songs.insert(0, creation.meta);
|
if (variant != null && curSong != null) {
|
||||||
insert(1, makeSongOption(creation.meta));
|
curSong.variants.push(variant);
|
||||||
|
curSong.metas.set(variant, creation.meta);
|
||||||
|
|
||||||
|
parent.tree.last().add(makeVariationOption(creation.meta));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
freeplayList.songs.insert(0, creation.meta);
|
||||||
|
insert(1, makeSongOption(creation.meta));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saveChart(name:String, data:ChartData) {
|
public function saveChart(name:String, data:ChartData) {
|
||||||
var difficultyAlreadyExists:Bool = curSong.difficulties.contains(name);
|
if (curSong.difficulties.contains(name)) {
|
||||||
if (difficultyAlreadyExists) {
|
|
||||||
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.chart-exists-title"), TU.translate("chartCreation.warnings.chart-exists-body"), [
|
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.chart-exists-title"), TU.translate("chartCreation.warnings.chart-exists-body"), [
|
||||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
||||||
]));
|
]));
|
||||||
@@ -113,11 +139,16 @@ class CharterSelectionScreen extends EditorTreeMenuScreen {
|
|||||||
|
|
||||||
// Add to List
|
// Add to List
|
||||||
curSong.difficulties.push(name);
|
curSong.difficulties.push(name);
|
||||||
parent.tree.last().insert(parent.tree.last().length - 1, makeChartOption(name, curSong.name));
|
|
||||||
|
var screen = parent.tree.last();
|
||||||
|
var idx = 0;
|
||||||
|
while (!(screen.members[idx] is Separator)) idx++;
|
||||||
|
screen.insert(idx, makeChartOption(name, curSong.variant != null && curSong.variant != "" ? curSong.variant : null, curSong.name));
|
||||||
|
|
||||||
// Add to Meta
|
// Add to Meta
|
||||||
var meta = Json.parse(sys.io.File.getContent('$songFolder/meta.json'));
|
var meta = Json.parse(sys.io.File.getContent('$songFolder/meta.json'));
|
||||||
if (meta.difficulties != null && !meta.difficulties.contains(name)) {
|
if (meta.difficulties == null) meta.difficulties = [];
|
||||||
|
if (!meta.difficulties.contains(name)) {
|
||||||
meta.difficulties.push(name);
|
meta.difficulties.push(name);
|
||||||
CoolUtil.safeSaveFile('$songFolder/meta.json', Chart.makeMetaSaveable(meta));
|
CoolUtil.safeSaveFile('$songFolder/meta.json', Chart.makeMetaSaveable(meta));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ typedef SongCreationData = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SongCreationScreen extends UISubstateWindow {
|
class SongCreationScreen extends UISubstateWindow {
|
||||||
private var onSave:Null<SongCreationData> -> Null<String -> SongCreationData -> Void> -> Void = null;
|
private var onSave:Null<SongCreationData> -> Null<String -> Void> -> Void = null;
|
||||||
|
|
||||||
public var songNameTextBox:UITextBox;
|
public var songNameTextBox:UITextBox;
|
||||||
public var bpmStepper:UINumericStepper;
|
public var bpmStepper:UINumericStepper;
|
||||||
@@ -42,7 +42,6 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
public var difficultiesTextBox:UITextBox;
|
public var difficultiesTextBox:UITextBox;
|
||||||
|
|
||||||
public var engineDropdown:UIDropDown;
|
public var engineDropdown:UIDropDown;
|
||||||
public var createSong:UIButton;
|
|
||||||
|
|
||||||
public var importInstExplorer:UIFileExplorer;
|
public var importInstExplorer:UIFileExplorer;
|
||||||
public var importVoicesExplorer:UIFileExplorer;
|
public var importVoicesExplorer:UIFileExplorer;
|
||||||
@@ -72,7 +71,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
|
|
||||||
public var curPage:Int = 0;
|
public var curPage:Int = 0;
|
||||||
|
|
||||||
public function new(?onSave:SongCreationData -> Null<String -> SongCreationData -> Void> -> Void) {
|
public function new(?onSave:SongCreationData -> Null<String -> Void> -> Void) {
|
||||||
super();
|
super();
|
||||||
if (onSave != null) this.onSave = onSave;
|
if (onSave != null) this.onSave = onSave;
|
||||||
}
|
}
|
||||||
@@ -190,14 +189,6 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
selectFormatGroup.add(engineDropdown);
|
selectFormatGroup.add(engineDropdown);
|
||||||
addLabelOn(engineDropdown, translate("importChartFormat"));
|
addLabelOn(engineDropdown, translate("importChartFormat"));
|
||||||
|
|
||||||
createSong = new UIButton(windowSpr.x + 20, windowSpr.y + windowSpr.bHeight - 16 - 32, "< " + translate("back"), function() {
|
|
||||||
winTitle = translate("win-title");
|
|
||||||
isImporting = false;
|
|
||||||
updatePagesTexts();
|
|
||||||
refreshPages();
|
|
||||||
}, 120);
|
|
||||||
selectFormatGroup.add(createSong);
|
|
||||||
|
|
||||||
var menuTitle:UIText;
|
var menuTitle:UIText;
|
||||||
importAudioGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, translate("importAudios"), 28));
|
importAudioGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, translate("importAudios"), 28));
|
||||||
|
|
||||||
@@ -341,7 +332,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
backButton.x = (saveButton.x = windowSpr.x + windowSpr.bWidth - 20 - 125) - 20 - saveButton.bWidth;
|
backButton.x = (saveButton.x = windowSpr.x + windowSpr.bWidth - 20 - 125) - 20 - saveButton.bWidth;
|
||||||
closeButton.x = (curPage > 0 ? backButton : saveButton).x - 20 - saveButton.bWidth;
|
closeButton.x = (curPage > 0 ? backButton : saveButton).x - 20 - saveButton.bWidth;
|
||||||
|
|
||||||
for (button in [saveButton, backButton, closeButton, importFrom, createSong])
|
for (button in [saveButton, backButton, closeButton, importFrom])
|
||||||
button.y = windowSpr.y + windowSpr.bHeight - 16 - 32;
|
button.y = windowSpr.y + windowSpr.bHeight - 16 - 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,6 +347,12 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
iconSprite.scrollFactor.set(1, 1);
|
iconSprite.scrollFactor.set(1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for variations
|
||||||
|
function formatMeta(meta:ChartMetaData):ChartMetaData return meta;
|
||||||
|
|
||||||
|
function getChartSavePath(meta:ChartMetaData, diff:String):String
|
||||||
|
return 'charts/${meta.variant != null && meta.variant != "" ? meta.variant + "/" : ""}$diff.json';
|
||||||
|
|
||||||
function saveSongInfo() {
|
function saveSongInfo() {
|
||||||
if (isImporting)
|
if (isImporting)
|
||||||
{
|
{
|
||||||
@@ -390,20 +387,21 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
codenameChart: true
|
codenameChart: true
|
||||||
};
|
};
|
||||||
PsychParser.parse(oldChart, base);
|
PsychParser.parse(oldChart, base);
|
||||||
|
var meta = formatMeta({
|
||||||
|
name: songId,
|
||||||
|
difficulties: ['normal'],
|
||||||
|
bpm: oldChart.bpm,
|
||||||
|
beatsPerMeasure: oldChart.beatsPerMeasure,
|
||||||
|
stepsPerBeat: oldChart.stepsPerBeat,
|
||||||
|
displayName: oldChart.song
|
||||||
|
});
|
||||||
if (onSave != null) onSave({
|
if (onSave != null) onSave({
|
||||||
meta: {
|
meta: meta,
|
||||||
name: songId,
|
|
||||||
difficulties: [songId],
|
|
||||||
bpm: oldChart.bpm,
|
|
||||||
beatsPerMeasure: oldChart.beatsPerMeasure,
|
|
||||||
stepsPerBeat: oldChart.stepsPerBeat,
|
|
||||||
displayName: oldChart.song
|
|
||||||
},
|
|
||||||
instBytes: importInstExplorer.file,
|
instBytes: importInstExplorer.file,
|
||||||
voicesBytes: importVoicesExplorer.file,
|
voicesBytes: importVoicesExplorer.file,
|
||||||
}, (songFolder:String, creation:SongCreationData) -> {
|
}, (songFolder:String) -> {
|
||||||
#if sys
|
#if sys
|
||||||
CoolUtil.safeSaveFile('$songFolder/charts/${songId}.json', Json.stringify(base, Flags.JSON_PRETTY_PRINT));
|
CoolUtil.safeSaveFile('$songFolder/${getChartSavePath(meta, "normal")}', Json.stringify(base, Flags.JSON_PRETTY_PRINT));
|
||||||
#end
|
#end
|
||||||
});
|
});
|
||||||
} catch (e:haxe.Exception) {
|
} catch (e:haxe.Exception) {
|
||||||
@@ -415,7 +413,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
for (stepper in [bpmStepper, beatsPerMeasureStepper, denominatorStepper])
|
for (stepper in [bpmStepper, beatsPerMeasureStepper, denominatorStepper])
|
||||||
@:privateAccess stepper.__onChange(stepper.label.text);
|
@:privateAccess stepper.__onChange(stepper.label.text);
|
||||||
|
|
||||||
var meta:ChartMetaData = {
|
var meta:ChartMetaData = formatMeta({
|
||||||
name: songNameTextBox.label.text,
|
name: songNameTextBox.label.text,
|
||||||
bpm: bpmStepper.value,
|
bpm: bpmStepper.value,
|
||||||
beatsPerMeasure: Std.int(beatsPerMeasureStepper.value),
|
beatsPerMeasure: Std.int(beatsPerMeasureStepper.value),
|
||||||
@@ -426,7 +424,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
opponentModeAllowed: opponentModeCheckbox.checked,
|
opponentModeAllowed: opponentModeCheckbox.checked,
|
||||||
coopAllowed: coopAllowedCheckbox.checked,
|
coopAllowed: coopAllowedCheckbox.checked,
|
||||||
difficulties: [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()],
|
difficulties: [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()],
|
||||||
};
|
});
|
||||||
|
|
||||||
if (onSave != null) onSave({
|
if (onSave != null) onSave({
|
||||||
meta: meta,
|
meta: meta,
|
||||||
@@ -445,6 +443,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
var meta:ChartMetaData = {name: songId};
|
var meta:ChartMetaData = {name: songId};
|
||||||
var diffCharts:Array<ChartDataWithInfo> = [];
|
var diffCharts:Array<ChartDataWithInfo> = [];
|
||||||
VSliceParser.parse(vslicemeta, vslicechart, meta, diffCharts, songId);
|
VSliceParser.parse(vslicemeta, vslicechart, meta, diffCharts, songId);
|
||||||
|
formatMeta(meta);
|
||||||
|
|
||||||
if (onSave != null) onSave({
|
if (onSave != null) onSave({
|
||||||
meta: meta,
|
meta: meta,
|
||||||
@@ -452,9 +451,9 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
voicesBytes: files.get('Voices.${Flags.SOUND_EXT}'), //it may exist
|
voicesBytes: files.get('Voices.${Flags.SOUND_EXT}'), //it may exist
|
||||||
playerVocals: files.get('Voices-${playData.characters.playerVocals != null ? playData.characters.playerVocals[0] : playData.characters.player}.${Flags.SOUND_EXT}'),
|
playerVocals: files.get('Voices-${playData.characters.playerVocals != null ? playData.characters.playerVocals[0] : playData.characters.player}.${Flags.SOUND_EXT}'),
|
||||||
oppVocals: files.get('Voices-${playData.characters.opponentVocals != null ? playData.characters.opponentVocals[0] : playData.characters.opponent}.${Flags.SOUND_EXT}'),
|
oppVocals: files.get('Voices-${playData.characters.opponentVocals != null ? playData.characters.opponentVocals[0] : playData.characters.opponent}.${Flags.SOUND_EXT}'),
|
||||||
}, (songFolder:String, creation:SongCreationData) -> {
|
}, (songFolder:String) -> {
|
||||||
#if sys
|
#if sys
|
||||||
for (diff in diffCharts) CoolUtil.safeSaveFile('$songFolder/charts/${diff.diffName}.json', Json.stringify(diff.chart, Flags.JSON_PRETTY_PRINT));
|
for (diff in diffCharts) CoolUtil.safeSaveFile('$songFolder/${getChartSavePath(meta, diff.diffName)}', Json.stringify(diff.chart, Flags.JSON_PRETTY_PRINT));
|
||||||
#end
|
#end
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package funkin.editors.charter;
|
||||||
|
|
||||||
|
import flixel.text.FlxText.FlxTextFormat;
|
||||||
|
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
||||||
|
import funkin.backend.chart.ChartData;
|
||||||
|
import funkin.editors.charter.SongCreationScreen;
|
||||||
|
|
||||||
|
class VariationCreationScreen extends SongCreationScreen {
|
||||||
|
public var parentMeta:ChartMetaData;
|
||||||
|
|
||||||
|
public function new(parent:ChartMetaData, ?onSave:SongCreationData -> Null<String -> Void> -> Void) {
|
||||||
|
super(onSave);
|
||||||
|
this.parentMeta = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
override function create() {
|
||||||
|
super.create();
|
||||||
|
|
||||||
|
songNameTextBox.label.text = translateMeta("variation");
|
||||||
|
cast(songNameTextBox.members[songNameTextBox.members.length - 1], UIText).text = translateMeta("variation");
|
||||||
|
|
||||||
|
cast(importIdTextBox.members[importIdTextBox.members.length - 1], UIText).applyMarkup(
|
||||||
|
translate("variation"),
|
||||||
|
[new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]
|
||||||
|
);
|
||||||
|
|
||||||
|
bpmStepper.value = parentMeta.bpm;
|
||||||
|
beatsPerMeasureStepper.value = parentMeta.beatsPerMeasure;
|
||||||
|
denominatorStepper.value = Std.int(16 / parentMeta.stepsPerBeat);
|
||||||
|
displayNameTextBox.label.text = parentMeta.displayName;
|
||||||
|
iconTextBox.label.text = parentMeta.icon;
|
||||||
|
opponentModeCheckbox.checked = parentMeta.opponentModeAllowed;
|
||||||
|
coopAllowedCheckbox.checked = parentMeta.coopAllowed;
|
||||||
|
colorWheel.setColor(parentMeta.color);
|
||||||
|
difficultiesTextBox.label.text = parentMeta.difficulties.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
override function formatMeta(meta:ChartMetaData):ChartMetaData {
|
||||||
|
meta.variant = meta.name;
|
||||||
|
meta.vocalsSuffix = meta.instSuffix = '-${meta.variant}';
|
||||||
|
meta.name = parentMeta.name;
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,7 +31,6 @@ class UIColorwheel extends UISliceSprite {
|
|||||||
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
||||||
|
|
||||||
colorPickerShader = new CustomShader("engine/colorPicker");
|
colorPickerShader = new CustomShader("engine/colorPicker");
|
||||||
colorPickerShader.hset("hue", hue);
|
|
||||||
|
|
||||||
colorPicker = new FlxSprite(x + 12.5, (y + 125/2) - (100/2)).makeGraphic(100, 100, FlxColor.TRANSPARENT);
|
colorPicker = new FlxSprite(x + 12.5, (y + 125/2) - (100/2)).makeGraphic(100, 100, FlxColor.TRANSPARENT);
|
||||||
colorPicker.drawRoundRect(0, 0, 100, 100, 10, 10, FlxColor.WHITE);
|
colorPicker.drawRoundRect(0, 0, 100, 100, 10, 10, FlxColor.WHITE);
|
||||||
@@ -91,6 +90,11 @@ class UIColorwheel extends UISliceSprite {
|
|||||||
updateWheel(false);
|
updateWheel(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setColor(color:FlxColor) {
|
||||||
|
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
||||||
|
updateWheel(false);
|
||||||
|
}
|
||||||
|
|
||||||
inline function updateColorPickerSelector()
|
inline function updateColorPickerSelector()
|
||||||
colorPickerSelector.selector.setPosition(colorPicker.x + (colorPicker.width *saturation) - 8, colorPicker.y + (colorPicker.height + (colorPicker.height * -brightness))- 8);
|
colorPickerSelector.selector.setPosition(colorPicker.x + (colorPicker.width *saturation) - 8, colorPicker.y + (colorPicker.height + (colorPicker.height * -brightness))- 8);
|
||||||
|
|
||||||
|
|||||||
@@ -128,11 +128,12 @@ class TreeMenuScreen extends FlxSpriteGroup {
|
|||||||
var i = curSelected, y = initY, object:FlxSprite = null, itemHeight:Float = 0;
|
var i = curSelected, y = initY, object:FlxSprite = null, itemHeight:Float = 0;
|
||||||
|
|
||||||
inline function updateItem() {
|
inline function updateItem() {
|
||||||
object.y = CoolUtil.fpsLerp(object.y, y - (itemHeight = object.height) * 0.5, r);
|
object.y = CoolUtil.fpsLerp(object.y, y - itemHeight * 0.5, r);
|
||||||
object.x = x + 100 - Math.pow(Math.abs((object.y - (FlxG.height - itemHeight) * 0.5) / itemHeight / FlxG.height * FlxG.initialHeight), 1.6) * 15;
|
object.x = x + 100 - Math.pow(Math.abs((object.y - (FlxG.height - itemHeight) * 0.5) / itemHeight / FlxG.height * FlxG.initialHeight), 1.6) * 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i < length) if ((object = members[i++]) != null) {
|
while (i < length) if ((object = members[i++]) != null) {
|
||||||
|
itemHeight = object.height;
|
||||||
updateItem();
|
updateItem();
|
||||||
y += itemHeight;
|
y += itemHeight;
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,7 @@ class TreeMenuScreen extends FlxSpriteGroup {
|
|||||||
y = initY;
|
y = initY;
|
||||||
i = curSelected;
|
i = curSelected;
|
||||||
while (i-- > 0) if ((object = members[i]) != null) {
|
while (i-- > 0) if ((object = members[i]) != null) {
|
||||||
y -= itemHeight;
|
y -= (itemHeight = object.height);
|
||||||
updateItem();
|
updateItem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class NewOption extends TextOption {
|
|||||||
|
|
||||||
public function new(name:String, desc:String, callback:Void->Void) {
|
public function new(name:String, desc:String, callback:Void->Void) {
|
||||||
super(name, desc, callback);
|
super(name, desc, callback);
|
||||||
itemHeight = 160;
|
itemHeight = 150;
|
||||||
|
|
||||||
__text.color = FlxColor.LIME;
|
__text.color = FlxColor.LIME;
|
||||||
__text.x = 100;
|
__text.x = 100;
|
||||||
|
|||||||
@@ -49,8 +49,9 @@ class FunkinSave {
|
|||||||
__load();
|
__load();
|
||||||
if (save.data.highscores != null) {
|
if (save.data.highscores != null) {
|
||||||
var temp;
|
var temp;
|
||||||
for (entryData in Reflect.fields(save.data.highscores)) if ((temp = __getHighscoreEntry(entryData)) != null)
|
for (entryData in Reflect.fields(save.data.highscores))
|
||||||
highscores.set(temp, Reflect.field(save.data.highscores, entryData));
|
if ((temp = __getHighscoreEntry(entryData)) != null && Reflect.field(save.data.highscores, entryData) != null)
|
||||||
|
highscores.set(temp, Reflect.field(save.data.highscores, entryData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user