1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2024-11-25 08:13:45 +00:00

Finished song data loader

This commit is contained in:
Eric Myllyoja 2022-09-16 15:37:00 -04:00
parent 848874eaac
commit 3597b09a46
7 changed files with 289 additions and 36 deletions

View file

@ -139,17 +139,17 @@ class LatencyState extends MusicBeatSubstate
super.create();
}
override function stepHit()
override function stepHit():Bool
{
if (curStep % 4 == 2)
{
blocks.members[((curBeat % 8) + 1) % 8].alpha = 0.5;
}
super.stepHit();
return super.stepHit();
}
override function beatHit()
override function beatHit():Bool
{
if (curBeat % 8 == 0)
blocks.forEach(blok ->
@ -160,7 +160,7 @@ class LatencyState extends MusicBeatSubstate
blocks.members[curBeat % 8].alpha = 1;
// block.visible = !block.visible;
super.beatHit();
return super.beatHit();
}
override function update(elapsed:Float)

View file

@ -335,11 +335,7 @@ class BaseCharacter extends Bopper
var shouldStopSinging:Bool = (this.characterType == BF) ? !isHoldingNote() : true;
FlxG.watch.addQuick('singTimeMs-${characterId}', singTimeMs);
<<<<<<< HEAD
if (holdTimer > singTimeMs && shouldStopSinging) // && !getCurrentAnimation().endsWith("miss")
=======
if (holdTimer > singTimeMs && shouldStopSinging)
>>>>>>> origin/note-redux
{
// trace('holdTimer reached ${holdTimer}sec (> ${singTimeMs}), stopping sing animation');
holdTimer = 0;

View file

@ -1,7 +1,10 @@
package funkin.play.song;
import funkin.play.song.SongData.SongDataParser;
import funkin.play.song.SongData.SongEventData;
import funkin.play.song.SongData.SongMetadata;
import funkin.play.song.SongData.SongNoteData;
import funkin.play.song.SongData.SongPlayableChar;
import funkin.play.song.SongData.SongTimeChange;
import funkin.play.song.SongData.SongTimeFormat;
@ -20,12 +23,14 @@ class Song // implements IPlayStateScriptedClass
final _metadata:Array<SongMetadata>;
final variations:Array<String>;
final difficulties:Map<String, SongDifficulty>;
public function new(id:String)
{
this.songId = id;
variations = [];
difficulties = new Map<String, SongDifficulty>();
_metadata = SongDataParser.parseSongMetadata(songId);
@ -35,6 +40,9 @@ class Song // implements IPlayStateScriptedClass
}
populateFromMetadata();
// TODO: Disable later.
cacheCharts();
}
function populateFromMetadata()
@ -46,6 +54,8 @@ class Song // implements IPlayStateScriptedClass
{
var difficulty = new SongDifficulty(diffId, metadata.variation);
variations.push(metadata.variation);
difficulty.songName = metadata.songName;
difficulty.songArtist = metadata.artist;
difficulty.timeFormat = metadata.timeFormat;
@ -54,28 +64,48 @@ class Song // implements IPlayStateScriptedClass
difficulty.loop = metadata.loop;
difficulty.generatedBy = metadata.generatedBy;
difficulty.stage = metadata.playData.stage;
// difficulty.noteSkin = metadata.playData.noteSkin;
difficulty.chars = new Map<String, SongPlayableChar>();
for (charId in metadata.playData.playableChars.keys())
{
var char = metadata.playData.playableChars.get(charId);
difficulty.chars.set(charId, char);
}
difficulties.set(diffId, difficulty);
}
}
}
/**
* Parse and cache the chart for a specific difficulty.
*/
public function cacheChart(diffId:String)
{
getDifficulty(diffId).cacheChart();
}
/**
* Parse and cache the chart for all difficulties of this song.
*/
public function cacheCharts()
{
for (difficulty in difficulties)
trace('Caching ${variations.length} chart files for song $songId');
for (variation in variations)
{
difficulty.cacheChart();
var chartData = SongDataParser.parseSongChartData(songId, variation);
for (diffId in chartData.notes.keys())
{
trace(' Difficulty $diffId');
var difficulty = difficulties.get(diffId);
if (difficulty == null)
{
trace('Could not find difficulty $diffId for song $songId');
continue;
}
difficulty.notes = chartData.notes.get(diffId);
difficulty.scrollSpeed = chartData.scrollSpeed.get(diffId);
difficulty.events = chartData.events;
}
}
trace('Done caching charts.');
}
/**
@ -124,9 +154,13 @@ class SongDifficulty
public var timeChanges:Array<SongTimeChange> = [];
public var scrollSpeed(default, null):Float = SongValidator.DEFAULT_SCROLLSPEED;
public var stage:String = SongValidator.DEFAULT_STAGE;
public var chars:Map<String, SongPlayableChar> = null;
// public var notes(default, null):Array<;
public var scrollSpeed:Float = SongValidator.DEFAULT_SCROLLSPEED;
public var notes:Array<SongNoteData>;
public var events:Array<SongEventData>;
public function new(diffId:String, variation:String)
{
@ -134,13 +168,8 @@ class SongDifficulty
this.variation = variation;
}
public function cacheChart():Void
{
// TODO: Parse chart data
}
public function clearChart():Void
{
// notes = null;
notes = null;
}
}

View file

@ -249,6 +249,231 @@ typedef RawSongPlayableChar =
var i:String;
}
typedef RawSongNoteData =
{
/**
* The timestamp of the note. The timestamp is in the format of the song's time format.
*/
var t:Float;
/**
* Data for the note. Represents the index on the strumline.
* 0 = left, 1 = down, 2 = up, 3 = right
* `floor(direction / strumlineSize)` specifies which strumline the note is on.
* 0 = player, 1 = opponent, etc.
*/
var d:Int;
/**
* Length of the note, if applicable.
* Defaults to 0 for single notes.
*/
var l:Float;
/**
* The kind of the note.
* This can allow the note to include information used for custom behavior.
* Defaults to blank or `"normal"`.
*/
var k:String;
}
abstract SongNoteData(RawSongNoteData)
{
public function new(time:Float, data:Int, length:Float = 0, kind:String = "")
{
this = {
t: time,
d: data,
l: length,
k: kind
};
}
public var time(get, set):Float;
public function get_time():Float
{
return this.t;
}
public function set_time(value:Float):Float
{
return this.t = value;
}
/**
* The raw data for the note.
*/
public var data(get, set):Int;
public function get_data():Int
{
return this.d;
}
public function set_data(value:Int):Int
{
return this.d = value;
}
/**
* The direction of the note, if applicable.
* Strips the strumline index from the data.
*
* 0 = left, 1 = down, 2 = up, 3 = right
*/
public inline function getDirection(strumlineSize:Int = 4):Int
{
return this.d % strumlineSize;
}
/**
* The strumline index of the note, if applicable.
* Strips the direction from the data.
*
* 0 = player, 1 = opponent, etc.
*/
public inline function getStrumlineIndex(strumlineSize:Int = 4):Int
{
return Math.floor(this.d / strumlineSize);
}
public var length(get, set):Float;
public function get_length():Float
{
return this.l;
}
public function set_length(value:Float):Float
{
return this.l = value;
}
public var kind(get, set):String;
public function get_kind():String
{
if (this.k == null || this.k == '')
return 'normal';
return this.k;
}
public function set_kind(value:String):String
{
if (value == 'normal' || value == '')
value = null;
return this.k = value;
}
}
typedef RawSongEventData =
{
/**
* The timestamp of the event. The timestamp is in the format of the song's time format.
*/
var t:Float;
/**
* The kind of the event.
* Examples include "FocusCamera" and "PlayAnimation"
* Custom events can be added by scripts with the `ScriptedSongEvent` class.
*/
var e:String;
/**
* The data for the event.
* This can allow the event to include information used for custom behavior.
* Data type depends on the event kind. It can be anything that's JSON serializable.
*/
var v:Dynamic;
}
abstract SongEventData(RawSongEventData)
{
public function new(time:Float, event:String, value:Dynamic = null)
{
this = {
t: time,
e: event,
v: value
};
}
public var time(get, set):Float;
public function get_time():Float
{
return this.t;
}
public function set_time(value:Float):Float
{
return this.t = value;
}
public var event(get, set):String;
public function get_event():String
{
return this.e;
}
public function set_event(value:String):String
{
return this.e = value;
}
public var value(get, set):Dynamic;
public function get_value():Dynamic
{
return this.v;
}
public function set_value(value:Dynamic):Dynamic
{
return this.v = value;
}
public inline function getBool():Bool
{
return cast this.v;
}
public inline function getInt():Int
{
return cast this.v;
}
public inline function getFloat():Float
{
return cast this.v;
}
public inline function getString():String
{
return cast this.v;
}
public inline function getArray():Array<Dynamic>
{
return cast this.v;
}
public inline function getMap():DynamicAccess<Dynamic>
{
return cast this.v;
}
public inline function getBoolArray():Array<Bool>
{
return cast this.v;
}
}
abstract SongPlayableChar(RawSongPlayableChar)
{
public function new(girlfriend:String, opponent:String, inst:String = "")
@ -299,6 +524,12 @@ abstract SongPlayableChar(RawSongPlayableChar)
typedef SongChartData =
{
var version:Version;
var scrollSpeed:DynamicAccess<Float>;
var events:Array<SongEventData>;
var notes:DynamicAccess<Array<SongNoteData>>;
var generatedBy:String;
};
typedef RawSongTimeChange =

View file

@ -54,9 +54,9 @@ class SongMigrator
{
trace('[SONGDATA] Song (${songId}) chart version (${jsonData.version}) is valid and up-to-date.');
var songMetadata:SongMetadata = cast jsonData;
var songChartData:SongChartData = cast jsonData;
return songMetadata;
return songChartData;
}
else
{

View file

@ -18,6 +18,7 @@ class SongValidator
public static final DEFAULT_DIVISIONS:Int = -1;
public static final DEFAULT_LOOP:Bool = false;
public static final DEFAULT_GENERATEDBY:String = "Unknown";
public static final DEFAULT_STAGE:String = "mainStage";
public static final DEFAULT_SCROLLSPEED:Float = 1.0;
/**

View file

@ -1,18 +1,14 @@
package funkin.ui.stageBuildShit;
import flixel.FlxSprite;
import flixel.input.mouse.FlxMouseEvent;
import flixel.input.mouse.FlxMouseEventManager;
import flixel.math.FlxPoint;
import flixel.ui.FlxButton;
import funkin.play.PlayState;
import funkin.play.character.BaseCharacter;
import funkin.play.stage.StageData.StageDataParser;
import funkin.play.stage.StageData;
import haxe.Json;
import haxe.ui.ComponentBuilder;
import haxe.ui.RuntimeComponentBuilder;
import haxe.ui.Toolkit;
import haxe.ui.components.Button;
import haxe.ui.containers.HBox;
import haxe.ui.containers.VBox;
import haxe.ui.core.Component;
import openfl.Assets;
@ -46,7 +42,7 @@ class StageOffsetSubstate extends MusicBeatSubstate
for (thing in PlayState.instance.currentStage)
{
FlxMouseEventManager.add(thing, spr ->
FlxMouseEvent.add(thing, spr ->
{
char = cast thing;
trace("JUST PRESSED!");
@ -94,7 +90,7 @@ class StageOffsetSubstate extends MusicBeatSubstate
{
for (thing in PlayState.instance.currentStage)
{
FlxMouseEventManager.remove(thing);
FlxMouseEvent.remove(thing);
thing.alpha = 1;
}