mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-22 15:48:08 -05:00
Merge remote-tracking branch 'origin/rewrite/master' into bugfix/conductor-rewrite
This commit is contained in:
commit
a1002c4756
38 changed files with 426 additions and 200 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -4,8 +4,7 @@
|
|||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
// Compilation server issues can cause auto-cleanup to remove valid imports.
|
||||
"source.organizeImports": false
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
"editor.defaultFormatter": "nadako.vshaxe",
|
||||
"editor.tabSize": 2
|
||||
|
|
10
Project.xml
10
Project.xml
|
@ -99,18 +99,20 @@
|
|||
|
||||
<haxelib name="flixel-addons" /> <!-- Additional utilities for Flixel -->
|
||||
<haxelib name="hscript" /> <!-- Scripting -->
|
||||
<haxelib name="flixel-ui" /> <!-- UI framework (deprecate this? -->
|
||||
<haxelib name="flixel-ui" /> <!-- UI framework (DEPRECATED) -->
|
||||
<haxelib name="haxeui-core" /> <!-- UI framework -->
|
||||
<haxelib name="haxeui-flixel" /> <!-- Integrate HaxeUI with Flixel -->
|
||||
<haxelib name="flixel-text-input" /> <!-- Improved text field rendering for HaxeUI -->
|
||||
<haxelib name="polymod" /> <!-- Modding framework -->
|
||||
<haxelib name="flxanimate" /> <!-- Texture atlas rendering -->
|
||||
<haxelib name="hxCodec" /> <!-- Video playback -->
|
||||
|
||||
<haxelib name="json2object" /> <!-- JSON parsing -->
|
||||
<haxelib name="tink_json" /> <!-- JSON parsing -->
|
||||
<haxelib name="tink_json" /> <!-- JSON parsing (DEPRECATED) -->
|
||||
<haxelib name="thx.semver" /> <!-- Version string handling -->
|
||||
|
||||
<haxelib name="hxcpp-debug-server" if="desktop debug" /> <!-- VSCode debug support -->
|
||||
|
||||
<haxelib name="thx.semver" />
|
||||
<haxelib name="hxcpp-debug-server" if="desktop debug" />
|
||||
<!--Disable the Flixel core focus lost screen-->
|
||||
<haxedef name="FLX_NO_FOCUS_LOST_SCREEN" />
|
||||
<!--Disable the Flixel core debugger. Automatically gets set whenever you compile in release mode!-->
|
||||
|
|
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 54065ef5b7dec959aea478fd79b44e692e7c248a
|
||||
Subproject commit 309e60ceea2c298e8bf34575359c74f64833479b
|
33
hmm.json
33
hmm.json
|
@ -11,15 +11,20 @@
|
|||
"name": "flixel",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "da04cbda49a4c5eebe93fb61296dbaf4f0f1b556",
|
||||
"url": "https://github.com/EliteMasterEric/flixel"
|
||||
"ref": "a83738673e7edbf8acba3a1426af284dfe6719fe",
|
||||
"url": "https://github.com/FunkinCrew/flixel"
|
||||
},
|
||||
{
|
||||
"name": "flixel-addons",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "c8c41e26d463aaf2edc0582fb23b6e228235bd16",
|
||||
"url": "https://github.com/EliteMasterEric/flixel-addons"
|
||||
"ref": "fd3aecdeb5635fa0428dffee204fc78fc26b5885",
|
||||
"url": "https://github.com/FunkinCrew/flixel-addons"
|
||||
},
|
||||
{
|
||||
"name": "flixel-text-input",
|
||||
"type": "haxelib",
|
||||
"version": "1.1.0"
|
||||
},
|
||||
{
|
||||
"name": "flixel-ui",
|
||||
|
@ -32,8 +37,8 @@
|
|||
"name": "flxanimate",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "dd2903f7dc7024335b981edf2a770760cec912e1",
|
||||
"url": "https://github.com/ninjamuffin99/flxanimate"
|
||||
"ref": "d7c5621be742e2c98d523dfe5af7528835eaff1e",
|
||||
"url": "https://github.com/FunkinCrew/flxanimate"
|
||||
},
|
||||
{
|
||||
"name": "format",
|
||||
|
@ -49,14 +54,14 @@
|
|||
"name": "haxeui-core",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "1e40adb6bf58b0eb6a5600f75face565b647ab36",
|
||||
"ref": "5086e59e7551d775ed4d1fb0188e31de22d1312b",
|
||||
"url": "https://github.com/haxeui/haxeui-core"
|
||||
},
|
||||
{
|
||||
"name": "haxeui-flixel",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "26b6bb132c92dfa9b77b4a61eaeda8f9a9efda98",
|
||||
"ref": "2b9cff727999b53ed292b1675ac1c9089ac77600",
|
||||
"url": "https://github.com/haxeui/haxeui-flixel"
|
||||
},
|
||||
{
|
||||
|
@ -95,15 +100,15 @@
|
|||
"name": "json2object",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "f4df19cfa196f85eece55c3367021fc965f1fa9a",
|
||||
"url": "https://github.com/EliteMasterEric/json2object"
|
||||
"ref": "a8c26f18463c98da32f744c214fe02273e1823fa",
|
||||
"url": "https://github.com/FunkinCrew/json2object"
|
||||
},
|
||||
{
|
||||
"name": "lime",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "737b86f121cdc90358d59e2e527934f267c94a2c",
|
||||
"url": "https://github.com/EliteMasterEric/lime"
|
||||
"url": "https://github.com/FunkinCrew/lime"
|
||||
},
|
||||
{
|
||||
"name": "mconsole",
|
||||
|
@ -124,21 +129,21 @@
|
|||
"type": "git",
|
||||
"dir": "src",
|
||||
"ref": "master",
|
||||
"url": "https://github.com/EliteMasterEric/mockatoo"
|
||||
"url": "https://github.com/FunkinCrew/mockatoo"
|
||||
},
|
||||
{
|
||||
"name": "munit",
|
||||
"type": "git",
|
||||
"dir": "src",
|
||||
"ref": "master",
|
||||
"url": "https://github.com/EliteMasterEric/MassiveUnit"
|
||||
"url": "https://github.com/FunkinCrew/MassiveUnit"
|
||||
},
|
||||
{
|
||||
"name": "openfl",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "f229d76361c7e31025a048fe7909847f75bb5d5e",
|
||||
"url": "https://github.com/EliteMasterEric/openfl"
|
||||
"url": "https://github.com/FunkinCrew/openfl"
|
||||
},
|
||||
{
|
||||
"name": "polymod",
|
||||
|
|
|
@ -11,6 +11,7 @@ import funkin.data.song.SongDataUtils;
|
|||
* A core class which handles musical timing throughout the game,
|
||||
* both in gameplay and in menus.
|
||||
*/
|
||||
@:nullSafety
|
||||
class Conductor
|
||||
{
|
||||
// onBeatHit is called every quarter note
|
||||
|
@ -61,7 +62,7 @@ class Conductor
|
|||
/**
|
||||
* The most recent time change for the current song position.
|
||||
*/
|
||||
public var currentTimeChange(default, null):SongTimeChange;
|
||||
public var currentTimeChange(default, null):Null<SongTimeChange>;
|
||||
|
||||
/**
|
||||
* The current position in the song in milliseconds.
|
||||
|
@ -156,32 +157,32 @@ class Conductor
|
|||
/**
|
||||
* Current position in the song, in measures.
|
||||
*/
|
||||
public var currentMeasure(default, null):Int;
|
||||
public var currentMeasure(default, null):Int = 0;
|
||||
|
||||
/**
|
||||
* Current position in the song, in beats.
|
||||
*/
|
||||
public var currentBeat(default, null):Int;
|
||||
public var currentBeat(default, null):Int = 0;
|
||||
|
||||
/**
|
||||
* Current position in the song, in steps.
|
||||
*/
|
||||
public var currentStep(default, null):Int;
|
||||
public var currentStep(default, null):Int = 0;
|
||||
|
||||
/**
|
||||
* Current position in the song, in measures and fractions of a measure.
|
||||
*/
|
||||
public var currentMeasureTime(default, null):Float;
|
||||
public var currentMeasureTime(default, null):Float = 0;
|
||||
|
||||
/**
|
||||
* Current position in the song, in beats and fractions of a measure.
|
||||
*/
|
||||
public var currentBeatTime(default, null):Float;
|
||||
public var currentBeatTime(default, null):Float = 0;
|
||||
|
||||
/**
|
||||
* Current position in the song, in steps and fractions of a step.
|
||||
*/
|
||||
public var currentStepTime(default, null):Float;
|
||||
public var currentStepTime(default, null):Float = 0;
|
||||
|
||||
/**
|
||||
* An offset tied to the current chart file to compensate for a delay in the instrumental.
|
||||
|
|
|
@ -178,7 +178,31 @@ class DataParse
|
|||
switch (json.value)
|
||||
{
|
||||
case JObject(fields):
|
||||
return cast Tools.getValue(json);
|
||||
var result:LegacyNoteSection =
|
||||
{
|
||||
mustHitSection: false,
|
||||
sectionNotes: [],
|
||||
};
|
||||
for (field in fields)
|
||||
{
|
||||
switch (field.name)
|
||||
{
|
||||
case 'sectionNotes':
|
||||
result.sectionNotes = legacyNotes(field.value, field.name);
|
||||
|
||||
case 'mustHitSection':
|
||||
result.mustHitSection = Tools.getValue(field.value);
|
||||
case 'typeOfSection':
|
||||
result.typeOfSection = Tools.getValue(field.value);
|
||||
case 'lengthInSteps':
|
||||
result.lengthInSteps = Tools.getValue(field.value);
|
||||
case 'changeBPM':
|
||||
result.changeBPM = Tools.getValue(field.value);
|
||||
case 'bpm':
|
||||
result.bpm = Tools.getValue(field.value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
default:
|
||||
throw 'Expected property $name to be an object, but it was ${json.value}.';
|
||||
}
|
||||
|
@ -189,7 +213,12 @@ class DataParse
|
|||
switch (json.value)
|
||||
{
|
||||
case JObject(fields):
|
||||
return cast Tools.getValue(json);
|
||||
var result = {};
|
||||
for (field in fields)
|
||||
{
|
||||
Reflect.setField(result, field.name, legacyNoteSectionArray(field.value, field.name));
|
||||
}
|
||||
return result;
|
||||
default:
|
||||
throw 'Expected property $name to be an object, but it was ${json.value}.';
|
||||
}
|
||||
|
@ -211,13 +240,13 @@ class DataParse
|
|||
switch (json.value)
|
||||
{
|
||||
case JArray(values):
|
||||
// var time:Null<Float> = values[0] == null ? null : Tools.getValue(values[0]);
|
||||
// var data:Null<Int> = values[1] == null ? null : Tools.getValue(values[1]);
|
||||
// var length:Null<Float> = values[2] == null ? null : Tools.getValue(values[2]);
|
||||
// var alt:Null<Bool> = values[3] == null ? null : Tools.getValue(values[3]);
|
||||
var time:Null<Float> = values[0] == null ? null : Tools.getValue(values[0]);
|
||||
var data:Null<Int> = values[1] == null ? null : Tools.getValue(values[1]);
|
||||
var length:Null<Float> = values[2] == null ? null : Tools.getValue(values[2]);
|
||||
var alt:Null<Bool> = values[3] == null ? null : Tools.getValue(values[3]);
|
||||
|
||||
// return new LegacyNote(time, data, length, alt);
|
||||
return null;
|
||||
return new LegacyNote(time, data, length, alt);
|
||||
// return null;
|
||||
default:
|
||||
throw 'Expected property $name to be a note, but it was ${json.value}.';
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ class LevelRegistry extends BaseRegistry<Level, LevelData>
|
|||
// JsonParser does not take type parameters,
|
||||
// otherwise this function would be in BaseRegistry.
|
||||
var parser = new json2object.JsonParser<LevelData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadEntryFile(id))
|
||||
{
|
||||
|
@ -57,6 +58,7 @@ class LevelRegistry extends BaseRegistry<Level, LevelData>
|
|||
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<LevelData>
|
||||
{
|
||||
var parser = new json2object.JsonParser<LevelData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(contents, fileName);
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
|
|
@ -35,6 +35,7 @@ class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData>
|
|||
// JsonParser does not take type parameters,
|
||||
// otherwise this function would be in BaseRegistry.
|
||||
var parser = new json2object.JsonParser<NoteStyleData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadEntryFile(id))
|
||||
{
|
||||
|
@ -62,6 +63,7 @@ class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData>
|
|||
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<NoteStyleData>
|
||||
{
|
||||
var parser = new json2object.JsonParser<NoteStyleData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(contents, fileName);
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
|
|
@ -747,7 +747,7 @@ class SongNoteDataRaw
|
|||
/**
|
||||
* The kind of the note.
|
||||
* This can allow the note to include information used for custom behavior.
|
||||
* Defaults to blank or `"normal"`.
|
||||
* Defaults to blank or `Constants.DEFAULT_DIFFICULTY`.
|
||||
*/
|
||||
@:alias("k")
|
||||
@:default("normal")
|
||||
|
|
|
@ -230,6 +230,7 @@ class SongDataUtils
|
|||
trace('Read ${notesString.length} characters from clipboard.');
|
||||
|
||||
var parser = new json2object.JsonParser<SongClipboardItems>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(notesString, 'clipboard');
|
||||
if (parser.errors.length > 0)
|
||||
{
|
||||
|
|
|
@ -126,6 +126,8 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
|
||||
|
||||
var parser = new json2object.JsonParser<SongMetadata>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadEntryMetadataFile(id, variation))
|
||||
{
|
||||
case {fileName: fileName, contents: contents}:
|
||||
|
@ -147,6 +149,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
|
||||
|
||||
var parser = new json2object.JsonParser<SongMetadata>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(contents, fileName);
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
@ -206,6 +209,8 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
|
||||
|
||||
var parser = new json2object.JsonParser<SongMetadata_v2_1_0>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadEntryMetadataFile(id, variation))
|
||||
{
|
||||
case {fileName: fileName, contents: contents}:
|
||||
|
@ -226,6 +231,8 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
|
||||
|
||||
var parser = new json2object.JsonParser<SongMetadata_v2_0_0>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadEntryMetadataFile(id, variation))
|
||||
{
|
||||
case {fileName: fileName, contents: contents}:
|
||||
|
@ -244,6 +251,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
function parseEntryMetadataRaw_v2_1_0(contents:String, ?fileName:String = 'raw'):Null<SongMetadata>
|
||||
{
|
||||
var parser = new json2object.JsonParser<SongMetadata_v2_1_0>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(contents, fileName);
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
@ -257,6 +265,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
function parseEntryMetadataRaw_v2_0_0(contents:String, ?fileName:String = 'raw'):Null<SongMetadata>
|
||||
{
|
||||
var parser = new json2object.JsonParser<SongMetadata_v2_0_0>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(contents, fileName);
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
@ -272,6 +281,8 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
|
||||
|
||||
var parser = new json2object.JsonParser<SongMusicData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadMusicDataFile(id, variation))
|
||||
{
|
||||
case {fileName: fileName, contents: contents}:
|
||||
|
@ -291,6 +302,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
public function parseMusicDataRaw(contents:String, ?fileName:String = 'raw'):Null<SongMusicData>
|
||||
{
|
||||
var parser = new json2object.JsonParser<SongMusicData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(contents, fileName);
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
@ -334,6 +346,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
|
||||
|
||||
var parser = new json2object.JsonParser<SongChartData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadEntryChartFile(id, variation))
|
||||
{
|
||||
|
@ -356,6 +369,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
|
||||
|
||||
var parser = new json2object.JsonParser<SongChartData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(contents, fileName);
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
|
|
@ -68,6 +68,7 @@ class ChartManifestData
|
|||
public static function deserialize(contents:String):Null<ChartManifestData>
|
||||
{
|
||||
var parser = new json2object.JsonParser<ChartManifestData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(contents, 'manifest.json');
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
|
|
@ -19,7 +19,8 @@ class LegacySongData
|
|||
|
||||
@:jcustomparse(funkin.data.DataParse.eitherLegacyScrollSpeeds)
|
||||
public var speed:Either<Float, LegacyScrollSpeeds>;
|
||||
public var stageDefault:String;
|
||||
@:optional
|
||||
public var stageDefault:Null<String>;
|
||||
public var bpm:Float;
|
||||
|
||||
@:jcustomparse(funkin.data.DataParse.eitherLegacyNoteData)
|
||||
|
|
|
@ -14,6 +14,7 @@ class FNFLegacyImporter
|
|||
public static function parseLegacyDataRaw(input:String, fileName:String = 'raw'):FNFLegacyData
|
||||
{
|
||||
var parser = new json2object.JsonParser<FNFLegacyData>();
|
||||
parser.ignoreUnknownVariables = true; // Set to true to ignore extra variables that might be included in the JSON.
|
||||
parser.fromJson(input, fileName);
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
@ -185,15 +186,34 @@ class FNFLegacyImporter
|
|||
return result;
|
||||
}
|
||||
|
||||
static final STRUMLINE_SIZE = 4;
|
||||
|
||||
static function migrateNoteSections(input:Array<LegacyNoteSection>):Array<SongNoteData>
|
||||
{
|
||||
var result:Array<SongNoteData> = [];
|
||||
|
||||
for (section in input)
|
||||
{
|
||||
var mustHitSection = section.mustHitSection ?? false;
|
||||
for (note in section.sectionNotes)
|
||||
{
|
||||
result.push(new SongNoteData(note.time, note.data, note.length, note.getKind()));
|
||||
// Handle the dumb logic for mustHitSection.
|
||||
var noteData = note.data;
|
||||
|
||||
// Flip notes if mustHitSection is FALSE (not true lol).
|
||||
if (!mustHitSection)
|
||||
{
|
||||
if (noteData >= STRUMLINE_SIZE)
|
||||
{
|
||||
noteData -= STRUMLINE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
noteData += STRUMLINE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
result.push(new SongNoteData(note.time, noteData, note.length, note.getKind()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,18 @@ class Cursor
|
|||
Cursor.cursorMode = null;
|
||||
}
|
||||
|
||||
public static inline function toggle():Void
|
||||
{
|
||||
if (FlxG.mouse.visible)
|
||||
{
|
||||
hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
public static final CURSOR_DEFAULT_PARAMS:CursorParams =
|
||||
{
|
||||
graphic: "assets/images/cursor/cursor-default.png",
|
||||
|
|
|
@ -64,9 +64,16 @@ class GameOverSubState extends MusicBeatSubState
|
|||
*/
|
||||
var isEnding:Bool = false;
|
||||
|
||||
public function new()
|
||||
var isChartingMode:Bool = false;
|
||||
|
||||
var transparent:Bool;
|
||||
|
||||
public function new(params:GameOverParams)
|
||||
{
|
||||
super();
|
||||
|
||||
this.isChartingMode = params?.isChartingMode ?? false;
|
||||
transparent = params.transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,9 +94,10 @@ class GameOverSubState extends MusicBeatSubState
|
|||
//
|
||||
|
||||
// Add a black background to the screen.
|
||||
// We make this transparent so that we can see the stage underneath during debugging.
|
||||
var bg = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
|
||||
bg.alpha = 0.25;
|
||||
// We make this transparent so that we can see the stage underneath during debugging,
|
||||
// but it's normally opaque.
|
||||
bg.alpha = transparent ? 0.25 : 1.0;
|
||||
bg.scrollFactor.set();
|
||||
add(bg);
|
||||
|
||||
|
@ -176,9 +184,20 @@ class GameOverSubState extends MusicBeatSubState
|
|||
// PlayState.seenCutscene = false; // old thing...
|
||||
gameOverMusic.stop();
|
||||
|
||||
if (PlayStatePlaylist.isStoryMode) FlxG.switchState(new StoryMenuState());
|
||||
if (isChartingMode)
|
||||
{
|
||||
this.close();
|
||||
if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position!
|
||||
PlayState.instance.close(); // This only works because PlayState is a substate!
|
||||
}
|
||||
else if (PlayStatePlaylist.isStoryMode)
|
||||
{
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.switchState(new FreeplayState());
|
||||
}
|
||||
}
|
||||
|
||||
if (gameOverMusic.playing)
|
||||
|
@ -307,3 +326,9 @@ class GameOverSubState extends MusicBeatSubState
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
typedef GameOverParams =
|
||||
{
|
||||
var isChartingMode:Bool;
|
||||
var transparent:Bool;
|
||||
}
|
||||
|
|
|
@ -922,7 +922,11 @@ class PlayState extends MusicBeatSubState
|
|||
}
|
||||
#end
|
||||
|
||||
var gameOverSubState = new GameOverSubState();
|
||||
var gameOverSubState = new GameOverSubState(
|
||||
{
|
||||
isChartingMode: isChartingMode,
|
||||
transparent: persistentDraw
|
||||
});
|
||||
FlxTransitionableSubState.skipNextTransIn = true;
|
||||
FlxTransitionableSubState.skipNextTransOut = true;
|
||||
openSubState(gameOverSubState);
|
||||
|
@ -1097,23 +1101,6 @@ class PlayState extends MusicBeatSubState
|
|||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
* This function is called whenever Flixel switches switching to a new FlxState.
|
||||
* @return Whether to actually switch to the new state.
|
||||
*/
|
||||
@:haxe.warning("-WDeprecated")
|
||||
override function switchTo(nextState:FlxState):Bool
|
||||
{
|
||||
var result:Bool = super.switchTo(nextState);
|
||||
|
||||
if (result)
|
||||
{
|
||||
performCleanup();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any references to the current stage, then clears the stage cache,
|
||||
* then reloads all the stages.
|
||||
|
@ -1251,7 +1238,7 @@ class PlayState extends MusicBeatSubState
|
|||
return true;
|
||||
}
|
||||
|
||||
override function destroy():Void
|
||||
public override function destroy():Void
|
||||
{
|
||||
if (currentConversation != null)
|
||||
{
|
||||
|
@ -1259,6 +1246,8 @@ class PlayState extends MusicBeatSubState
|
|||
currentConversation.kill();
|
||||
}
|
||||
|
||||
performCleanup();
|
||||
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ class MultiSparrowCharacter extends BaseCharacter
|
|||
graphic = value.parent;
|
||||
this.frames = value;
|
||||
this.frame = value.getByIndex(0);
|
||||
this.numFrames = value.numFrames;
|
||||
// this.numFrames = value.numFrames;
|
||||
resetHelpers();
|
||||
this.bakedRotationAngle = 0;
|
||||
this.animation.frameIndex = 0;
|
||||
|
|
|
@ -164,6 +164,7 @@ class StageDataParser
|
|||
try
|
||||
{
|
||||
var parser = new json2object.JsonParser<StageData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
parser.fromJson(rawJson, '$stageId.json');
|
||||
|
||||
if (parser.errors.length > 0)
|
||||
|
|
|
@ -754,15 +754,23 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
|
||||
function set_currentNoteSelection(value:Array<SongNoteData>):Array<SongNoteData>
|
||||
{
|
||||
// This value is true if all elements of the current selection are also in the new selection.
|
||||
var isSuperset:Bool = currentNoteSelection.isSubset(value);
|
||||
var isEqual:Bool = currentNoteSelection.isEqualUnordered(value);
|
||||
|
||||
currentNoteSelection = value;
|
||||
|
||||
if (currentNoteSelection.length > 0)
|
||||
if (!isEqual)
|
||||
{
|
||||
notePreview.addNotes(currentNoteSelection, Std.int(songLengthInMs), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
notePreviewDirty = true;
|
||||
if (currentNoteSelection.length > 0 && isSuperset)
|
||||
{
|
||||
notePreview.addSelectedNotes(currentNoteSelection, Std.int(songLengthInMs));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The new selection removes elements from the old selection, so we have to redraw the note preview.
|
||||
notePreviewDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
return currentNoteSelection;
|
||||
|
@ -1011,7 +1019,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
function get_availableDifficulties():Array<String>
|
||||
{
|
||||
var m:Null<SongMetadata> = songMetadata.get(selectedVariation);
|
||||
return m?.playData?.difficulties ?? [];
|
||||
return m?.playData?.difficulties ?? [Constants.DEFAULT_DIFFICULTY];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1070,7 +1078,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
var result:Null<SongChartData> = songChartData.get(selectedVariation);
|
||||
if (result == null)
|
||||
{
|
||||
result = new SongChartData(["normal" => 1.0], [], ["normal" => []]);
|
||||
result = new SongChartData([Constants.DEFAULT_DIFFICULTY => 1.0], [], [Constants.DEFAULT_DIFFICULTY => []]);
|
||||
songChartData.set(selectedVariation, result);
|
||||
}
|
||||
return result;
|
||||
|
@ -1294,6 +1302,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
|
||||
function set_selectedDifficulty(value:String):String
|
||||
{
|
||||
if (value == null) value = availableDifficulties[0] ?? Constants.DEFAULT_DIFFICULTY;
|
||||
|
||||
selectedDifficulty = value;
|
||||
|
||||
// Make sure view is updated when the difficulty changes.
|
||||
|
@ -2547,8 +2557,25 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
|
||||
menubarItemPlayPause.onClick = _ -> toggleAudioPlayback();
|
||||
|
||||
menubarItemLoadInstrumental.onClick = _ -> this.openUploadInstDialog(true);
|
||||
menubarItemLoadVocals.onClick = _ -> this.openUploadVocalsDialog(true);
|
||||
menubarItemLoadInstrumental.onClick = _ -> {
|
||||
var dialog = this.openUploadInstDialog(true);
|
||||
// Ensure instrumental and vocals are reloaded properly.
|
||||
dialog.onDialogClosed = function(_) {
|
||||
this.isHaxeUIDialogOpen = false;
|
||||
this.switchToCurrentInstrumental();
|
||||
this.postLoadInstrumental();
|
||||
}
|
||||
};
|
||||
|
||||
menubarItemLoadVocals.onClick = _ -> {
|
||||
var dialog = this.openUploadVocalsDialog(true);
|
||||
// Ensure instrumental and vocals are reloaded properly.
|
||||
dialog.onDialogClosed = function(_) {
|
||||
this.isHaxeUIDialogOpen = false;
|
||||
this.switchToCurrentInstrumental();
|
||||
this.postLoadInstrumental();
|
||||
}
|
||||
};
|
||||
|
||||
menubarItemVolumeMetronome.onChange = event -> {
|
||||
var volume:Float = event.value.toFloat() / 100.0;
|
||||
|
@ -2686,14 +2713,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
* Open the backups folder in the file explorer.
|
||||
* Don't call this on HTML5.
|
||||
*/
|
||||
function openBackupsFolder(?_):Void
|
||||
function openBackupsFolder(?_):Bool
|
||||
{
|
||||
#if sys
|
||||
// TODO: Is there a way to open a folder and highlight a file in it?
|
||||
var absoluteBackupsPath:String = Path.join([Sys.getCwd(), ChartEditorImportExportHandler.BACKUPS_PATH]);
|
||||
WindowUtil.openFolder(absoluteBackupsPath);
|
||||
return true;
|
||||
#else
|
||||
trace('No file system access, cannot open backups folder.');
|
||||
return false;
|
||||
#end
|
||||
}
|
||||
|
||||
|
@ -4054,7 +4083,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
}
|
||||
else
|
||||
{
|
||||
// If we clicked and released outside the grid, do nothing.
|
||||
// If we clicked and released outside the grid (or on HaxeUI), do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4377,7 +4406,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
|
||||
playbarNoteSnap.text = '1/${noteSnapQuant}';
|
||||
playbarDifficulty.text = "Difficulty: " + selectedDifficulty.toTitleCase();
|
||||
playbarBPM.text = "BPM: " + Conductor.instance.currentTimeChange.bpm;
|
||||
playbarBPM.text = 'BPM: ${Conductor.instance.currentTimeChange.bpm}';
|
||||
}
|
||||
|
||||
function handlePlayhead():Void
|
||||
|
@ -5320,6 +5349,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
// TODO: Only update the notes that have changed.
|
||||
notePreview.erase();
|
||||
notePreview.addNotes(currentSongChartNoteData, Std.int(songLengthInMs));
|
||||
notePreview.addSelectedNotes(currentNoteSelection, Std.int(songLengthInMs));
|
||||
notePreview.addEvents(currentSongChartEventData, Std.int(songLengthInMs));
|
||||
}
|
||||
|
||||
|
|
|
@ -80,11 +80,24 @@ class ChartEditorNotePreview extends FlxSprite
|
|||
* @param notes The data for the notes.
|
||||
* @param songLengthInMs The total length of the song in milliseconds.
|
||||
*/
|
||||
public function addNotes(notes:Array<SongNoteData>, songLengthInMs:Int, ?isSelection:Bool = false):Void
|
||||
public function addNotes(notes:Array<SongNoteData>, songLengthInMs:Int):Void
|
||||
{
|
||||
for (note in notes)
|
||||
{
|
||||
addNote(note, songLengthInMs, isSelection);
|
||||
addNote(note, songLengthInMs, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an array of selected notes to the preview.
|
||||
* @param notes The data for the notes.
|
||||
* @param songLengthInMs The total length of the song in milliseconds.
|
||||
*/
|
||||
public function addSelectedNotes(notes:Array<SongNoteData>, songLengthInMs:Int):Void
|
||||
{
|
||||
for (note in notes)
|
||||
{
|
||||
addNote(note, songLengthInMs, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,14 @@ import funkin.ui.debug.charting.dialogs.ChartEditorBaseDialog.DialogParams;
|
|||
@:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/dialogs/about.xml"))
|
||||
class ChartEditorAboutDialog extends ChartEditorBaseDialog
|
||||
{
|
||||
public function new(state2:ChartEditorState, params2:DialogParams)
|
||||
public function new(chartEditorState2:ChartEditorState, params2:DialogParams)
|
||||
{
|
||||
super(state2, params2);
|
||||
super(chartEditorState2, params2);
|
||||
}
|
||||
|
||||
public static function build(state:ChartEditorState, ?closable:Bool, ?modal:Bool):ChartEditorAboutDialog
|
||||
public static function build(chartEditorState:ChartEditorState, ?closable:Bool, ?modal:Bool):ChartEditorAboutDialog
|
||||
{
|
||||
var dialog = new ChartEditorAboutDialog(state,
|
||||
var dialog = new ChartEditorAboutDialog(chartEditorState,
|
||||
{
|
||||
closable: closable ?? true,
|
||||
modal: modal ?? true
|
||||
|
|
|
@ -11,16 +11,16 @@ import haxe.ui.core.Component;
|
|||
@:access(funkin.ui.debug.charting.ChartEditorState)
|
||||
class ChartEditorBaseDialog extends Dialog
|
||||
{
|
||||
var state:ChartEditorState;
|
||||
var chartEditorState:ChartEditorState;
|
||||
var params:DialogParams;
|
||||
|
||||
var locked:Bool = false;
|
||||
|
||||
public function new(state:ChartEditorState, params:DialogParams)
|
||||
public function new(chartEditorState:ChartEditorState, params:DialogParams)
|
||||
{
|
||||
super();
|
||||
|
||||
this.state = state;
|
||||
this.chartEditorState = chartEditorState;
|
||||
this.params = params;
|
||||
|
||||
this.destroyOnClose = true;
|
||||
|
@ -47,7 +47,7 @@ class ChartEditorBaseDialog extends Dialog
|
|||
*/
|
||||
public function onClose(event:DialogEvent):Void
|
||||
{
|
||||
state.isHaxeUIDialogOpen = false;
|
||||
chartEditorState.isHaxeUIDialogOpen = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,13 +11,13 @@ import haxe.ui.containers.menus.Menu;
|
|||
@:access(funkin.ui.debug.charting.ChartEditorState)
|
||||
class ChartEditorBaseMenu extends Menu
|
||||
{
|
||||
var state:ChartEditorState;
|
||||
var chartEditorState:ChartEditorState;
|
||||
|
||||
public function new(state:ChartEditorState)
|
||||
public function new(chartEditorState:ChartEditorState)
|
||||
{
|
||||
super();
|
||||
|
||||
this.state = state;
|
||||
this.chartEditorState = chartEditorState;
|
||||
|
||||
// this.destroyOnClose = true;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
|
|||
public var charSelectScroll:ScrollView;
|
||||
public var charIconName:Label;
|
||||
|
||||
public function new(state2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false)
|
||||
public function new(chartEditorState2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false)
|
||||
{
|
||||
super(state2);
|
||||
super(chartEditorState2);
|
||||
|
||||
initialize(charType, lockPosition);
|
||||
this.alpha = 0;
|
||||
|
@ -38,17 +38,17 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
|
|||
{
|
||||
var currentCharId:String = switch (charType)
|
||||
{
|
||||
case BF: state.currentSongMetadata.playData.characters.player;
|
||||
case GF: state.currentSongMetadata.playData.characters.girlfriend;
|
||||
case DAD: state.currentSongMetadata.playData.characters.opponent;
|
||||
case BF: chartEditorState.currentSongMetadata.playData.characters.player;
|
||||
case GF: chartEditorState.currentSongMetadata.playData.characters.girlfriend;
|
||||
case DAD: chartEditorState.currentSongMetadata.playData.characters.opponent;
|
||||
default: throw 'Invalid charType: ' + charType;
|
||||
};
|
||||
|
||||
// Position this menu.
|
||||
var targetHealthIcon:Null<HealthIcon> = switch (charType)
|
||||
{
|
||||
case BF: state.healthIconBF;
|
||||
case DAD: state.healthIconDad;
|
||||
case BF: chartEditorState.healthIconBF;
|
||||
case DAD: chartEditorState.healthIconDad;
|
||||
default: null;
|
||||
};
|
||||
|
||||
|
@ -101,14 +101,14 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
|
|||
charButton.onClick = _ -> {
|
||||
switch (charType)
|
||||
{
|
||||
case BF: state.currentSongMetadata.playData.characters.player = charId;
|
||||
case GF: state.currentSongMetadata.playData.characters.girlfriend = charId;
|
||||
case DAD: state.currentSongMetadata.playData.characters.opponent = charId;
|
||||
case BF: chartEditorState.currentSongMetadata.playData.characters.player = charId;
|
||||
case GF: chartEditorState.currentSongMetadata.playData.characters.girlfriend = charId;
|
||||
case DAD: chartEditorState.currentSongMetadata.playData.characters.opponent = charId;
|
||||
default: throw 'Invalid charType: ' + charType;
|
||||
};
|
||||
|
||||
state.healthIconsDirty = true;
|
||||
state.refreshToolbox(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
|
||||
chartEditorState.healthIconsDirty = true;
|
||||
chartEditorState.refreshToolbox(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
|
||||
};
|
||||
|
||||
charButton.onMouseOver = _ -> {
|
||||
|
@ -123,9 +123,9 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
|
|||
charIconName.text = defaultText;
|
||||
}
|
||||
|
||||
public static function build(state2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false):ChartEditorCharacterIconSelectorMenu
|
||||
public static function build(chartEditorState:ChartEditorState, charType:CharacterType, lockPosition:Bool = false):ChartEditorCharacterIconSelectorMenu
|
||||
{
|
||||
var menu = new ChartEditorCharacterIconSelectorMenu(state2, charType, lockPosition);
|
||||
var menu = new ChartEditorCharacterIconSelectorMenu(chartEditorState, charType, lockPosition);
|
||||
|
||||
Screen.instance.addComponent(menu);
|
||||
|
||||
|
|
|
@ -64,12 +64,12 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
|
|||
if (event.button != DialogButton.APPLY && !this.closable)
|
||||
{
|
||||
// User cancelled the wizard! Back to the welcome dialog.
|
||||
state.openWelcomeDialog(this.closable);
|
||||
chartEditorState.openWelcomeDialog(this.closable);
|
||||
}
|
||||
|
||||
for (dropTarget in dropHandlers)
|
||||
{
|
||||
state.removeDropHandler(dropTarget);
|
||||
chartEditorState.removeDropHandler(dropTarget);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,20 +111,21 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
|
|||
|
||||
try
|
||||
{
|
||||
var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFCPath(state, path.toString());
|
||||
var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFCPath(chartEditorState, path.toString());
|
||||
if (result != null)
|
||||
{
|
||||
state.success('Loaded Chart', result.length == 0 ? 'Loaded chart (${path.toString()})' : 'Loaded chart (${path.toString()})\n${result.join("\n")}');
|
||||
chartEditorState.success('Loaded Chart',
|
||||
result.length == 0 ? 'Loaded chart (${path.toString()})' : 'Loaded chart (${path.toString()})\n${result.join("\n")}');
|
||||
this.hideDialog(DialogButton.APPLY);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()})');
|
||||
chartEditorState.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()})');
|
||||
}
|
||||
}
|
||||
catch (err)
|
||||
{
|
||||
state.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()}): ${err}');
|
||||
chartEditorState.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()}): ${err}');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,19 +140,19 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
|
|||
{
|
||||
try
|
||||
{
|
||||
var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFC(state, selectedFile.bytes);
|
||||
var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFC(chartEditorState, selectedFile.bytes);
|
||||
if (result != null)
|
||||
{
|
||||
state.success('Loaded Chart',
|
||||
chartEditorState.success('Loaded Chart',
|
||||
result.length == 0 ? 'Loaded chart (${selectedFile.name})' : 'Loaded chart (${selectedFile.name})\n${result.join("\n")}');
|
||||
|
||||
if (selectedFile.fullPath != null) state.currentWorkingFilePath = selectedFile.fullPath;
|
||||
if (selectedFile.fullPath != null) chartEditorState.currentWorkingFilePath = selectedFile.fullPath;
|
||||
this.hideDialog(DialogButton.APPLY);
|
||||
}
|
||||
}
|
||||
catch (err)
|
||||
{
|
||||
state.failure('Failed to Load Chart', 'Failed to load chart (${selectedFile.name}): ${err}');
|
||||
chartEditorState.failure('Failed to Load Chart', 'Failed to load chart (${selectedFile.name}): ${err}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,26 +41,26 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
|
|||
|
||||
// Add items to the Recent Charts list
|
||||
#if sys
|
||||
for (chartPath in state.previousWorkingFilePaths)
|
||||
for (chartPath in chartEditorState.previousWorkingFilePaths)
|
||||
{
|
||||
if (chartPath == null) continue;
|
||||
this.addRecentFilePath(state, chartPath);
|
||||
this.addRecentFilePath(chartEditorState, chartPath);
|
||||
}
|
||||
#else
|
||||
this.addHTML5RecentFileMessage();
|
||||
#end
|
||||
|
||||
// Add items to the Load From Template list
|
||||
this.buildTemplateSongList(state);
|
||||
this.buildTemplateSongList(chartEditorState);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state The current state of the chart editor.
|
||||
* @return A newly created `ChartEditorWelcomeDialog`.
|
||||
*/
|
||||
public static function build(state:ChartEditorState, ?closable:Bool, ?modal:Bool):ChartEditorWelcomeDialog
|
||||
public static function build(chartEditorState:ChartEditorState, ?closable:Bool, ?modal:Bool):ChartEditorWelcomeDialog
|
||||
{
|
||||
var dialog = new ChartEditorWelcomeDialog(state,
|
||||
var dialog = new ChartEditorWelcomeDialog(chartEditorState,
|
||||
{
|
||||
closable: closable ?? false,
|
||||
modal: modal ?? true
|
||||
|
@ -102,12 +102,12 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
|
|||
var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFCPath(state, chartPath);
|
||||
if (result != null)
|
||||
{
|
||||
state.success('Loaded Chart',
|
||||
chartEditorState.success('Loaded Chart',
|
||||
result.length == 0 ? 'Loaded chart (${chartPath.toString()})' : 'Loaded chart (${chartPath.toString()})\n${result.join("\n")}');
|
||||
}
|
||||
else
|
||||
{
|
||||
state.error('Failed to Load Chart', 'Failed to load chart (${chartPath.toString()})');
|
||||
chartEditorState.error('Failed to Load Chart', 'Failed to load chart (${chartPath.toString()})');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
|
|||
this.hideDialog(DialogButton.CANCEL);
|
||||
|
||||
// Load song from template
|
||||
state.loadSongAsTemplate(targetSongId);
|
||||
chartEditorState.loadSongAsTemplate(targetSongId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
|
|||
this.hideDialog(DialogButton.CANCEL);
|
||||
|
||||
// Open the "Open Chart" dialog
|
||||
state.openBrowseFNFC(false);
|
||||
chartEditorState.openBrowseFNFC(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,7 +199,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
|
|||
//
|
||||
// Create Song Wizard
|
||||
//
|
||||
state.openCreateSongWizardBasicOnly(false);
|
||||
chartEditorState.openCreateSongWizardBasicOnly(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -214,7 +214,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
|
|||
//
|
||||
// Create Song Wizard
|
||||
//
|
||||
state.openCreateSongWizardErectOnly(false);
|
||||
chartEditorState.openCreateSongWizardErectOnly(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,7 +229,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
|
|||
//
|
||||
// Create Song Wizard
|
||||
//
|
||||
state.openCreateSongWizardBasicErect(false);
|
||||
chartEditorState.openCreateSongWizardBasicErect(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -242,6 +242,6 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
|
|||
this.hideDialog(DialogButton.CANCEL);
|
||||
|
||||
// Open the "Import Chart" dialog
|
||||
state.openImportChartWizard('legacy', false);
|
||||
chartEditorState.openImportChartWizard('legacy', false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,11 +28,11 @@ class ChartEditorAudioHandler
|
|||
* @param instId The instrumental this vocal track will be for.
|
||||
* @return Success or failure.
|
||||
*/
|
||||
public static function loadVocalsFromPath(state:ChartEditorState, path:Path, charId:String, instId:String = ''):Bool
|
||||
public static function loadVocalsFromPath(state:ChartEditorState, path:Path, charId:String, instId:String = '', wipeFirst:Bool = false):Bool
|
||||
{
|
||||
#if sys
|
||||
var fileBytes:Bytes = sys.io.File.getBytes(path.toString());
|
||||
return loadVocalsFromBytes(state, fileBytes, charId, instId);
|
||||
return loadVocalsFromBytes(state, fileBytes, charId, instId, wipeFirst);
|
||||
#else
|
||||
trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way.");
|
||||
return false;
|
||||
|
@ -47,12 +47,12 @@ class ChartEditorAudioHandler
|
|||
* @param instId The instrumental this vocal track will be for.
|
||||
* @return Success or failure.
|
||||
*/
|
||||
public static function loadVocalsFromAsset(state:ChartEditorState, path:String, charId:String, instId:String = ''):Bool
|
||||
public static function loadVocalsFromAsset(state:ChartEditorState, path:String, charId:String, instId:String = '', wipeFirst:Bool = false):Bool
|
||||
{
|
||||
var trackData:Null<Bytes> = Assets.getBytes(path);
|
||||
if (trackData != null)
|
||||
{
|
||||
return loadVocalsFromBytes(state, trackData, charId, instId);
|
||||
return loadVocalsFromBytes(state, trackData, charId, instId, wipeFirst);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -63,10 +63,12 @@ class ChartEditorAudioHandler
|
|||
* @param bytes The audio byte data.
|
||||
* @param charId The character this vocal track will be for.
|
||||
* @param instId The instrumental this vocal track will be for.
|
||||
* @param wipeFirst Whether to wipe the existing vocal data before loading.
|
||||
*/
|
||||
public static function loadVocalsFromBytes(state:ChartEditorState, bytes:Bytes, charId:String, instId:String = ''):Bool
|
||||
public static function loadVocalsFromBytes(state:ChartEditorState, bytes:Bytes, charId:String, instId:String = '', wipeFirst:Bool = false):Bool
|
||||
{
|
||||
var trackId:String = '${charId}${instId == '' ? '' : '-${instId}'}';
|
||||
if (wipeFirst) wipeVocalData(state);
|
||||
state.audioVocalTrackData.set(trackId, bytes);
|
||||
return true;
|
||||
}
|
||||
|
@ -78,11 +80,11 @@ class ChartEditorAudioHandler
|
|||
* @param instId The instrumental this vocal track will be for.
|
||||
* @return Success or failure.
|
||||
*/
|
||||
public static function loadInstFromPath(state:ChartEditorState, path:Path, instId:String = ''):Bool
|
||||
public static function loadInstFromPath(state:ChartEditorState, path:Path, instId:String = '', wipeFirst:Bool = false):Bool
|
||||
{
|
||||
#if sys
|
||||
var fileBytes:Bytes = sys.io.File.getBytes(path.toString());
|
||||
return loadInstFromBytes(state, fileBytes, instId);
|
||||
return loadInstFromBytes(state, fileBytes, instId, wipeFirst);
|
||||
#else
|
||||
trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way.");
|
||||
return false;
|
||||
|
@ -96,12 +98,12 @@ class ChartEditorAudioHandler
|
|||
* @param instId The instrumental this vocal track will be for.
|
||||
* @return Success or failure.
|
||||
*/
|
||||
public static function loadInstFromAsset(state:ChartEditorState, path:String, instId:String = ''):Bool
|
||||
public static function loadInstFromAsset(state:ChartEditorState, path:String, instId:String = '', wipeFirst:Bool = false):Bool
|
||||
{
|
||||
var trackData:Null<Bytes> = Assets.getBytes(path);
|
||||
if (trackData != null)
|
||||
{
|
||||
return loadInstFromBytes(state, trackData, instId);
|
||||
return loadInstFromBytes(state, trackData, instId, wipeFirst);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -113,9 +115,10 @@ class ChartEditorAudioHandler
|
|||
* @param charId The character this vocal track will be for.
|
||||
* @param instId The instrumental this vocal track will be for.
|
||||
*/
|
||||
public static function loadInstFromBytes(state:ChartEditorState, bytes:Bytes, instId:String = ''):Bool
|
||||
public static function loadInstFromBytes(state:ChartEditorState, bytes:Bytes, instId:String = '', wipeFirst:Bool = false):Bool
|
||||
{
|
||||
if (instId == '') instId = 'default';
|
||||
if (wipeFirst) wipeInstrumentalData(state);
|
||||
state.audioInstTrackData.set(instId, bytes);
|
||||
return true;
|
||||
}
|
||||
|
@ -127,9 +130,9 @@ class ChartEditorAudioHandler
|
|||
|
||||
stopExistingVocals(state);
|
||||
result = playVocals(state, BF, playerId, instId);
|
||||
if (!result) return false;
|
||||
// if (!result) return false;
|
||||
result = playVocals(state, DAD, opponentId, instId);
|
||||
if (!result) return false;
|
||||
// if (!result) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -687,6 +687,9 @@ class ChartEditorDialogHandler
|
|||
Conductor.instance.instrumentalOffset = state.currentInstrumentalOffset; // Loads from the metadata.
|
||||
Conductor.instance.mapTimeChanges(state.currentSongMetadata.timeChanges);
|
||||
|
||||
state.selectedVariation = Constants.DEFAULT_VARIATION;
|
||||
state.selectedDifficulty = state.availableDifficulties[0];
|
||||
|
||||
state.difficultySelectDirty = true;
|
||||
|
||||
dialog.hideDialog(DialogButton.APPLY);
|
||||
|
@ -755,14 +758,9 @@ class ChartEditorDialogHandler
|
|||
trace('Selected file: $pathStr');
|
||||
var path:Path = new Path(pathStr);
|
||||
|
||||
if (!hasClearedVocals)
|
||||
if (state.loadVocalsFromPath(path, charKey, instId, !hasClearedVocals))
|
||||
{
|
||||
hasClearedVocals = true;
|
||||
state.stopExistingVocals();
|
||||
}
|
||||
|
||||
if (state.loadVocalsFromPath(path, charKey, instId))
|
||||
{
|
||||
// Tell the user the load was successful.
|
||||
state.success('Loaded Vocals', 'Loaded vocals for $charName (${path.file}.${path.ext}), variation ${state.selectedVariation}');
|
||||
#if FILE_DROP_SUPPORTED
|
||||
|
@ -796,13 +794,10 @@ class ChartEditorDialogHandler
|
|||
if (selectedFile != null && selectedFile.bytes != null)
|
||||
{
|
||||
trace('Selected file: ' + selectedFile.name);
|
||||
if (!hasClearedVocals)
|
||||
|
||||
if (state.loadVocalsFromBytes(selectedFile.bytes, charKey, instId, !hasClearedVocals))
|
||||
{
|
||||
hasClearedVocals = true;
|
||||
state.stopExistingVocals();
|
||||
}
|
||||
if (state.loadVocalsFromBytes(selectedFile.bytes, charKey, instId))
|
||||
{
|
||||
// Tell the user the load was successful.
|
||||
state.success('Loaded Vocals', 'Loaded vocals for $charName (${selectedFile.name}), variation ${state.selectedVariation}');
|
||||
|
||||
|
|
|
@ -315,6 +315,8 @@ class ChartEditorImportExportHandler
|
|||
public static function getLatestBackupPath():Null<String>
|
||||
{
|
||||
#if sys
|
||||
if (!sys.FileSystem.exists(BACKUPS_PATH)) sys.FileSystem.createDirectory(BACKUPS_PATH);
|
||||
|
||||
var entries:Array<String> = sys.FileSystem.readDirectory(BACKUPS_PATH);
|
||||
entries.sort(SortUtil.alphabetically);
|
||||
|
||||
|
|
|
@ -12,13 +12,13 @@ import haxe.ui.core.Component;
|
|||
@:access(funkin.ui.debug.charting.ChartEditorState)
|
||||
class ChartEditorBaseToolbox extends CollapsibleDialog
|
||||
{
|
||||
var state:ChartEditorState;
|
||||
var chartEditorState:ChartEditorState;
|
||||
|
||||
private function new(state:ChartEditorState)
|
||||
private function new(chartEditorState:ChartEditorState)
|
||||
{
|
||||
super();
|
||||
|
||||
this.state = state;
|
||||
this.chartEditorState = chartEditorState;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,9 +40,9 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
var frameVariation:Frame;
|
||||
var frameDifficulty:Frame;
|
||||
|
||||
public function new(state2:ChartEditorState)
|
||||
public function new(chartEditorState2:ChartEditorState)
|
||||
{
|
||||
super(state2);
|
||||
super(chartEditorState2);
|
||||
|
||||
initialize();
|
||||
|
||||
|
@ -51,7 +51,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
|
||||
function onClose(event:UIEvent)
|
||||
{
|
||||
state.menubarItemToggleToolboxMetadata.selected = false;
|
||||
chartEditorState.menubarItemToggleToolboxMetadata.selected = false;
|
||||
}
|
||||
|
||||
function initialize():Void
|
||||
|
@ -67,11 +67,11 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
if (valid)
|
||||
{
|
||||
inputSongName.removeClass('invalid-value');
|
||||
state.currentSongMetadata.songName = event.target.text;
|
||||
chartEditorState.currentSongMetadata.songName = event.target.text;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.currentSongMetadata.songName = '';
|
||||
chartEditorState.currentSongMetadata.songName = '';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -81,11 +81,11 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
if (valid)
|
||||
{
|
||||
inputSongArtist.removeClass('invalid-value');
|
||||
state.currentSongMetadata.artist = event.target.text;
|
||||
chartEditorState.currentSongMetadata.artist = event.target.text;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.currentSongMetadata.artist = '';
|
||||
chartEditorState.currentSongMetadata.artist = '';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -94,41 +94,41 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
|
||||
if (valid)
|
||||
{
|
||||
state.currentSongMetadata.playData.stage = event.data.id;
|
||||
chartEditorState.currentSongMetadata.playData.stage = event.data.id;
|
||||
}
|
||||
};
|
||||
var startingValueStage = ChartEditorDropdowns.populateDropdownWithStages(inputStage, state.currentSongMetadata.playData.stage);
|
||||
var startingValueStage = ChartEditorDropdowns.populateDropdownWithStages(inputStage, chartEditorState.currentSongMetadata.playData.stage);
|
||||
inputStage.value = startingValueStage;
|
||||
|
||||
inputNoteStyle.onChange = function(event:UIEvent) {
|
||||
if (event.data?.id == null) return;
|
||||
state.currentSongNoteStyle = event.data.id;
|
||||
chartEditorState.currentSongNoteStyle = event.data.id;
|
||||
};
|
||||
|
||||
inputBPM.onChange = function(event:UIEvent) {
|
||||
if (event.value == null || event.value <= 0) return;
|
||||
|
||||
// Use a command so we can undo/redo this action.
|
||||
var startingBPM = state.currentSongMetadata.timeChanges[0].bpm;
|
||||
var startingBPM = chartEditorState.currentSongMetadata.timeChanges[0].bpm;
|
||||
if (event.value != startingBPM)
|
||||
{
|
||||
state.performCommand(new ChangeStartingBPMCommand(event.value));
|
||||
chartEditorState.performCommand(new ChangeStartingBPMCommand(event.value));
|
||||
}
|
||||
};
|
||||
|
||||
inputOffsetInst.onChange = function(event:UIEvent) {
|
||||
if (event.value == null) return;
|
||||
|
||||
state.currentInstrumentalOffset = event.value;
|
||||
chartEditorState.currentInstrumentalOffset = event.value;
|
||||
Conductor.instance.instrumentalOffset = event.value;
|
||||
// Update song length.
|
||||
state.songLengthInMs = (state.audioInstTrack?.length ?? 1000.0) + Conductor.instance.instrumentalOffset;
|
||||
chartEditorState.songLengthInMs = (chartEditorState.audioInstTrack?.length ?? 1000.0) + Conductor.instance.instrumentalOffset;
|
||||
};
|
||||
|
||||
inputOffsetVocal.onChange = function(event:UIEvent) {
|
||||
if (event.value == null) return;
|
||||
|
||||
state.currentSongMetadata.offsets.setVocalOffset(state.currentSongMetadata.playData.characters.player, event.value);
|
||||
chartEditorState.currentSongMetadata.offsets.setVocalOffset(chartEditorState.currentSongMetadata.playData.characters.player, event.value);
|
||||
};
|
||||
inputScrollSpeed.onChange = function(event:UIEvent) {
|
||||
var valid:Bool = event.target.value != null && event.target.value > 0;
|
||||
|
@ -136,25 +136,25 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
if (valid)
|
||||
{
|
||||
inputScrollSpeed.removeClass('invalid-value');
|
||||
state.currentSongChartScrollSpeed = event.target.value;
|
||||
chartEditorState.currentSongChartScrollSpeed = event.target.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.currentSongChartScrollSpeed = 1.0;
|
||||
chartEditorState.currentSongChartScrollSpeed = 1.0;
|
||||
}
|
||||
labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x';
|
||||
labelScrollSpeed.text = 'Scroll Speed: ${chartEditorState.currentSongChartScrollSpeed}x';
|
||||
};
|
||||
|
||||
buttonCharacterOpponent.onClick = function(_) {
|
||||
state.openCharacterDropdown(CharacterType.DAD, false);
|
||||
chartEditorState.openCharacterDropdown(CharacterType.DAD, false);
|
||||
};
|
||||
|
||||
buttonCharacterGirlfriend.onClick = function(_) {
|
||||
state.openCharacterDropdown(CharacterType.GF, false);
|
||||
chartEditorState.openCharacterDropdown(CharacterType.GF, false);
|
||||
};
|
||||
|
||||
buttonCharacterPlayer.onClick = function(_) {
|
||||
state.openCharacterDropdown(CharacterType.BF, false);
|
||||
chartEditorState.openCharacterDropdown(CharacterType.BF, false);
|
||||
};
|
||||
|
||||
refresh();
|
||||
|
@ -162,17 +162,17 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
|
||||
public override function refresh():Void
|
||||
{
|
||||
inputSongName.value = state.currentSongMetadata.songName;
|
||||
inputSongArtist.value = state.currentSongMetadata.artist;
|
||||
inputStage.value = state.currentSongMetadata.playData.stage;
|
||||
inputNoteStyle.value = state.currentSongMetadata.playData.noteStyle;
|
||||
inputBPM.value = state.currentSongMetadata.timeChanges[0].bpm;
|
||||
inputScrollSpeed.value = state.currentSongChartScrollSpeed;
|
||||
labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x';
|
||||
frameVariation.text = 'Variation: ${state.selectedVariation.toTitleCase()}';
|
||||
frameDifficulty.text = 'Difficulty: ${state.selectedDifficulty.toTitleCase()}';
|
||||
inputSongName.value = chartEditorState.currentSongMetadata.songName;
|
||||
inputSongArtist.value = chartEditorState.currentSongMetadata.artist;
|
||||
inputStage.value = chartEditorState.currentSongMetadata.playData.stage;
|
||||
inputNoteStyle.value = chartEditorState.currentSongMetadata.playData.noteStyle;
|
||||
inputBPM.value = chartEditorState.currentSongMetadata.timeChanges[0].bpm;
|
||||
inputScrollSpeed.value = chartEditorState.currentSongChartScrollSpeed;
|
||||
labelScrollSpeed.text = 'Scroll Speed: ${chartEditorState.currentSongChartScrollSpeed}x';
|
||||
frameVariation.text = 'Variation: ${chartEditorState.selectedVariation.toTitleCase()}';
|
||||
frameDifficulty.text = 'Difficulty: ${chartEditorState.selectedDifficulty.toTitleCase()}';
|
||||
|
||||
var stageId:String = state.currentSongMetadata.playData.stage;
|
||||
var stageId:String = chartEditorState.currentSongMetadata.playData.stage;
|
||||
var stageData:Null<StageData> = StageDataParser.parseStageData(stageId);
|
||||
if (inputStage != null)
|
||||
{
|
||||
|
@ -183,21 +183,45 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
|
||||
var LIMIT = 6;
|
||||
|
||||
var charDataOpponent:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.opponent);
|
||||
buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.opponent);
|
||||
buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}';
|
||||
var charDataOpponent:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.opponent);
|
||||
if (charDataOpponent != null)
|
||||
{
|
||||
buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.opponent);
|
||||
buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}';
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonCharacterOpponent.icon = null;
|
||||
buttonCharacterOpponent.text = "None";
|
||||
}
|
||||
|
||||
var charDataGirlfriend:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.girlfriend);
|
||||
buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.girlfriend);
|
||||
buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}';
|
||||
var charDataGirlfriend:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.girlfriend);
|
||||
if (charDataGirlfriend != null)
|
||||
{
|
||||
buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.girlfriend);
|
||||
buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}';
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonCharacterGirlfriend.icon = null;
|
||||
buttonCharacterGirlfriend.text = "None";
|
||||
}
|
||||
|
||||
var charDataPlayer:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.player);
|
||||
buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.player);
|
||||
buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}';
|
||||
var charDataPlayer:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.player);
|
||||
if (charDataPlayer != null)
|
||||
{
|
||||
buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.player);
|
||||
buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}';
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonCharacterPlayer.icon = null;
|
||||
buttonCharacterPlayer.text = "None";
|
||||
}
|
||||
}
|
||||
|
||||
public static function build(state:ChartEditorState):ChartEditorMetadataToolbox
|
||||
public static function build(chartEditorState:ChartEditorState):ChartEditorMetadataToolbox
|
||||
{
|
||||
return new ChartEditorMetadataToolbox(state);
|
||||
return new ChartEditorMetadataToolbox(chartEditorState);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ class FreeplayState extends MusicBeatSubState
|
|||
var stickerSubState:StickerSubState;
|
||||
|
||||
//
|
||||
static var rememberedDifficulty:Null<String> = "normal";
|
||||
static var rememberedDifficulty:Null<String> = Constants.DEFAULT_DIFFICULTY;
|
||||
static var rememberedSongId:Null<String> = null;
|
||||
|
||||
public function new(?stickers:StickerSubState = null)
|
||||
|
@ -874,15 +874,14 @@ class FreeplayState extends MusicBeatSubState
|
|||
}
|
||||
}
|
||||
|
||||
@:haxe.warning("-WDeprecated")
|
||||
override function switchTo(nextState:FlxState):Bool
|
||||
public override function destroy():Void
|
||||
{
|
||||
super.destroy();
|
||||
var daSong = songs[curSelected];
|
||||
if (daSong != null)
|
||||
{
|
||||
clearDaCache(daSong.songName);
|
||||
}
|
||||
return super.switchTo(nextState);
|
||||
}
|
||||
|
||||
function changeDiff(change:Int = 0)
|
||||
|
|
|
@ -35,7 +35,7 @@ class CharacterPlayer extends Box
|
|||
public function new(defaultToBf:Bool = true)
|
||||
{
|
||||
super();
|
||||
_overrideSkipTransformChildren = false;
|
||||
// _overrideSkipTransformChildren = false;
|
||||
|
||||
if (defaultToBf)
|
||||
{
|
||||
|
|
|
@ -106,7 +106,7 @@ class StoryMenuState extends MusicBeatState
|
|||
var stickerSubState:StickerSubState;
|
||||
|
||||
static var rememberedLevelId:Null<String> = null;
|
||||
static var rememberedDifficulty:Null<String> = "normal";
|
||||
static var rememberedDifficulty:Null<String> = Constants.DEFAULT_DIFFICULTY;
|
||||
|
||||
public function new(?stickers:StickerSubState = null)
|
||||
{
|
||||
|
|
|
@ -123,6 +123,7 @@ class Constants
|
|||
|
||||
/**
|
||||
* Default list of difficulties for charts.
|
||||
* Assumes no Erect mode, etc.
|
||||
*/
|
||||
public static final DEFAULT_DIFFICULTY_LIST:Array<String> = ['easy', 'normal', 'hard'];
|
||||
|
||||
|
|
|
@ -76,4 +76,56 @@ class ArrayTools
|
|||
while (array.length > 0)
|
||||
array.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true only if both arrays contain the same elements (possibly in a different order).
|
||||
* @param a The first array to compare.
|
||||
* @param b The second array to compare.
|
||||
* @return Weather both arrays contain the same elements.
|
||||
*/
|
||||
public static function isEqualUnordered<T>(a:Array<T>, b:Array<T>):Bool
|
||||
{
|
||||
if (a.length != b.length) return false;
|
||||
for (element in a)
|
||||
{
|
||||
if (!b.contains(element)) return false;
|
||||
}
|
||||
for (element in b)
|
||||
{
|
||||
if (!a.contains(element)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if `superset` contains all elements of `subset`.
|
||||
* @param superset The array to query for each element.
|
||||
* @param subset The array containing the elements to query for.
|
||||
* @return Weather `superset` contains all elements of `subset`.
|
||||
*/
|
||||
public static function isSuperset<T>(superset:Array<T>, subset:Array<T>):Bool
|
||||
{
|
||||
// Shortcuts.
|
||||
if (subset.length == 0) return true;
|
||||
if (subset.length > superset.length) return false;
|
||||
|
||||
// Check each element.
|
||||
for (element in subset)
|
||||
{
|
||||
if (!superset.contains(element)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if `superset` contains all elements of `subset`.
|
||||
* @param subset The array containing the elements to query for.
|
||||
* @param superset The array to query for each element.
|
||||
* @return Weather `superset` contains all elements of `subset`.
|
||||
*/
|
||||
public static function isSubset<T>(subset:Array<T>, superset:Array<T>):Bool
|
||||
{
|
||||
// Switch it around.
|
||||
return isSuperset(superset, subset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,6 +156,7 @@ class MyTypeRegistry extends BaseRegistry<MyType, MyTypeData>
|
|||
// JsonParser does not take type parameters,
|
||||
// otherwise this function would be in BaseRegistry.
|
||||
var parser = new json2object.JsonParser<MyTypeData>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadEntryFile(id))
|
||||
{
|
||||
|
@ -181,6 +182,7 @@ class MyTypeRegistry extends BaseRegistry<MyType, MyTypeData>
|
|||
// JsonParser does not take type parameters,
|
||||
// otherwise this function would be in BaseRegistry.
|
||||
var parser = new json2object.JsonParser<MyTypeData_v0_1_x>();
|
||||
parser.ignoreUnknownVariables = false;
|
||||
|
||||
switch (loadEntryFile(id))
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue