Merge branch 'master' into some-options

This commit is contained in:
CyndaquilDAC
2021-07-19 23:22:43 -05:00
committed by GitHub
25 changed files with 2044 additions and 355 deletions

File diff suppressed because it is too large Load Diff

View File

@ -28,8 +28,6 @@ class Conductor
public static var safeZoneOffset:Float = Math.floor((safeFrames / 60) * 1000); // is calculated in create(), is safeFrames in milliseconds
public static var timeScale:Float = Conductor.safeZoneOffset / 166;
public static var lengthInSteps:Float = 0;
public static var bpmChangeMap:Array<BPMChangeEvent> = [];
public function new()
@ -70,15 +68,27 @@ class Conductor
trace("new BPM map BUDDY " + bpmChangeMap);
}
public static function changeBPM(newBpm:Float)
public static function recalculateTimingStruct(SONG:Song)
{
for(i in SONG.eventObjects)
{
/*TimingStruct.addTiming(beat,bpm,endBeat, Std.parseFloat(OFFSET));
if (changeEvents.length != 0)
{
var data = TimingStruct.AllTimings[currentIndex - 1];
data.endBeat = beat;
data.length = (data.endBeat - data.startBeat) / (data.bpm / 60);
TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length;
}*/
}
}
public static function changeBPM(newBpm:Float, ?recalcLength = true)
{
bpm = newBpm;
crochet = ((60 / bpm) * 1000);
stepCrochet = crochet / 4;
lengthInSteps = (FlxG.sound.music.length / stepCrochet);
trace("\nLength in in steps: " + lengthInSteps);
}
}

View File

