added ability to save charts
This commit is contained in:
@@ -87,12 +87,14 @@ class Paths
|
||||
return OpenFlAssets.exists(diff) ? diff : getPath('songs/${song.toLowerCase()}/song/Inst.$SOUND_EXT', null);
|
||||
}
|
||||
|
||||
inline static public function image(key:String, ?library:String, checkForAtlas:Bool = false)
|
||||
static public function image(key:String, ?library:String, checkForAtlas:Bool = false)
|
||||
{
|
||||
var atlasPath = checkForAtlas ? getPath('images/$key/spritemap.png', library) : null;
|
||||
var multiplePath = checkForAtlas ? getPath('images/$key/1.png', library) : null;
|
||||
if (atlasPath != null && OpenFlAssets.exists(atlasPath)) return atlasPath.substr(0, atlasPath.length - 14);
|
||||
if (multiplePath != null && OpenFlAssets.exists(multiplePath)) return multiplePath.substr(0, multiplePath.length - 6);
|
||||
if (checkForAtlas) {
|
||||
var atlasPath = getPath('images/$key/spritemap.png', library);
|
||||
var multiplePath = getPath('images/$key/1.png', library);
|
||||
if (atlasPath != null && OpenFlAssets.exists(atlasPath)) return atlasPath.substr(0, atlasPath.length - 14);
|
||||
if (multiplePath != null && OpenFlAssets.exists(multiplePath)) return multiplePath.substr(0, multiplePath.length - 6);
|
||||
}
|
||||
return getPath('images/$key.png', library);
|
||||
}
|
||||
|
||||
@@ -115,17 +117,7 @@ class Paths
|
||||
difficulty = difficulty.toLowerCase();
|
||||
song = song.toLowerCase();
|
||||
|
||||
//var difficultyEnd = (difficulty == "normal") ? "" : '-$difficulty';
|
||||
|
||||
// songs/your-song/charts/hard.json
|
||||
var p = getPath('songs/$song/charts/$difficulty.json', null);
|
||||
if (OpenFlAssets.exists(p)) return p;
|
||||
|
||||
// data/charts/your-song/hard.json
|
||||
var p = json('charts/$song/$difficulty');
|
||||
if (OpenFlAssets.exists(p)) return p;
|
||||
|
||||
return p; // returns the normal one so that it shows the correct path in the error message.
|
||||
return getPath('songs/$song/charts/$difficulty.json', null);
|
||||
}
|
||||
|
||||
inline static public function font(key:String)
|
||||
|
||||
@@ -158,8 +158,6 @@ class Chart {
|
||||
var filteredChart = filterChartForSaving(chart, saveSettings.saveMetaInChart);
|
||||
var meta = filteredChart.meta;
|
||||
|
||||
// idk how null reacts to it so better be sure
|
||||
|
||||
#if sys
|
||||
if (!FileSystem.exists('${songFolderPath}\\charts\\'))
|
||||
FileSystem.createDirectory('${songFolderPath}\\charts\\');
|
||||
@@ -169,6 +167,7 @@ class Chart {
|
||||
|
||||
File.saveContent(chartPath, Json.stringify(filteredChart, null, saveSettings.prettyPrint == true ? "\t" : null));
|
||||
|
||||
// idk how null reacts to it so better be sure
|
||||
if (saveSettings.overrideExistingMeta == true || !FileSystem.exists(metaPath))
|
||||
File.saveContent(metaPath, Json.stringify(meta, null, saveSettings.prettyPrint == true ? "\t" : null));
|
||||
#end
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package funkin.editors;
|
||||
|
||||
#if desktop
|
||||
import sys.io.File;
|
||||
#end
|
||||
import haxe.io.Path;
|
||||
import lime.ui.FileDialog;
|
||||
import openfl.net.FileReference;
|
||||
import openfl.events.Event;
|
||||
import openfl.events.IOErrorEvent;
|
||||
|
||||
class SaveSubstate extends MusicBeatSubstate {
|
||||
public var saveOptions:Map<String, Bool>;
|
||||
public var options:SaveSubstateData;
|
||||
|
||||
public var data:String;
|
||||
|
||||
public var cam:FlxCamera;
|
||||
|
||||
public function new(data:String, ?options:SaveSubstateData, ?saveOptions:Map<String, Bool>) {
|
||||
super();
|
||||
this.data = data;
|
||||
|
||||
if (saveOptions == null)
|
||||
saveOptions = [];
|
||||
this.saveOptions = saveOptions;
|
||||
|
||||
if (options != null)
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
|
||||
var fileDialog = new FileDialog();
|
||||
fileDialog.onCancel.add(function() {
|
||||
trace("h");
|
||||
close();
|
||||
});
|
||||
fileDialog.onSelect.add(function(str) {
|
||||
#if desktop
|
||||
File.saveContent(str, data);
|
||||
#end
|
||||
trace("h");
|
||||
close();
|
||||
});
|
||||
fileDialog.browse(SAVE, options.saveExt.getDefault(Path.extension(options.defaultSaveFile)), options.defaultSaveFile);
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
parent.persistentUpdate = false;
|
||||
}
|
||||
|
||||
private function onError(_) {
|
||||
// TODO: error handling
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
typedef SaveSubstateData = {
|
||||
var ?defaultSaveFile:String;
|
||||
var ?saveExt:String;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package funkin.editors.charter;
|
||||
|
||||
import haxe.Json;
|
||||
import flixel.input.keyboard.FlxKey;
|
||||
import flixel.sound.FlxSound;
|
||||
import flixel.util.FlxSort;
|
||||
@@ -95,6 +96,17 @@ class Charter extends UIState {
|
||||
label: "New"
|
||||
},
|
||||
null,
|
||||
{
|
||||
label: "Save",
|
||||
keybind: [CONTROL, S],
|
||||
onSelect: _file_save,
|
||||
},
|
||||
{
|
||||
label: "Save As...",
|
||||
keybind: [CONTROL, SHIFT, S],
|
||||
onSelect: _file_saveas,
|
||||
},
|
||||
null,
|
||||
{
|
||||
label: "Exit",
|
||||
onSelect: _file_exit
|
||||
@@ -356,13 +368,14 @@ class Charter extends UIState {
|
||||
loadSong();
|
||||
}
|
||||
|
||||
var instPath:String;
|
||||
public function loadSong() {
|
||||
if (__reload)
|
||||
PlayState.loadSong(__song, __diff, false, false);
|
||||
|
||||
Conductor.setupSong(PlayState.SONG);
|
||||
|
||||
FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff)));
|
||||
FlxG.sound.setMusic(FlxG.sound.load(instPath = Paths.inst(__song, __diff)));
|
||||
vocals = FlxG.sound.load(Paths.voices(__song, __diff));
|
||||
vocals.group = FlxG.sound.defaultMusicGroup;
|
||||
|
||||
@@ -469,20 +482,31 @@ class Charter extends UIState {
|
||||
if (!FlxG.keys.pressed.SHIFT)
|
||||
verticalChange = CoolUtil.floorInt(verticalChange);
|
||||
var horizontalChange:Int = CoolUtil.floorInt((mousePos.x - dragStartPos.x) / 40);
|
||||
addToUndo(CNoteDrag([for(s in selection) {
|
||||
var drags = [];
|
||||
var deletes = [];
|
||||
for(s in selection) {
|
||||
var oldStep = s.step;
|
||||
var oldID = s.id;
|
||||
|
||||
s.updatePos(s.step + verticalChange, s.id + horizontalChange, s.susLength, s.type);
|
||||
var newID = s.id + horizontalChange;
|
||||
var newStep = s.step + verticalChange;
|
||||
if (newStep < 0 || newID < 0 || newID >= strumLines.length * 4) {
|
||||
s.updatePos(s.step, s.id, s.susLength, s.type);
|
||||
deletes.push(s);
|
||||
} else {
|
||||
s.updatePos(newStep, newID, s.susLength, s.type);
|
||||
|
||||
{
|
||||
note: s,
|
||||
oldID: oldID,
|
||||
oldStep: oldStep,
|
||||
newID: s.id,
|
||||
newStep: s.step
|
||||
};
|
||||
}]));
|
||||
drags.push({
|
||||
note: s,
|
||||
oldID: oldID,
|
||||
oldStep: oldStep,
|
||||
newID: s.id,
|
||||
newStep: s.step
|
||||
});
|
||||
}
|
||||
}
|
||||
deleteNotes(deletes, false);
|
||||
addToUndo(CNoteDrag(drags, deletes));
|
||||
gridActionType = NONE;
|
||||
}
|
||||
case NONE:
|
||||
@@ -527,23 +551,25 @@ class Charter extends UIState {
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteNote(note:CharterNote):CharterNote {
|
||||
public function deleteNote(note:CharterNote, addToUndo:Bool = true):CharterNote {
|
||||
if (note == null) return note;
|
||||
|
||||
notesGroup.remove(note, true);
|
||||
note.kill();
|
||||
addToUndo(CDeleteNotes([note]));
|
||||
if (addToUndo)
|
||||
this.addToUndo(CDeleteNotes([note]));
|
||||
return null;
|
||||
}
|
||||
|
||||
public function deleteNotes(notes:Array<CharterNote>) {
|
||||
public function deleteNotes(notes:Array<CharterNote>, addToUndo:Bool = true) {
|
||||
if (notes.length <= 0) return [];
|
||||
|
||||
for(note in notes) {
|
||||
notesGroup.remove(note, true);
|
||||
note.kill();
|
||||
}
|
||||
addToUndo(CDeleteNotes(notes));
|
||||
if (addToUndo)
|
||||
this.addToUndo(CDeleteNotes(notes));
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -638,6 +664,32 @@ class Charter extends UIState {
|
||||
function _file_exit(_) {
|
||||
FlxG.switchState(new CharterSelection());
|
||||
}
|
||||
function _file_save(_) {
|
||||
#if sys
|
||||
for(assetPath in [Paths.chart(__song, __diff.toLowerCase()), instPath]) {
|
||||
var path = Assets.getPath(assetPath);
|
||||
var filteredPath = path.substr(0, path.lastIndexOf(assetPath == instPath ? '/song/' : '/charts/'));
|
||||
trace(filteredPath);
|
||||
saveTo(filteredPath);
|
||||
return;
|
||||
}
|
||||
#end
|
||||
_file_saveas(_);
|
||||
}
|
||||
|
||||
function _file_saveas(_) {
|
||||
openSubState(new SaveSubstate(Json.stringify(Chart.filterChartForSaving(PlayState.SONG, true)), {
|
||||
defaultSaveFile: '${__diff.toLowerCase()}.json'
|
||||
}));
|
||||
}
|
||||
|
||||
#if sys
|
||||
function saveTo(path:String) {
|
||||
buildChart();
|
||||
Chart.save(path, PlayState.SONG, __diff.toLowerCase());
|
||||
}
|
||||
#end
|
||||
|
||||
function _edit_copy(_) {
|
||||
var minStep:Float = selection[0].step;
|
||||
for(s in selection)
|
||||
@@ -694,9 +746,14 @@ class Charter extends UIState {
|
||||
case CSustainChange(changes):
|
||||
for(n in changes)
|
||||
n.note.updatePos(n.note.step, n.note.id, n.before, n.note.type);
|
||||
case CNoteDrag(notes):
|
||||
case CNoteDrag(notes, deletes):
|
||||
for(n in notes)
|
||||
n.note.updatePos(n.oldStep, n.oldID, n.note.susLength, n.note.type);
|
||||
for(d in deletes) {
|
||||
notesGroup.add(d);
|
||||
d.revive();
|
||||
}
|
||||
selection = [for(n in notes) n.note];
|
||||
|
||||
}
|
||||
if (v != null)
|
||||
@@ -736,9 +793,11 @@ class Charter extends UIState {
|
||||
case CSustainChange(changes):
|
||||
for(n in changes)
|
||||
n.note.updatePos(n.note.step, n.note.id, n.after, n.note.type);
|
||||
case CNoteDrag(notes):
|
||||
case CNoteDrag(notes, deletes):
|
||||
for(n in notes)
|
||||
n.note.updatePos(n.newStep, n.newID, n.note.susLength, n.note.type);
|
||||
deleteNotes(deletes, false);
|
||||
selection = [for(n in notes) n.note];
|
||||
}
|
||||
if (v != null)
|
||||
undoList.insert(0, v);
|
||||
@@ -862,7 +921,7 @@ enum CharterChange {
|
||||
CSustainChange(notes:Array<NoteSustainChange>);
|
||||
CCreateNotes(notes:Array<CharterNote>);
|
||||
CDeleteNotes(notes:Array<CharterNote>);
|
||||
CNoteDrag(notes:Array<NoteDragChange>);
|
||||
CNoteDrag(notes:Array<NoteDragChange>, deletes:Array<CharterNote>);
|
||||
}
|
||||
|
||||
enum CharterCopyboardObject {
|
||||
|
||||
@@ -19,6 +19,9 @@ class UIUtil {
|
||||
* @param topMenuOptions
|
||||
*/
|
||||
public static function processShortcuts(topMenuOptions:Array<UIContextMenuOption>) {
|
||||
var maxKeyLength = 0;
|
||||
var curTopMenuOption = null;
|
||||
|
||||
for(o in topMenuOptions) {
|
||||
if (o == null) continue;
|
||||
|
||||
@@ -56,16 +59,22 @@ class UIUtil {
|
||||
if (!needsShift && FlxG.keys.pressed.SHIFT) continue;
|
||||
if (!pressed || !justPressed) continue;
|
||||
|
||||
if (o.onSelect != null)
|
||||
o.onSelect(o);
|
||||
|
||||
return true;
|
||||
if (maxKeyLength < o.keybinds.length) {
|
||||
maxKeyLength = o.keybinds.length;
|
||||
curTopMenuOption = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (o.childs != null && processShortcuts(o.childs))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (curTopMenuOption != null) {
|
||||
if (curTopMenuOption.onSelect != null)
|
||||
curTopMenuOption.onSelect(curTopMenuOption);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user