@ -1,5 +1,12 @@
package;
import openfl.utils.Future;
import openfl.media.Sound;
import flixel.system.FlxSound;
#if sys
import smTools.SMFile;
import sys.FileSystem;
import sys.io.File;
#end
import Song.SwagSong;
import flixel.input.gamepad.FlxGamepad;
import flash.text.TextField;
@ -63,6 +70,9 @@ class FreeplayState extends MusicBeatState
//var diffList = "";
songData = [];
songs = [];
for (i in 0...initSonglist.length)
{
var data:Array<String> = initSonglist[i].split(':');
@ -83,6 +93,35 @@ class FreeplayState extends MusicBeatState
}
trace("tryin to load sm files");
#if sys
for(i in FileSystem.readDirectory("assets/sm/"))
{
trace(i);
if (FileSystem.isDirectory("assets/sm/" + i))
{
trace("Reading SM file dir " + i);
for (file in FileSystem.readDirectory("assets/sm/" + i))
{
if (file.contains(" "))
FileSystem.rename("assets/sm/" + i + "/" + file,"assets/sm/" + i + "/" + file.replace(" ","_"));
if (file.endsWith(".sm"))
{
trace("reading " + file);
var file:SMFile = SMFile.loadFile("assets/sm/" + i + "/" + file.replace(" ","_"));
trace("Converting " + file.header.TITLE);
var data = file.convertToFNF("assets/sm/" + i + "/converted.json");
var meta = new SongMetadata(file.header.TITLE, 0, "sm",file,"assets/sm/" + i);
songs.push(meta);
var song = Song.loadFromJsonRAW(data);
songData.set(file.header.TITLE, [song,song,song]);
}
}
}
}
#end
//trace("\n" + diffList);
/*
@ -319,6 +358,18 @@ class FreeplayState extends MusicBeatState
PlayState.storyDifficulty = curDifficulty;
PlayState.storyWeek = songs[curSelected].week;
trace('CUR WEEK' + PlayState.storyWeek);
#if sys
if (songs[curSelected].songCharacter == "sm")
{
PlayState.isSM = true;
PlayState.sm = songs[curSelected].sm;
PlayState.pathToSm = songs[curSelected].path;
}
else
PlayState.isSM = false;
#else
PlayState.isSM = false;
#end
LoadingState.loadAndSwitchState(new PlayState());
}
}
@ -332,6 +383,7 @@ class FreeplayState extends MusicBeatState
if (curDifficulty > 2)
curDifficulty = 0;
// adjusting the highscore song name to be compatible (changeDiff)
var songHighscore = StringTools.replace(songs[curSelected].songName, " ", "-");
switch (songHighscore) {
@ -357,6 +409,7 @@ class FreeplayState extends MusicBeatState
FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
curSelected += change;
if (curSelected < 0)
@ -383,7 +436,17 @@ class FreeplayState extends MusicBeatState
diffCalcText.text = 'RATING: ${DiffCalc.CalculateDiff(songData.get(songs[curSelected].songName)[curDifficulty])}';
#if PRELOAD_ALL
FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0);
if (songs[curSelected].songCharacter == "sm")
{
var data = songs[curSelected];
trace("Loading " + data.path + "/" + data.sm.header.MUSIC);
var bytes = File.getBytes(data.path + "/" + data.sm.header.MUSIC);
var sound = new Sound();
sound.loadCompressedDataFromByteArray(bytes.getData(), bytes.length);
FlxG.sound.playMusic(sound);
}
else
FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0);
#end
var hmm;
@ -432,12 +495,27 @@ class SongMetadata
{
public var songName:String = "";
public var week:Int = 0;
#if sys
public var sm:SMFile;
public var path:String;
#end
public var songCharacter:String = "";
#if sys
public function new(song:String, week:Int, songCharacter:String, ?sm:SMFile = null, ?path:String = "")
{
this.songName = song;
this.week = week;
this.songCharacter = songCharacter;
this.sm = sm;
this.path = path;
}
#else
public function new(song:String, week:Int, songCharacter:String)
{
this.songName = song;
this.week = week;
this.songCharacter = songCharacter;
}
#end
}

View File

@ -12,13 +12,17 @@ class HealthIcon extends FlxSprite
public function new(char:String = 'bf', isPlayer:Bool = false)
{
super();
loadGraphic(Paths.image('iconGrid'), true, 150, 150);
if(FlxG.save.data.antialiasing)
{
antialiasing = true;
}
if (char == 'sm')
{
loadGraphic(Paths.image("stepmania-icon"));
return;
}
loadGraphic(Paths.image('iconGrid'), true, 150, 150);
animation.add('bf', [0, 1], 0, false, isPlayer);
animation.add('bf-car', [0, 1], 0, false, isPlayer);
animation.add('bf-christmas', [0, 1], 0, false, isPlayer);

View File

@ -12,4 +12,5 @@ class HelperFunctions
public static function GCD(a, b) {
return b == 0 ? FlxMath.absInt(a) : GCD(b, a % b);
}
}

View File

@ -38,9 +38,9 @@ class MainMenuState extends MusicBeatState
var newGaming2:FlxText;
public static var firstStart:Bool = true;
public static var nightly:String = "";
public static var nightly:String = "-Pre-Release";
public static var kadeEngineVer:String = "1.5.4" + nightly;
public static var kadeEngineVer:String = "1.6" + nightly;
public static var gameVer:String = "0.2.7.1";
var magenta:FlxSprite;

View File

@ -3,15 +3,11 @@ package;
#if windows
import Discord.DiscordClient;
#end
import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
import openfl.Lib;
import Conductor.BPMChangeEvent;
import flixel.FlxG;
import flixel.addons.transition.FlxTransitionableState;
import flixel.addons.ui.FlxUIState;
import flixel.math.FlxRect;
import flixel.util.FlxTimer;
class MusicBeatState extends FlxUIState
{
@ -20,6 +16,7 @@ class MusicBeatState extends FlxUIState
private var curStep:Int = 0;
private var curBeat:Int = 0;
private var curDecimalBeat:Float = 0;
private var controls(get, never):Controls;
inline function get_controls():Controls
@ -27,6 +24,7 @@ class MusicBeatState extends FlxUIState
override function create()
{
TimingStruct.clearTimings();
(cast (Lib.current.getChildAt(0), Main)).setFPSCap(FlxG.save.data.fpsCap);
if (transIn != null)
@ -73,6 +71,29 @@ class MusicBeatState extends FlxUIState
}
}
if (Conductor.songPosition < 0)
curDecimalBeat = 0;
else
{
if (TimingStruct.AllTimings.length > 1)
{
var data = TimingStruct.getTimingAtTimestamp(Conductor.songPosition);
FlxG.watch.addQuick("Current Conductor Timing Seg", data.bpm);
Conductor.crochet = ((60 / data.bpm) * 1000);
var percent = (Conductor.songPosition - (data.startTime * 1000)) / (data.length * 1000);
curDecimalBeat = data.startBeat + (((Conductor.songPosition/1000) - data.startTime) * (data.bpm / 60));
}
else
{
curDecimalBeat = (Conductor.songPosition / 1000) * (Conductor.bpm/60);
Conductor.crochet = ((60 / Conductor.bpm) * 1000);
}
}
if (FlxG.save.data.fpsRain && skippedFrames >= 6)
{
if (currentColor >= array.length)

View File

@ -33,6 +33,8 @@ class Note extends FlxSprite
public var originColor:Int = 0; // The sustain note's original note's color
public var noteSection:Int = 0;
public var noteCharterObject:FlxSprite;
public var noteScore:Float = 1;
public var noteYOff:Int = 0;

30
source/OFLWaveform.hx Normal file
View File

@ -0,0 +1,30 @@
import lime.media.AudioSource;
import lime.media.AudioBuffer;
import openfl.media.Sound;
import openfl.display.Graphics;
import openfl.display.Sprite;
class OFLWaveform extends Sprite
{
public var musicLength = 0;
public var _x = 0;
public var _y = 0;
public var _sound:String;
function new(x,y,musicLength, data:String)
{
super();
_x = x;
_y = y;
_sound = data;
this.musicLength = musicLength;
}
public function drawWaveform()
{
var gfx:Graphics = graphics;
gfx.clear();
}
}

View File

@ -59,6 +59,13 @@ class OutdatedSubState extends MusicBeatState
+ "\n& more changes and bugfixes in the full changelog"
+ "\n\nPress Space to view the full changelog and update\nor ESCAPE to ignore this",
32);
if (MainMenuState.nightly != "")
txt.text =
"You are on\n"
+ MainMenuState.kadeEngineVer + "-" + MainMenuState.nightly
+ "\nWhich is a PRE-RELEASE BUILD!"
+ "\n\nReport all bugs to the author of the pre-release.\nSpace/Escape ignores this.";
txt.setFormat("VCR OSD Mono", 32, FlxColor.fromRGB(200, 200, 200), CENTER);
txt.borderColor = FlxColor.BLACK;
@ -92,10 +99,15 @@ class OutdatedSubState extends MusicBeatState
override function update(elapsed:Float)
{
if (controls.ACCEPT)
if (controls.ACCEPT && MainMenuState.nightly == "")
{
fancyOpenURL("https://kadedev.github.io/Kade-Engine/changelogs/changelog-" + needVer);
}
else if (controls.ACCEPT)
{
leftState = true;
FlxG.switchState(new MainMenuState());
}
if (controls.BACK)
{
leftState = true;

View File

@ -133,6 +133,11 @@ class PauseSubState extends MusicBeatSubstate
}
var songPath = 'assets/data/' + songLowercase + '/';
#if sys
if (PlayState.isSM && !PlayState.isStoryMode)
songPath = PlayState.pathToSm;
#end
if (controls.UP_P || upPcontroller)
{
changeSelection(-1);

View File

@ -1,5 +1,11 @@
package;
import Song.Event;
import openfl.media.Sound;
#if sys
import sys.io.File;
import smTools.SMFile;
#end
import openfl.ui.KeyLocation;
import openfl.events.Event;
import haxe.EnumTools;
@ -113,6 +119,12 @@ class PlayState extends MusicBeatState
private var vocals:FlxSound;
public static var isSM:Bool = false;
#if sys
public static var sm:SMFile;
public static var pathToSm:String;
#end
public var originalX:Float;
public static var dad:Character;
@ -170,6 +182,8 @@ class PlayState extends MusicBeatState
public static var offsetTesting:Bool = false;
public var isSMFile:Bool = false;
var notesHitArray:Array<Date> = [];
var currentFrames:Int = 0;
var idleToBeat:Bool = true; // change if bf and dad would idle to the beat of the song
@ -261,6 +275,8 @@ class PlayState extends MusicBeatState
override public function create()
{
FlxG.mouse.visible = false;
instance = this;
if (FlxG.save.data.fpsCap > 290)
@ -377,6 +393,47 @@ class PlayState extends MusicBeatState
Conductor.mapBPMChanges(SONG);
Conductor.changeBPM(SONG.bpm);
if (SONG.eventObjects == null)
{
SONG.eventObjects = [new Song.Event("Init BPM",0,SONG.bpm,"BPM Change")];
}
TimingStruct.clearTimings();
var convertedStuff:Array<Song.Event> = [];
var currentIndex = 0;
for (i in SONG.eventObjects)
{
var name = Reflect.field(i,"name");
var type = Reflect.field(i,"type");
var pos = Reflect.field(i,"position");
var value = Reflect.field(i,"value");
if (type == "BPM Change")
{
var beat:Float = pos;
var endBeat:Float = Math.POSITIVE_INFINITY;
TimingStruct.addTiming(beat,value,endBeat, 0); // offset in this case = start time since we don't have a offset
if (currentIndex != 0)
{
var data = TimingStruct.AllTimings[currentIndex - 1];
data.endBeat = beat;
data.length = (data.endBeat - data.startBeat) / (data.bpm / 60);
TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length;
}
currentIndex++;
}
convertedStuff.push(new Song.Event(name,pos,value,type));
}
SONG.eventObjects = convertedStuff;
trace('INFORMATION ABOUT WHAT U PLAYIN WIT:\nFRAMES: ' + PlayStateChangeables.safeFrames + '\nZONE: ' + Conductor.safeZoneOffset + '\nTS: '
+ Conductor.timeScale + '\nBotPlay : ' + PlayStateChangeables.botPlay);
@ -1630,7 +1687,20 @@ class PlayState extends MusicBeatState
if (!paused)
{
#if sys
if (!isStoryMode && isSM)
{
trace("Loading " + pathToSm + "/" + sm.header.MUSIC);
var bytes = File.getBytes(pathToSm + "/" + sm.header.MUSIC);
var sound = new Sound();
sound.loadCompressedDataFromByteArray(bytes.getData(), bytes.length);
FlxG.sound.playMusic(sound);
}
else
FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false);
#else
FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false);
#end
}
FlxG.sound.music.onComplete = endSong;
@ -1715,10 +1785,17 @@ class PlayState extends MusicBeatState
curSong = songData.song;
#if sys
if (SONG.needsVoices && !isSM)
vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song));
else
vocals = new FlxSound();
#else
if (SONG.needsVoices)
vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song));
else
vocals = new FlxSound();
#end
trace('loaded vocals');
@ -1747,6 +1824,11 @@ class PlayState extends MusicBeatState
}
var songPath = 'assets/data/' + songLowercase + '/';
#if sys
if (isSM && !isStoryMode)
songPath = pathToSm;
#end
for (file in sys.FileSystem.readDirectory(songPath))
{
@ -2100,12 +2182,77 @@ class PlayState extends MusicBeatState
public var stopUpdate = false;
public var removedVideo = false;
public var currentBPM = 0;
public var updateFrame = 0;
override public function update(elapsed:Float)
{
#if !debug
perfectMode = false;
#end
if (updateFrame == 4)
{
TimingStruct.clearTimings();
var currentIndex = 0;
for (i in SONG.eventObjects)
{
if (i.type == "BPM Change")
{
var beat:Float = i.position;
var endBeat:Float = Math.POSITIVE_INFINITY;
TimingStruct.addTiming(beat,i.value,endBeat, 0); // offset in this case = start time since we don't have a offset
if (currentIndex != 0)
{
var data = TimingStruct.AllTimings[currentIndex - 1];
data.endBeat = beat;
data.length = (data.endBeat - data.startBeat) / (data.bpm / 60);
TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length;
}
currentIndex++;
}
}
updateFrame++;
}
else if (updateFrame != 5)
updateFrame++;
var timingSeg = TimingStruct.getTimingAtTimestamp(Conductor.songPosition);
if (timingSeg != null)
{
var timingSegBpm = timingSeg.bpm;
if (timingSegBpm != Conductor.bpm)
{
trace("BPM CHANGE to " + timingSegBpm);
Conductor.changeBPM(timingSegBpm, false);
}
}
var newScroll = PlayStateChangeables.scrollSpeed;
for(i in SONG.eventObjects)
{
switch(i.type)
{
case "Scroll Speed Change":
if (i.position < curDecimalBeat)
newScroll = i.value;
}
}
PlayStateChangeables.scrollSpeed = newScroll;
if (PlayStateChangeables.botPlay && FlxG.keys.justPressed.ONE)
camHUD.visible = !camHUD.visible;
@ -2596,6 +2743,9 @@ class PlayState extends MusicBeatState
camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95);
}
FlxG.watch.addQuick("curBPM", Conductor.bpm);
FlxG.watch.addQuick("Closest Note", (unspawnNotes.length != 0 ? unspawnNotes[0].strumTime - Conductor.songPosition : "No note"));
FlxG.watch.addQuick("beatShit", curBeat);
FlxG.watch.addQuick("stepShit", curStep);
@ -4259,11 +4409,6 @@ class PlayState extends MusicBeatState
if (SONG.notes[Math.floor(curStep / 16)] != null)
{
if (SONG.notes[Math.floor(curStep / 16)].changeBPM)
{
Conductor.changeBPM(SONG.notes[Math.floor(curStep / 16)].bpm);
FlxG.log.add('CHANGED BPM!');
}
// else
// Conductor.changeBPM(SONG.bpm);

View File

@ -2,6 +2,8 @@ package;
typedef SwagSection =
{
var startTime:Float;
var endTime:Float;
var sectionNotes:Array<Array<Dynamic>>;
var lengthInSteps:Int;
var typeOfSection:Int;
@ -13,6 +15,8 @@ typedef SwagSection =
class Section
{
public var startTime:Float = 0;
public var endTime:Float = 0;
public var sectionNotes:Array<Array<Dynamic>> = [];
public var lengthInSteps:Int = 16;

32
source/SectionRender.hx Normal file
View File

@ -0,0 +1,32 @@
import flixel.FlxG;
import flixel.util.FlxColor;
import flixel.group.FlxGroup.FlxTypedGroup;
import Section.SwagSection;
import flixel.addons.display.FlxGridOverlay;
import flixel.FlxSprite;
class SectionRender extends FlxSprite
{
public var section:SwagSection;
public var icon:FlxSprite;
public var lastUpdated:Bool;
public function new(x:Float,y:Float,GRID_SIZE:Int, ?Height:Int = 16)
{
super(x,y);
makeGraphic(GRID_SIZE * 8, GRID_SIZE * Height,FlxColor.BLACK);
var h = GRID_SIZE;
if (Math.floor(h) != h)
h = GRID_SIZE;
FlxGridOverlay.overlay(this,GRID_SIZE, Std.int(h), GRID_SIZE * 8,GRID_SIZE * Height);
}
override function update(elapsed)
{
}
}

View File

@ -7,10 +7,28 @@ import lime.utils.Assets;
using StringTools;
class Event
{
public var name:String;
public var position:Float;
public var value:Dynamic;
public var type:String;
public function new(name:String,pos:Float,value:Dynamic,type:String)
{
this.name = name;
this.position = pos;
this.value = value;
this.type = type;
}
}
typedef SwagSong =
{
var chartVersion:String;
var song:String;
var notes:Array<SwagSection>;
var eventObjects:Array<Event>;
var bpm:Float;
var needsVoices:Bool;
var speed:Float;
@ -25,10 +43,12 @@ typedef SwagSong =
class Song
{
public var chartVersion:String;
public var song:String;
public var notes:Array<SwagSection>;
public var bpm:Float;
public var needsVoices:Bool = true;
public var eventObjects:Array<Event>;
public var speed:Float = 1;
public var player1:String = 'bf';
@ -44,10 +64,19 @@ class Song
this.bpm = bpm;
}
public static function loadFromJsonRAW(rawJson:String)
{
while (!rawJson.endsWith("}"))
{
rawJson = rawJson.substr(0, rawJson.length - 1);
// LOL GOING THROUGH THE BULLSHIT TO CLEAN IDK WHATS STRANGE
}
return parseJSONshit(rawJson);
}
public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong
{
trace(jsonInput);
// pre lowercasing the folder name
var folderLowercase = StringTools.replace(folder, " ", "-").toLowerCase();
switch (folderLowercase) {

55
source/TimingStruct.hx Normal file
View File

@ -0,0 +1,55 @@
import flixel.FlxG;
class TimingStruct
{
public static var AllTimings:Array<TimingStruct> = [];
public var bpm:Float = 0;
public var startBeat:Float = 0;
public var endBeat:Float = Math.POSITIVE_INFINITY;
public var startTime:Float = 0;
public var length:Float = Math.POSITIVE_INFINITY; // in beats
public static function clearTimings()
{
AllTimings = [];
}
public static function addTiming(startBeat,bpm,endBeat:Float, offset:Float)
{
var pog = new TimingStruct(startBeat,bpm,endBeat, offset);
AllTimings.push(pog);
}
public function new(startBeat,bpm,endBeat:Float, offset:Float)
{
this.bpm = bpm;
this.startBeat = startBeat;
if (endBeat != -1)
this.endBeat = endBeat;
startTime = offset;
}
public static function getTimingAtTimestamp(msTime:Float):TimingStruct
{
for(i in AllTimings)
{
if (msTime >= i.startTime * 1000 && msTime < (i.startTime + i.length) * 1000)
return i;
}
trace('Apparently ' + msTime + ' is out of any segs');
return null;
}
public static function getTimingAtBeat(beat):TimingStruct
{
for(i in AllTimings)
{
if (i.startBeat <= beat && i.endBeat >= beat)
return i;
}
return null;
}
}

View File

@ -84,9 +84,6 @@ class TitleState extends MusicBeatState
trace('NEWGROUNDS LOL');
#end
// var file:SMFile = SMFile.loadFile("file.sm");
// this was testing things
#if FREEPLAY
FlxG.switchState(new FreeplayState());
#elseif CHARTING
@ -303,7 +300,7 @@ class TitleState extends MusicBeatState
{
returnedData[0] = data.substring(0, data.indexOf(';'));
returnedData[1] = data.substring(data.indexOf('-'), data.length);
if (!MainMenuState.kadeEngineVer.contains(returnedData[0].trim()) && !OutdatedSubState.leftState && MainMenuState.nightly == "")
if (!MainMenuState.kadeEngineVer.contains(returnedData[0].trim()) && !OutdatedSubState.leftState)
{
trace('outdated lmao! ' + returnedData[0] + ' != ' + MainMenuState.kadeEngineVer);
OutdatedSubState.needVer = returnedData[0];

View File

@ -1,7 +1,9 @@
#if sys
package smTools;
import sys.io.File;
import haxe.Exception;
import lime.app.Application;
import haxe.Json;
class SMFile
{
@ -12,6 +14,10 @@ class SMFile
private var _fileData:Array<String>;
public var isDouble:Bool = false;
public var isValid:Bool = true;
public var _readTime:Float = 0;
public var header:SMHeader;
@ -19,43 +25,230 @@ class SMFile
public function new(data:Array<String>)
{
_fileData = data;
// Gather header data
var headerData = "";
var inc = 0;
while(!StringTools.contains(data[inc + 1],"//"))
try
{
headerData += data[inc] + "\n";
inc++;
// trace(data[inc]);
}
_fileData = data;
header = new SMHeader(headerData.split('\n'));
// check if this is a valid file, it should be a dance double file.
inc += 3; // skip three lines down
if (!StringTools.contains(data[inc],"dance-double:"))
return;
trace('this is dance double');
inc += 4; // skip 5 down to where da notes @
trace(data[inc]);
measures = [];
while(data[inc + 1] != ";")
{
var measure = "";
while(data[inc + 1] != ",")
// Gather header data
var headerData = "";
var inc = 0;
while(!StringTools.contains(data[inc + 1],"//"))
{
headerData += data[inc];
inc++;
var line = data[inc];
measure += line + "\n";
// trace(data[inc]);
}
measures.push(new SMMeasure(measure.split('\n')));
header = new SMHeader(headerData.split(';'));
if (!StringTools.contains(header.MUSIC,"ogg"))
{
Application.current.window.alert("The music MUST be an OGG File.","SM File loading (" + header.TITLE + ")");
isValid = false;
return;
}
// check if this is a valid file, it should be a dance double file.
inc += 3; // skip three lines down
if (!StringTools.contains(data[inc],"dance-double:") && !StringTools.contains(data[inc],"dance-single"))
{
Application.current.window.alert("The file you are loading is neither a Dance Double chart or a Dance Single chart","SM File loading (" + header.TITLE + ")");
isValid = false;
return;
}
if (StringTools.contains(data[inc],"dance-double:"))
isDouble = true;
if (isDouble)
trace('this is dance double');
inc += 5; // skip 5 down to where da notes @
measures = [];
var measure = "";
trace(data[inc - 1]);
for (ii in inc...data.length)
{
var i = data[ii];
if (StringTools.contains(i,",") || StringTools.contains(i,";"))
{
measures.push(new SMMeasure(measure.split('\n')));
//trace(measures.length);
measure = "";
continue;
}
measure += i + "\n";
}
trace(measures.length + " Measures");
}
trace(measures.length + " Measures");
catch(e:Exception)
{
Application.current.window.alert("Failure to load file.\n" + e,"SM File loading");
}
}
public function convertToFNF(saveTo:String):String
{
// array's for helds
var heldNotes:Array<Array<Dynamic>>;
if (isDouble) // held storage lanes
heldNotes = [[],[],[],[],[],[],[],[]];
else
heldNotes = [[],[],[],[]];
// variables
var measureIndex = 0;
var currentBeat:Float = 0;
var output = "";
// init a fnf song
var song = {
song: header.TITLE,
notes: [],
eventObjects: [],
bpm: header.getBPM(0),
needsVoices: true,
player1: 'bf',
player2: 'gf',
gfVersion: 'gf',
noteStyle: 'normal',
stage: 'stage',
speed: 1.0,
validScore: false
};
// lets check if the sm loading was valid
if (!isValid)
{
var json = {
"song": song
};
var data:String = Json.stringify(json,null," ");
File.saveContent(saveTo,data);
return data;
}
// aight time to convert da measures
trace("Converting measures");
for(measure in measures)
{
// private access since _measure is private
@:privateAccess
var lengthInRows = 192 / (measure._measure.length - 1);
var rowIndex = 0;
// section declaration
var section = {
sectionNotes: [],
lengthInSteps: 16,
typeOfSection: 0,
mustHitSection: false,
bpm: header.getBPM(0),
changeBPM: false,
altAnim: false
};
// if it's not a double always set this to true
if (!isDouble)
section.mustHitSection = true;
@:privateAccess
for(i in 0...measure._measure.length - 1)
{
var noteRow = (measureIndex * 192) + (lengthInRows * rowIndex);
var notes:Array<String> = [];
for(note in measure._measure[i].split(''))
{
//output += note;
notes.push(note);
}
currentBeat = noteRow / 48;
var seg = TimingStruct.getTimingAtBeat(currentBeat);
var timeInSec:Float = (seg.startTime + ((currentBeat - seg.startBeat) / (seg.bpm/60)));
var rowTime = timeInSec * 1000;
//output += " - Row " + noteRow + " - Time: " + rowTime + " (" + timeInSec + ") - Beat: " + currentBeat + " - Current BPM: " + header.getBPM(currentBeat) + "\n";
var index = 0;
var takeover = false;
for(i in notes)
{
// if its a mine lets skip (maybe add mines in the future??)
if (i == "M")
continue;
// get the lane and note type
var lane = index;
var numba = Std.parseInt(i);
// switch through the type and add the note
switch(numba)
{
case 1: // normal
section.sectionNotes.push([rowTime,lane ,0]);
case 2: // held head
heldNotes[lane] = [rowTime,lane,0];
case 3: // held tail
var data = heldNotes[lane];
var timeDiff = rowTime - data[0];
section.sectionNotes.push([data[0],lane,timeDiff]);
heldNotes[index] = [];
}
index++;
}
rowIndex++;
}
// push the section
song.notes.push(section);
//output += ",\n";
measureIndex++;
}
//File.saveContent("fuac" + header.TITLE,output);
if (header.changeEvents.length != 0)
{
song.eventObjects = header.changeEvents;
}
// save da song
var json = {
"song": song
};
var data:String = Json.stringify(json,null," ");
File.saveContent(saveTo,data);
return data;
}
}
#end

View File

@ -15,13 +15,83 @@ class SMHeader
public var BACKGROUND = "";
public var CDTITLE = "";
public var OFFSET = "";
public var BPMS = "";
public var BPMS = ""; // time=bpm
public var changeEvents:Array<Song.Event>;
public function new(headerData:Array<String>)
{
_header = headerData;
for (i in headerData)
{
readHeaderLine(i);
}
trace(BPMS);
MUSIC = StringTools.replace(MUSIC," ", "_");
changeEvents = [];
getBPM(0,true);
}
public function getBeatFromBPMIndex(index):Float
{
var bpmSplit = BPMS.split(',');
var beat = 0;
for(ii in 0...bpmSplit.length)
{
if (ii == index)
return Std.parseFloat(StringTools.replace(bpmSplit[ii].split('=')[0],",",""));
}
return 0.0;
}
public function getBPM(beat:Float, printAllBpms:Bool = false)
{
var bpmSplit = BPMS.split(',');
if (printAllBpms)
{
TimingStruct.clearTimings();
var currentIndex = 0;
for(i in bpmSplit)
{
var bpm:Float = Std.parseFloat(i.split('=')[1]);
var beat:Float = Std.parseFloat(StringTools.replace(i.split('=')[0],",",""));
var endBeat:Float = Math.POSITIVE_INFINITY;
TimingStruct.addTiming(beat,bpm,endBeat, -Std.parseFloat(OFFSET));
if (changeEvents.length != 0)
{
var data = TimingStruct.AllTimings[currentIndex - 1];
data.endBeat = beat;
data.length = (data.endBeat - data.startBeat) / (data.bpm / 60);
TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length;
}
changeEvents.push(new Song.Event(HelperFunctions.truncateFloat(beat,0) + "SM",beat,bpm,"BPM Change"));
if (bpmSplit.length == 1)
break;
currentIndex++;
}
trace(changeEvents.length + " - BPM CHANGES");
return 0.0;
}
var returningBPM = Std.parseFloat(bpmSplit[0].split('=')[1]);
for(i in bpmSplit)
{
var bpm:Float = Std.parseFloat(i.split('=')[1]);
var beatt:Float = Std.parseFloat(StringTools.replace(i.split('=')[0],",",""));
if (beatt <= beat)
returningBPM = bpm;
}
return returningBPM;
}
function readHeaderLine(line:String)

View File

@ -11,6 +11,19 @@ class SMMeasure
{
_measure = measureData;
notes = [];
// 0 = no note
// 1 = normal note
// 2 = head of sustain
// 3 = tail of sustain
for(i in measureData)
{
for (ii in 0...i.length)
{
notes.push(new SMNote(i.split('')[ii],ii));
}
}
}
}
#end

View File

@ -3,8 +3,13 @@ package smTools;
class SMNote
{
public var time:Float;
public var data:Int;
public var length:Float;
public var data:String;
public var lane:Int;
public function new(_data:String,_lane:Int)
{
data = _data;
lane = _lane;
}
}
#end