diff --git a/Project.xml b/Project.xml index eeffad6..320a787 100644 --- a/Project.xml +++ b/Project.xml @@ -57,6 +57,7 @@ +
@@ -69,6 +70,7 @@ +
@@ -89,7 +91,9 @@ - + + + diff --git a/README.md b/README.md index a1645e9..0711867 100644 --- a/README.md +++ b/README.md @@ -75,4 +75,5 @@ This game was made with love to Newgrounds and its community. Extra love to Tom - [GWebDev](https://github.com/GrowtopiaFli) - Video Code - [Rozebud](https://github.com/ThatRozebudDude) - Ideas (that I stole) - [Puyo](https://github.com/daniel11420) - Setting up appveyor and a lot of other help -- [Smokey](https://twitter.com/Smokey_5_) - telling me that I should do the tricky asset loading \ No newline at end of file +- [Smokey](https://twitter.com/Smokey_5_) - telling me that I should do the tricky asset loading +- [Poco](https://github.com/poco0317) - math degree (aka most of the fucking math in this project) \ No newline at end of file diff --git a/assets/preload/images/stepmania-icon.png b/assets/preload/images/stepmania-icon.png new file mode 100644 index 0000000..023353b Binary files /dev/null and b/assets/preload/images/stepmania-icon.png differ diff --git a/assets/sm/HOW TO ADD SM FILES.txt b/assets/sm/HOW TO ADD SM FILES.txt new file mode 100644 index 0000000..5eb12c3 --- /dev/null +++ b/assets/sm/HOW TO ADD SM FILES.txt @@ -0,0 +1 @@ +Put both the .sm and .ogg in the same folder and put the folder in this folder. Launch the game and go into freeplay, it'll load into the song list. \ No newline at end of file diff --git a/source/ChartingState.hx b/source/ChartingState.hx index 14a7e5d..db20a29 100644 --- a/source/ChartingState.hx +++ b/source/ChartingState.hx @@ -1,5 +1,12 @@ package; +import openfl.system.System; +import lime.app.Application; +#if sys +import sys.io.File; +#end +import flixel.addons.ui.FlxUIButton; +import flixel.addons.ui.StrNameLabel; import flixel.FlxCamera; import flixel.FlxObject; import flixel.addons.ui.FlxUIText; @@ -42,15 +49,25 @@ using StringTools; class ChartingState extends MusicBeatState { + public static var instance:ChartingState; + var _file:FileReference; public var playClaps:Bool = false; - public var snap:Int = 1; + public var snap:Int = 16; + + public var deezNuts:Map = new Map(); // snap conversion map var UI_box:FlxUITabMenu; var UI_options:FlxUITabMenu; + public static var lengthInSteps:Float = 0; + public static var lengthInBeats:Float = 0; + + public var beatsShown:Float = 1; // for the zoom factor + public var zoomFactor:Float = 1; + /** * Array of notes showing when each section STARTS in STEPS * Usually rounded up?? @@ -75,11 +92,14 @@ class ChartingState extends MusicBeatState var dummyArrow:FlxSprite; + var curRenderedNotes:FlxTypedGroup; var curRenderedSustains:FlxTypedGroup; var gridBG:FlxSprite; + public var sectionRenderes:FlxTypedGroup; + public static var _song:SwagSong; var typingShit:FlxInputText; @@ -95,27 +115,55 @@ class ChartingState extends MusicBeatState var player2:Character = new Character(0,0, "dad"); var player1:Boyfriend = new Boyfriend(0,0, "bf"); - var leftIcon:HealthIcon; - var rightIcon:HealthIcon; + public static var leftIcon:HealthIcon; + + var height = 0; + + public static var rightIcon:HealthIcon; private var lastNote:Note; + + public var lines:FlxTypedGroup; + var claps:Array = []; public var snapText:FlxText; var camFollow:FlxObject; + public static var latestChartVersion = "2"; + override function create() { curSection = lastSection; + trace(1 > Math.POSITIVE_INFINITY); + + FlxG.mouse.visible = true; + + instance = this; + + deezNuts.set(4,1); + deezNuts.set(8,2); + deezNuts.set(16,4); + deezNuts.set(32,8); + deezNuts.set(64,16); + + sectionRenderes = new FlxTypedGroup(); + lines = new FlxTypedGroup(); + texts = new FlxTypedGroup(); + + TimingStruct.clearTimings(); + if (PlayState.SONG != null) _song = PlayState.SONG; else { _song = { + chartVersion: latestChartVersion, song: 'Test', notes: [], + eventObjects: [], bpm: 150, needsVoices: true, player1: 'bf', @@ -130,18 +178,19 @@ class ChartingState extends MusicBeatState addGrid(1); - var blackBorder:FlxSprite = new FlxSprite(60,10).makeGraphic(120,100,FlxColor.BLACK); - blackBorder.scrollFactor.set(); + if (_song.chartVersion == null) + _song.chartVersion = "2"; + - blackBorder.alpha = 0.3; + //var blackBorder:FlxSprite = new FlxSprite(60,10).makeGraphic(120,100,FlxColor.BLACK); + //blackBorder.scrollFactor.set(); - /* - snapText = new FlxText(60,10,0,"Snap: 1/" + snap + " (Press SHIFT to unsnap the cursor)\nAdd Notes: 1-8 (or click)\nDiff: 0", 14); + //blackBorder.alpha = 0.3; + + + snapText = new FlxText(60,10,0,"", 14); snapText.scrollFactor.set(); - */ - - gridBlackLine = new FlxSprite(gridBG.x + gridBG.width / 2).makeGraphic(2, Std.int(gridBG.height), FlxColor.BLACK); - add(gridBlackLine); + curRenderedNotes = new FlxTypedGroup(); curRenderedSustains = new FlxTypedGroup(); @@ -155,16 +204,117 @@ class ChartingState extends MusicBeatState // sections = _song.notes; - updateGrid(); - loadSong(_song.song); Conductor.changeBPM(_song.bpm); Conductor.mapBPMChanges(_song); leftIcon = new HealthIcon(_song.player1); rightIcon = new HealthIcon(_song.player2); - leftIcon.scrollFactor.set(1, 1); - rightIcon.scrollFactor.set(1, 1); + + var index = 0; + + + + trace("goin"); + + 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++; + } + } + + var lastSeg = TimingStruct.AllTimings[TimingStruct.AllTimings.length - 1]; + + for (i in 0...TimingStruct.AllTimings.length) + { + var seg = TimingStruct.AllTimings[i]; + if (i == TimingStruct.AllTimings.length - 1) + lastSeg = seg; + } + + recalculateAllSectionTimes(); + + trace("Song length in MS: " + FlxG.sound.music.length); + + for(i in 0...9000000) // REALLY HIGH BEATS just cuz like ig this is the upper limit, I mean ur chart is probably going to run like ass anyways + { + var seg = TimingStruct.getTimingAtBeat(i); + + + var start:Float = (i - seg.startBeat) / (seg.bpm / 60); + + var time = (seg.startTime + start) * 1000; + + if (time > FlxG.sound.music.length) + break; + + lengthInBeats = i; + } + + lengthInSteps = lengthInBeats * 4; + + trace('LENGTH IN STEPS ' + lengthInSteps + ' | LENGTH IN BEATS ' + lengthInBeats + ' | SECTIONS: ' + Math.floor(((lengthInSteps + 16)) / 16)); + + var sections = Math.floor(((lengthInSteps + 16)) / 16); + + var targetY = getYfromStrum(FlxG.sound.music.length); + + trace("TARGET " + targetY); + + for (awfgaw in 0...Math.round(targetY / 640) + 1920) // grids/steps + { + var renderer = new SectionRender(0,640 * awfgaw,GRID_SIZE); + if (_song.notes[awfgaw] == null) + _song.notes.push(newSection(16,true,false)); + renderer.section = _song.notes[awfgaw]; + + sectionRenderes.add(renderer); + + var down = getYfromStrum(renderer.section.startTime) * zoomFactor; + + var sectionicon = _song.notes[awfgaw].mustHitSection ? new HealthIcon(_song.player1).clone() : new HealthIcon(_song.player2).clone(); + sectionicon.x = -95; + sectionicon.y = down - 75; + sectionicon.setGraphicSize(0, 45); + + renderer.icon = sectionicon; + renderer.lastUpdated = _song.notes[awfgaw].mustHitSection; + + add(sectionicon); + height = Math.floor(renderer.y); + } + + + + trace(height); + + gridBlackLine = new FlxSprite(gridBG.width / 2).makeGraphic(2, height, FlxColor.BLACK); + + //leftIcon.scrollFactor.set(); + //rightIcon.scrollFactor.set(); + leftIcon.setGraphicSize(0, 45); rightIcon.setGraphicSize(0, 45); @@ -175,16 +325,16 @@ class ChartingState extends MusicBeatState leftIcon.setPosition(0, -100); rightIcon.setPosition(gridBG.width / 2, -100); + leftIcon.scrollFactor.set(); + rightIcon.scrollFactor.set(); + bpmTxt = new FlxText(1000, 50, 0, "", 16); bpmTxt.scrollFactor.set(); add(bpmTxt); - strumLine = new FlxSprite(0, 50).makeGraphic(Std.int(GRID_SIZE * 8), 4); - add(strumLine); + strumLine = new FlxSprite(0, 0).makeGraphic(Std.int(GRID_SIZE * 8), 4); dummyArrow = new FlxSprite().makeGraphic(GRID_SIZE, GRID_SIZE); - add(dummyArrow); - var tabs = [ {name: "Song", label: 'Song Data'}, {name: "Section", label: 'Section Data'}, @@ -200,7 +350,7 @@ class ChartingState extends MusicBeatState UI_box.y = 20; add(UI_box); - var opt_tabs = [{name: "Options", label:'Editor Options'}]; + var opt_tabs = [{name: "Options", label:'Song Options'}, {name: "Events", label:'Song Events'}]; UI_options = new FlxUITabMenu(null, opt_tabs, true); @@ -211,23 +361,128 @@ class ChartingState extends MusicBeatState UI_options.y = FlxG.height - 300; add(UI_options); + addSongUI(); addSectionUI(); addNoteUI(); addOptionsUI(); + addEventsUI(); + regenerateLines(); + + + updateGrid(); + + trace("bruh"); + + + add(sectionRenderes); + add(dummyArrow); + add(strumLine); + add(lines); + add(texts); + add(gridBlackLine); add(curRenderedNotes); add(curRenderedSustains); - add(blackBorder); - //add(snapText); + trace("bruh"); + //add(blackBorder); + add(snapText); + trace("bruh"); + trace("create"); + + 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++; + } + } super.create(); } + public var texts:FlxTypedGroup; + + function regenerateLines() + { + while(lines.members.length > 0) + { + lines.members[0].destroy(); + lines.members.remove(lines.members[0]); + } + + while(texts.members.length > 0) + { + texts.members[0].destroy(); + texts.members.remove(texts.members[0]); + } + trace("removed lines and texts"); + + if (_song.eventObjects != null) + for(i in _song.eventObjects) + { + var seg = TimingStruct.getTimingAtBeat(i.position); + + var posi:Float = 0; + + if (seg != null) + { + var start:Float = (i.position - seg.startBeat) / (seg.bpm / 60); + + posi = seg.startTime + start; + } + + var pos = getYfromStrum(posi * 1000) * zoomFactor; + + if (pos < 0) + pos = 0; + + var type = i.type; + + var text = new FlxText(-190, pos,0,i.name + "\n" + type + "\n" + i.value,12); + var line = new FlxSprite(0, pos).makeGraphic(Std.int(GRID_SIZE * 8), 4, FlxColor.BLUE); + + line.alpha = 0.2; + + lines.add(line); + texts.add(text); + + add(line); + add(text); + } + + for (i in sectionRenderes) + { + var pos = getYfromStrum(i.section.startTime) * zoomFactor; + i.icon.y = pos - 75; + + var line = new FlxSprite(0, pos).makeGraphic(Std.int(GRID_SIZE * 8), 4, FlxColor.BLACK); + line.alpha = 0.4; + lines.add(line); + } + } + function addGrid(?divisions:Float = 1) { // This here is because non-integer numbers aren't supported as grid sizes, making the grid slowly 'drift' as it goes on @@ -236,19 +491,430 @@ class ChartingState extends MusicBeatState h = GRID_SIZE; remove(gridBG); - gridBG = FlxGridOverlay.create(GRID_SIZE, Std.int(h), GRID_SIZE * 8, GRID_SIZE * 16); - add(gridBG); + gridBG = FlxGridOverlay.create(GRID_SIZE, Std.int(h), GRID_SIZE * 8,GRID_SIZE * 16); + trace(gridBG.height); + //gridBG.scrollFactor.set(); + //gridBG.x += 358; + //gridBG.y += 390; + trace("height of " + (Math.floor(lengthInSteps))); + + + /*for(i in 0...Math.floor(lengthInSteps)) + { + trace("Creating sprite " + i); + var grid = FlxGridOverlay.create(GRID_SIZE, Std.int(h), GRID_SIZE * 8, GRID_SIZE * 16); + add(grid); + if (i > lengthInSteps) + break; + }*/ + + var totalHeight = 0; + + //add(gridBG); + + + remove(gridBlackLine); + gridBlackLine = new FlxSprite(0 + gridBG.width / 2).makeGraphic(2, Std.int(Math.floor(lengthInSteps)), FlxColor.BLACK); + add(gridBlackLine); } var stepperDiv:FlxUINumericStepper; var check_snap:FlxUICheckBox; + var listOfEvents:FlxUIDropDownMenu; + var currentSelectedEventName:String = ""; + var savedType:String = ""; + var savedValue:String = ""; + var currentEventPosition:Float = 0; + + function containsName(name:String, events:Array):Song.Event + { + for (i in events) + { + var thisName = Reflect.field(i,"name"); + + if (thisName == name) + return i; + } + return null; + } + + public var chartEvents:Array = []; + + public var Typeables:Array = []; + + function addEventsUI() + { + if (_song.eventObjects == null) + { + _song.eventObjects = [new Song.Event("Init BPM",0,_song.bpm,"BPM Change")]; + } + + var firstEvent = ""; + + if (Lambda.count(_song.eventObjects) != 0) + { + firstEvent = _song.eventObjects[0].name; + } + + var listLabel = new FlxText(10, 5, 'List of Events'); + var nameLabel = new FlxText(150, 5, 'Event Name'); + var eventName = new FlxUIInputText(150,20,80,""); + var typeLabel = new FlxText(10, 45, 'Type of Event'); + var eventType = new FlxUIDropDownMenu(10,60,FlxUIDropDownMenu.makeStrIdLabelArray(["BPM Change", "Scroll Speed Change"], true)); + var valueLabel = new FlxText(150, 45, 'Event Value'); + var eventValue = new FlxUIInputText(150,60,80,""); + var eventSave = new FlxButton(10,155,"Save Event", function() { + var pog:Song.Event = new Song.Event(currentSelectedEventName,currentEventPosition,HelperFunctions.truncateFloat(Std.parseFloat(savedValue), 3),savedType); + + trace("trying to save " + currentSelectedEventName); + + var obj = containsName(pog.name,_song.eventObjects); + + + if (pog.name == "") + return; + + trace("yeah we can save it"); + + if (obj != null) + _song.eventObjects.remove(obj); + _song.eventObjects.push(pog); + + trace(_song.eventObjects.length); + + TimingStruct.clearTimings(); + + 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"); + + trace(i.type); + 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++; + } + } + + if (pog.type == "BPM Change") + recalculateAllSectionTimes(); + + regenerateLines(); + + var listofnames = []; + + for (key => value in _song.eventObjects) { + listofnames.push(value.name); + } + + listOfEvents.setData(FlxUIDropDownMenu.makeStrIdLabelArray(listofnames, true)); + + listOfEvents.selectedLabel = pog.name; + + trace('end'); + }); + var posLabel = new FlxText(150, 85, 'Event Position'); + var eventPos = new FlxUIInputText(150,100,80,""); + var eventAdd = new FlxButton(95,155,"Add Event", function() { + + var pog:Song.Event = new Song.Event("New Event " + HelperFunctions.truncateFloat(curDecimalBeat, 3),HelperFunctions.truncateFloat(curDecimalBeat, 3),_song.bpm + "","BPM Change"); + + trace("adding " + pog.name); + + var obj = containsName(pog.name,_song.eventObjects); + + if (obj != null) + return; + + trace("yeah we can add it"); + + _song.eventObjects.push(pog); + + eventName.text = pog.name; + eventType.selectedLabel = pog.type; + eventValue.text = pog.value; + eventPos.text = pog.position + ""; + currentSelectedEventName = pog.name; + currentEventPosition = pog.position; + + savedType = pog.type; + savedValue = pog.value; + + var listofnames = []; + + for (key => value in _song.eventObjects) { + listofnames.push(value.name); + } + + listOfEvents.setData(FlxUIDropDownMenu.makeStrIdLabelArray(listofnames, true)); + + listOfEvents.selectedLabel = pog.name; + + TimingStruct.clearTimings(); + + 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"); + + trace(i.type); + 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++; + } + } + trace("BPM CHANGES:"); + + for (i in TimingStruct.AllTimings) + trace(i.bpm + " - START: " + i.startBeat + " - END: " + i.endBeat + " - START-TIME: " + i.startTime); + + recalculateAllSectionTimes(); + + regenerateLines(); + + + }); + var eventRemove = new FlxButton(180,155,"Remove Event", function() { + + trace("lets see if we can remove " + listOfEvents.selectedLabel); + + var obj = containsName(listOfEvents.selectedLabel,_song.eventObjects); + + trace(obj); + + if (obj == null) + return; + + trace("yeah we can remove it it"); + + _song.eventObjects.remove(obj); + + var firstEvent = _song.eventObjects[0]; + + if (firstEvent == null) + { + _song.eventObjects.push(new Song.Event("Init BPM",0,_song.bpm,"BPM Change")); + firstEvent = _song.eventObjects[0]; + } + + eventName.text = firstEvent.name; + eventType.selectedLabel = firstEvent.type; + eventValue.text = firstEvent.value; + eventPos.text = firstEvent.position + ""; + currentSelectedEventName = firstEvent.name; + currentEventPosition = firstEvent.position; + + savedType = firstEvent.type; + savedValue = firstEvent.value; + + var listofnames = []; + + for (key => value in _song.eventObjects) { + listofnames.push(value.name); + } + + listOfEvents.setData(FlxUIDropDownMenu.makeStrIdLabelArray(listofnames, true)); + + listOfEvents.selectedLabel = firstEvent.name; + + TimingStruct.clearTimings(); + + 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"); + + trace(i.type); + 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++; + } + } + + recalculateAllSectionTimes(); + + regenerateLines(); + + + }); + var updatePos = new FlxButton(150,120,"Update Pos", function() { + var obj = containsName(currentSelectedEventName,_song.eventObjects); + if (obj == null) + return; + currentEventPosition = curDecimalBeat; + obj.position = currentEventPosition; + eventPos.text = currentEventPosition + ""; + }); + + + + var listofnames = []; + + var firstEventObject = null; + + for (event in _song.eventObjects) { + var name = Reflect.field(event,"name"); + var type = Reflect.field(event,"type"); + var pos = Reflect.field(event,"position"); + var value = Reflect.field(event,"value"); + + trace(value); + + var eventt = new Song.Event(name,pos,value,type); + + chartEvents.push(eventt); + listofnames.push(name); + } + + _song.eventObjects = chartEvents; + + if (listofnames.length == 0) + listofnames.push(""); + + if (_song.eventObjects.length != 0) + firstEventObject = _song.eventObjects[0]; + trace("bruh"); + + + if (firstEvent != "") + { + trace(firstEventObject); + eventName.text = firstEventObject.name; + trace("bruh"); + eventType.selectedLabel = firstEventObject.type; + trace("bruh"); + eventValue.text = firstEventObject.value; + trace("bruh"); + currentSelectedEventName = firstEventObject.name; + trace("bruh"); + currentEventPosition = firstEventObject.position; + trace("bruh"); + eventPos.text = currentEventPosition + ""; + trace("bruh"); + } + + listOfEvents = new FlxUIDropDownMenu(10,20, FlxUIDropDownMenu.makeStrIdLabelArray(listofnames, true), function(name:String) + { + var event = containsName(listOfEvents.selectedLabel,_song.eventObjects); + + if (event == null) + return; + + trace('selecting ' + name + ' found: ' + event); + + eventName.text = event.name; + eventValue.text = event.value; + eventPos.text = event.position + ""; + eventType.selectedLabel = event.type; + currentSelectedEventName = event.name; + currentEventPosition = event.position; + }); + + eventValue.callback = function(string:String, string2:String) + { + trace(string + " - value"); + savedValue = string; + }; + + eventType.callback = function(type:String) + { + savedType = eventType.selectedLabel; + }; + + eventName.callback = function(string:String, string2:String) + { + var obj = containsName(currentSelectedEventName,_song.eventObjects); + if (obj == null) + { + currentSelectedEventName = string; + return; + } + obj = containsName(string,_song.eventObjects); + if (obj != null) + return; + obj = containsName(currentSelectedEventName,_song.eventObjects); + obj.name = string; + currentSelectedEventName = string; + }; + trace("bruh"); + + Typeables.push(eventPos); + Typeables.push(eventValue); + Typeables.push(eventName); + + var tab_events = new FlxUI(null, UI_options); + tab_events.name = "Events"; + tab_events.add(posLabel); + tab_events.add(valueLabel); + tab_events.add(nameLabel); + tab_events.add(listLabel); + tab_events.add(typeLabel); + tab_events.add(eventName); + tab_events.add(eventType); + tab_events.add(listOfEvents); + tab_events.add(eventValue); + tab_events.add(eventSave); + tab_events.add(eventAdd); + tab_events.add(eventRemove); + tab_events.add(eventPos); + tab_events.add(updatePos); + UI_options.addGroup(tab_events); + } + function addOptionsUI() { - stepperDiv = new FlxUINumericStepper(10, 26, 1, subDivisions, 1, 4); - stepperDiv.value = 0; - stepperDiv.name = 'divisions'; - - var stepperDivLabel = new FlxText(8, 10, 'Grid sub-divisions'); + var hitsounds = new FlxUICheckBox(10, 60, null, null, "Play hitsounds", 100); hitsounds.checked = false; @@ -280,12 +946,8 @@ class ChartingState extends MusicBeatState var tab_options = new FlxUI(null, UI_options); tab_options.name = "Options"; - tab_options.add(stepperDiv); - tab_options.add(stepperDivLabel); - tab_options.add(check_snap); tab_options.add(hitsounds); tab_options.add(check_mute_inst); - UI_options.addGroup(tab_options); } @@ -345,7 +1007,14 @@ class ChartingState extends MusicBeatState var stepperSpeedLabel = new FlxText(74,80,'Scroll Speed'); var stepperVocalVol:FlxUINumericStepper = new FlxUINumericStepper(10, 95, 0.1, 1, 0.1, 10, 1); + #if sys + if (!PlayState.isSM) + stepperVocalVol.value = vocals.volume; + else + stepperVocalVol.value = 1; + #else stepperVocalVol.value = vocals.volume; + #end stepperVocalVol.name = 'song_vocalvol'; var stepperVocalVolLabel = new FlxText(74, 95, 'Vocal Volume'); @@ -417,6 +1086,7 @@ class ChartingState extends MusicBeatState var noteStyleLabel = new FlxText(10,280,64,'Note Skin'); + var tab_group_song = new FlxUI(null, UI_box); tab_group_song.name = "Song"; tab_group_song.add(UI_songTitle); @@ -477,15 +1147,6 @@ class ChartingState extends MusicBeatState var tab_group_section = new FlxUI(null, UI_box); tab_group_section.name = 'Section'; - stepperLength = new FlxUINumericStepper(10, 10, 4, 0, 0, 999, 0); - stepperLength.value = _song.notes[curSection].lengthInSteps; - stepperLength.name = "section_length"; - - var stepperLengthLabel = new FlxText(74,10,'Section Length (in steps)'); - - stepperSectionBPM = new FlxUINumericStepper(10, 80, 1, Conductor.bpm, 0, 999, 0); - stepperSectionBPM.value = Conductor.bpm; - stepperSectionBPM.name = 'section_bpm'; var stepperCopy:FlxUINumericStepper = new FlxUINumericStepper(110, 132, 1, 1, -999, 999, 0); var stepperCopyLabel = new FlxText(174,132,'sections back'); @@ -499,33 +1160,69 @@ class ChartingState extends MusicBeatState var swapSection:FlxButton = new FlxButton(10, 170, "Swap Section", function() { - for (i in 0..._song.notes[curSection].sectionNotes.length) + + var sect = lastUpdatedSection; + + if (sect != null) + return; + + for (i in 0...sect.sectionNotes.length) { - var note = _song.notes[curSection].sectionNotes[i]; + var note = sect.sectionNotes[i]; note[1] = (note[1] + 4) % 8; - _song.notes[curSection].sectionNotes[i] = note; + sect.sectionNotes[i] = note; updateGrid(); } }); - check_mustHitSection = new FlxUICheckBox(10, 30, null, null, "Camera Points to P1?", 100); - check_mustHitSection.name = 'check_mustHit'; + check_mustHitSection = new FlxUICheckBox(10, 30, null, null, "Camera Points to P1?", 100,null,function() { + var sect = lastUpdatedSection; + + trace(sect); + + if (sect != null) + return; + + sect.mustHitSection = check_mustHitSection.checked; + + for (i in sectionRenderes) + { + if (i.section.startTime == sect.startTime) + { + var cachedY = i.icon.y; + remove(i.icon); + var sectionicon = check_mustHitSection.checked ? new HealthIcon(_song.player1).clone() : new HealthIcon(_song.player2).clone(); + sectionicon.x = -95; + sectionicon.y = cachedY; + sectionicon.setGraphicSize(0, 45); + + i.icon = sectionicon; + i.lastUpdated = sect.mustHitSection; + + add(sectionicon); + } + } + }); check_mustHitSection.checked = true; // _song.needsVoices = check_mustHit.checked; check_altAnim = new FlxUICheckBox(10, 340, null, null, "Alternate Animation", 100); check_altAnim.name = 'check_altAnim'; - check_changeBPM = new FlxUICheckBox(10, 60, null, null, 'Change BPM', 100); - check_changeBPM.name = 'check_changeBPM'; + var refresh = new FlxButton(10, 60, 'Refresh Section', function() { + var section = getSectionByTime(Conductor.songPosition); - tab_group_section.add(stepperLength); - tab_group_section.add(stepperLengthLabel); - tab_group_section.add(stepperSectionBPM); + if (section == null) + return; + + check_mustHitSection.checked = section.mustHitSection; + check_altAnim.checked = section.altAnim; + }); + + tab_group_section.add(refresh); tab_group_section.add(stepperCopy); tab_group_section.add(stepperCopyLabel); tab_group_section.add(check_mustHitSection); tab_group_section.add(check_altAnim); - tab_group_section.add(check_changeBPM); tab_group_section.add(copyButton); tab_group_section.add(clearSectionButton); tab_group_section.add(swapSection); @@ -545,7 +1242,7 @@ class ChartingState extends MusicBeatState writingNotesText = new FlxUIText(20,100, 0, ""); writingNotesText.setFormat("Arial",20,FlxColor.WHITE,FlxTextAlign.LEFT,FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); - stepperSusLength = new FlxUINumericStepper(10, 10, Conductor.stepCrochet / 2, 0, 0, Conductor.stepCrochet * _song.notes[curSection].lengthInSteps * 4); + stepperSusLength = new FlxUINumericStepper(10, 10, Conductor.stepCrochet / 2, 0, 0, Conductor.stepCrochet * 16 * 4); stepperSusLength.value = 0; stepperSusLength.name = 'note_susLength'; @@ -559,8 +1256,8 @@ class ChartingState extends MusicBeatState UI_box.addGroup(tab_group_note); - /*player2 = new Character(0,gridBG.y, _song.player2); - player1 = new Boyfriend(player2.width * 0.2,gridBG.y + player2.height, _song.player1); + /*player2 = new Character(0,0, _song.player2); + player1 = new Boyfriend(player2.width * 0.2,0 + player2.height, _song.player1); player1.y = player1.y - player1.height; @@ -571,6 +1268,8 @@ class ChartingState extends MusicBeatState UI_box.add(player2);*/ } + + function loadSong(daSong:String):Void { @@ -579,23 +1278,45 @@ class ChartingState extends MusicBeatState FlxG.sound.music.stop(); // vocals.stop(); } - + #if sys + if (PlayState.isSM) + { + trace("Loading " + PlayState.pathToSm + "/" + PlayState.sm.header.MUSIC); + var bytes = File.getBytes(PlayState.pathToSm + "/" + PlayState.sm.header.MUSIC); + var sound = new Sound(); + sound.loadCompressedDataFromByteArray(bytes.getData(), bytes.length); + FlxG.sound.playMusic(sound); + } + else + FlxG.sound.playMusic(Paths.inst(daSong), 0.6); + #else FlxG.sound.playMusic(Paths.inst(daSong), 0.6); + #end // WONT WORK FOR TUTORIAL OR TEST SONG!!! REDO LATER + #if sys + if (PlayState.isSM) + vocals = null; + else + vocals = new FlxSound().loadEmbedded(Paths.voices(daSong)); + #else vocals = new FlxSound().loadEmbedded(Paths.voices(daSong)); + #end FlxG.sound.list.add(vocals); FlxG.sound.music.pause(); - vocals.pause(); + if (!PlayState.isSM) + vocals.pause(); FlxG.sound.music.onComplete = function() { - vocals.pause(); - vocals.time = 0; + if (!PlayState.isSM) + { + vocals.pause(); + vocals.time = 0; + } FlxG.sound.music.pause(); FlxG.sound.music.time = 0; - changeSection(); }; } @@ -626,13 +1347,8 @@ class ChartingState extends MusicBeatState var label = check.getLabel().text; switch (label) { - case 'Camera Points to P1?': - _song.notes[curSection].mustHitSection = check.checked; - case 'Change BPM': - _song.notes[curSection].changeBPM = check.checked; - FlxG.log.add('changed bpm shit'); case "Alternate Animation": - _song.notes[curSection].altAnim = check.checked; + getSectionByTime(Conductor.songPosition).altAnim = check.checked; } } else if (id == FlxUINumericStepper.CHANGE_EVENT && (sender is FlxUINumericStepper)) @@ -646,7 +1362,7 @@ class ChartingState extends MusicBeatState case 'section_length': if (nums.value <= 4) nums.value = 4; - _song.notes[curSection].lengthInSteps = Std.int(nums.value); + getSectionByTime(Conductor.songPosition).lengthInSteps = Std.int(nums.value); updateGrid(); case 'song_speed': @@ -673,12 +1389,13 @@ class ChartingState extends MusicBeatState case 'section_bpm': if (nums.value <= 0.1) nums.value = 0.1; - _song.notes[curSection].bpm = Std.int(nums.value); + getSectionByTime(Conductor.songPosition).bpm = Std.int(nums.value); updateGrid(); case 'song_vocalvol': if (nums.value <= 0.1) nums.value = 0.1; + if (!PlayState.isSM) vocals.volume = nums.value; case 'song_instvol': @@ -700,27 +1417,27 @@ class ChartingState extends MusicBeatState /* this function got owned LOL function lengthBpmBullshit():Float { - if (_song.notes[curSection].changeBPM) - return _song.notes[curSection].lengthInSteps * (_song.notes[curSection].bpm / _song.bpm); + if (getSectionByTime(Conductor.songPosition).changeBPM) + return getSectionByTime(Conductor.songPosition).lengthInSteps * (getSectionByTime(Conductor.songPosition).bpm / _song.bpm); else - return _song.notes[curSection].lengthInSteps; + return getSectionByTime(Conductor.songPosition).lengthInSteps; }*/ + + function stepStartTime(step):Float { - return _song.bpm / (step / 4) / 60; + return Conductor.bpm / (step / 4) / 60; } - function sectionStartTime():Float + function sectionStartTime(?customIndex:Int = -1):Float { - var daBPM:Float = _song.bpm; + if (customIndex == -1) + customIndex = curSection; + var daBPM:Float = Conductor.bpm; var daPos:Float = 0; - for (i in 0...curSection) + for (i in 0...customIndex) { - if (_song.notes[i].changeBPM) - { - daBPM = _song.notes[i].bpm; - } daPos += 4 * (1000 * 60 / daBPM); } return daPos; @@ -731,22 +1448,167 @@ class ChartingState extends MusicBeatState public var diff:Float = 0; + public var changeIndex = 0; + + public var currentBPM:Float = 0; + public var lastBPM:Float = 0; + + public var updateFrame = 0; + public var lastUpdatedSection:SwagSection = null; + + public function resizeEverything() + { + curRenderedNotes.forEach(function(note) { + var seg = TimingStruct.getTimingAtTimestamp(note.strumTime); + note.y = getYfromStrum(note.strumTime) * zoomFactor; + var stepCrochet = (((60 / seg.bpm) * 1000) / 4); + if (note.sustainLength >= 2) + { + note.noteCharterObject.y = note.y + GRID_SIZE; + note.noteCharterObject.makeGraphic(8,Math.floor((getYfromStrum(note.strumTime + note.sustainLength) * zoomFactor) - note.y),FlxColor.WHITE); + } + }); + + regenerateLines(); + } + + + override function update(elapsed:Float) { updateHeads(); - //snapText.text = "Snap: 1/" + snap + " (" + (doSnapShit ? "Shift to disable" : "Snap Disabled, Shift to renable. It's a bit buggy") + ")\nAdd Notes: 1-8 (or click)"; + var doInput = true; - curStep = recalculateSteps(); + for (i in Typeables) + { + if (i.hasFocus) + doInput = false; + } - /*if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.RIGHT) + if (doInput) + { + if (FlxG.mouse.wheel != 0) + { + FlxG.sound.music.pause(); + + if (!PlayState.isSM) + vocals.pause(); + claps.splice(0, claps.length); + + + if (FlxG.keys.pressed.CONTROL) + { + var amount = FlxG.mouse.wheel; + + if(amount > 0) + amount = 0; + + var increase:Float = 0; + + if (amount < 0) + increase = -0.04; + else + increase = 0.04; + + + zoomFactor += increase; + + if (zoomFactor > 2) + zoomFactor = 2; + + if (zoomFactor < 0.1) + zoomFactor = 0.1; + + resizeEverything(); + } + else + { + var amount = FlxG.mouse.wheel; + + if(amount > 0 && strumLine.y < 0) + amount = 0; + + if (doSnapShit) + { + var increase:Float = 0; + var beats:Float = 0; + + if (amount < 0) + { + increase = 1 / deezNuts.get(snap); + beats = (Math.floor((curDecimalBeat * deezNuts.get(snap)) + 0.001) / deezNuts.get(snap)) + increase; + } + else + { + increase = -1 / deezNuts.get(snap); + beats = ((Math.ceil(curDecimalBeat * deezNuts.get(snap)) - 0.001) / deezNuts.get(snap)) + increase; + } + + trace("SNAP - " + snap + " INCREASE - " + increase + " - GO TO BEAT " + beats); + + var data = TimingStruct.getTimingAtBeat(beats); + + var bpm = data != null ? data.bpm : _song.bpm; + + if (data != null) + { + + FlxG.sound.music.time = (data.startTime + ((beats - data.startBeat) / (bpm/60)) ) * 1000; + } + } + if (!PlayState.isSM) + vocals.time = FlxG.sound.music.time; + } + } + } + + 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++; + } + } + + recalculateAllSectionTimes(); + + regenerateLines(); + updateFrame++; + } + else if (updateFrame != 5) + updateFrame++; + + snapText.text = "Snap: 1/" + snap + " (" + (doSnapShit ? "Shift to disable, Left or Right to increase/decrease" : "Snap Disabled, Shift to renable.") + ")\nAdd Notes: 1-8 (or click)\nZoom: " + zoomFactor; + + + if (FlxG.keys.justPressed.RIGHT) snap = snap * 2; - if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.LEFT) + if (FlxG.keys.justPressed.LEFT) snap = Math.round(snap / 2); - if (snap >= 192) - snap = 192; - if (snap <= 1) - snap = 1;*/ + if (snap >= 64) + snap = 64; + if (snap <= 4) + snap = 4; /* if (FlxG.keys.justPressed.SHIFT) doSnapShit = !doSnapShit; @@ -758,11 +1620,66 @@ class ChartingState extends MusicBeatState doSnapShit = !defaultSnap; } + check_snap.checked = doSnapShit; Conductor.songPosition = FlxG.sound.music.time; _song.song = typingShit.text; + + var timingSeg = TimingStruct.getTimingAtTimestamp(Conductor.songPosition); + + var start = Conductor.songPosition; + + if (timingSeg != null) + { + var timingSegBpm = timingSeg.bpm; + currentBPM = timingSegBpm; + + if (currentBPM != Conductor.bpm) + { + trace("BPM CHANGE to " + currentBPM); + Conductor.changeBPM(currentBPM, false); + } + + var pog:Float = (curDecimalBeat - timingSeg.startBeat) / (Conductor.bpm / 60); + + start = (timingSeg.startTime + pog) * 1000; + } + + + var weird = getSectionByTime(start, true); + + FlxG.watch.addQuick("Section",weird); + + if (weird != null) + { + if (lastUpdatedSection != getSectionByTime(start,true)) + { + lastUpdatedSection = weird; + check_mustHitSection.checked = weird.mustHitSection; + check_altAnim.checked = weird.altAnim; + } + } + + + strumLine.y = getYfromStrum(start) * zoomFactor; + camFollow.y = strumLine.y; + + + bpmTxt.text = Std.string(FlxMath.roundDecimal(Conductor.songPosition / 1000, 2)) + + " / " + + Std.string(FlxMath.roundDecimal(FlxG.sound.music.length / 1000, 2)) + + "\nCur Section: " + + curSection + + "\nCurBPM: " + + currentBPM + + "\nCurBeat: " + + HelperFunctions.truncateFloat(curDecimalBeat,3) + + "\nZoom: " + + zoomFactor; + + var left = FlxG.keys.justPressed.ONE; var down = FlxG.keys.justPressed.TWO; var up = FlxG.keys.justPressed.THREE; @@ -774,6 +1691,8 @@ class ChartingState extends MusicBeatState var pressArray = [left, down, up, right, leftO, downO, upO, rightO]; var delete = false; + if (doInput) + { curRenderedNotes.forEach(function(note:Note) { if (strumLine.overlaps(note) && pressArray[Math.floor(Math.abs(note.noteData))]) @@ -791,10 +1710,7 @@ class ChartingState extends MusicBeatState addNote(new Note(Conductor.songPosition,p)); } } - - strumLine.y = getYfromStrum((Conductor.songPosition - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps)); - camFollow.y = strumLine.y; - + } if (playClaps) { @@ -802,21 +1718,21 @@ class ChartingState extends MusicBeatState { if (FlxG.sound.music.playing) { - FlxG.overlap(strumLine, note, function(_, _) + if (strumLine.overlaps(note)) { if(!claps.contains(note)) { claps.push(note); FlxG.sound.play(Paths.sound('SNAP')); } - }); + } } }); } /*curRenderedNotes.forEach(function(note:Note) { if (strumLine.overlaps(note) && strumLine.y == note.y) // yandere dev type shit { - if (_song.notes[curSection].mustHitSection) + if (getSectionByTime(Conductor.songPosition).mustHitSection) { trace('must hit ' + Math.abs(note.noteData)); if (note.noteData < 4) @@ -883,23 +1799,10 @@ class ChartingState extends MusicBeatState } });*/ - if (curBeat % 4 == 0 && curStep >= 16 * (curSection + 1)) - { - trace(curStep); - trace((_song.notes[curSection].lengthInSteps) * (curSection + 1)); - trace('DUMBSHIT'); - if (_song.notes[curSection + 1] == null) - { - addSection(); - } - - changeSection(curSection + 1, false); - } - - FlxG.watch.addQuick('daBeat', curBeat); - FlxG.watch.addQuick('daStep', curStep); + FlxG.watch.addQuick('daBeat', curDecimalBeat); + if (FlxG.mouse.justPressed) { if (FlxG.mouse.overlaps(curRenderedNotes)) @@ -921,10 +1824,10 @@ class ChartingState extends MusicBeatState } else { - if (FlxG.mouse.x > gridBG.x - && FlxG.mouse.x < gridBG.x + gridBG.width - && FlxG.mouse.y > gridBG.y - && FlxG.mouse.y < gridBG.y + (GRID_SIZE * _song.notes[curSection].lengthInSteps)) + if (FlxG.mouse.x > 0 + && FlxG.mouse.x < 0 + gridBG.width + && FlxG.mouse.y > 0 + && FlxG.mouse.y < 0 + height) { FlxG.log.add('added note'); addNote(); @@ -932,44 +1835,42 @@ class ChartingState extends MusicBeatState } } - if (FlxG.mouse.x > gridBG.x - && FlxG.mouse.x < gridBG.x + gridBG.width - && FlxG.mouse.y > gridBG.y - && FlxG.mouse.y < gridBG.y + (GRID_SIZE * _song.notes[curSection].lengthInSteps)) + if (FlxG.mouse.x > 0 + && FlxG.mouse.x < gridBG.width + && FlxG.mouse.y > 0 + && FlxG.mouse.y < height) { dummyArrow.visible = true; dummyArrow.x = Math.floor(FlxG.mouse.x / GRID_SIZE) * GRID_SIZE; - var div_by:Float = GRID_SIZE / subDivisions; - - if (doSnapShit) - dummyArrow.y = Math.floor(FlxG.mouse.y / div_by) * div_by; - else - dummyArrow.y = FlxG.mouse.y; + dummyArrow.y = (Math.floor(FlxG.mouse.y / deezNuts.get(snap)) * deezNuts.get(snap)); } else { dummyArrow.visible = false; } + if (doInput) + { if (FlxG.keys.justPressed.ENTER) { lastSection = curSection; PlayState.SONG = _song; FlxG.sound.music.stop(); + if (!PlayState.isSM) vocals.stop(); LoadingState.loadAndSwitchState(new PlayState()); } if (FlxG.keys.justPressed.E) { - changeNoteSustain(Conductor.stepCrochet); + changeNoteSustain(((60 / (timingSeg != null ? timingSeg.bpm : _song.bpm)) * 1000) / 4); } if (FlxG.keys.justPressed.Q) { - changeNoteSustain(-Conductor.stepCrochet); + changeNoteSustain(-(((60 / (timingSeg != null ? timingSeg.bpm : _song.bpm)) * 1000) / 4)); } if (FlxG.keys.justPressed.TAB) @@ -1006,23 +1907,18 @@ class ChartingState extends MusicBeatState var shiftThing:Int = 1; if (FlxG.keys.pressed.SHIFT) shiftThing = 4; - if (!FlxG.keys.pressed.CONTROL) - { - if (FlxG.keys.justPressed.RIGHT || FlxG.keys.justPressed.D) - changeSection(curSection + shiftThing); - if (FlxG.keys.justPressed.LEFT || FlxG.keys.justPressed.A) - changeSection(curSection - shiftThing); - } if (FlxG.keys.justPressed.SPACE) { if (FlxG.sound.music.playing) { FlxG.sound.music.pause(); + if (!PlayState.isSM) vocals.pause(); claps.splice(0, claps.length); } else { + if (!PlayState.isSM) vocals.play(); FlxG.sound.music.play(); } @@ -1037,48 +1933,15 @@ class ChartingState extends MusicBeatState } - if (FlxG.sound.music.time < 0 || curStep < 0) + if (FlxG.sound.music.time < 0 || curDecimalBeat < 0) FlxG.sound.music.time = 0; - if (FlxG.mouse.wheel != 0) - { - FlxG.sound.music.pause(); - vocals.pause(); - claps.splice(0, claps.length); - - var amount = FlxG.mouse.wheel; - - if(amount > 0 && strumLine.y < gridBG.y) - amount = 0; - - if (doSnapShit) - { - var increase:Int = 0; - - if (amount < 0) - increase = 1; - else - increase = -1; - - trace(increase + " - " + curStep + " - " + (curStep + increase)); - - // *Maybe a pre-snap goes here but I don't really know, I don't chart with number keys - FlxG.sound.music.time += (increase * Conductor.stepCrochet) / subDivisions; - - var msStep = FlxG.sound.music.time / Conductor.stepCrochet; - - curStep = Std.int(msStep); - } - else - FlxG.sound.music.time -= (amount * Conductor.stepCrochet * 0.4); - vocals.time = FlxG.sound.music.time; - } - if (!FlxG.keys.pressed.SHIFT) { if (FlxG.keys.pressed.W || FlxG.keys.pressed.S) { FlxG.sound.music.pause(); + if (!PlayState.isSM) vocals.pause(); claps.splice(0, claps.length); @@ -1091,6 +1954,7 @@ class ChartingState extends MusicBeatState else FlxG.sound.music.time += daTime; + if (!PlayState.isSM) vocals.time = FlxG.sound.music.time; } } @@ -1099,6 +1963,7 @@ class ChartingState extends MusicBeatState if (FlxG.keys.justPressed.W || FlxG.keys.justPressed.S) { FlxG.sound.music.pause(); + if (!PlayState.isSM) vocals.pause(); var daTime:Float = Conductor.stepCrochet * 2; @@ -1110,25 +1975,18 @@ class ChartingState extends MusicBeatState else FlxG.sound.music.time += daTime; + if (!PlayState.isSM) vocals.time = FlxG.sound.music.time; } } } - + } _song.bpm = tempBpm; /* if (FlxG.keys.justPressed.UP) Conductor.changeBPM(Conductor.bpm + 1); if (FlxG.keys.justPressed.DOWN) Conductor.changeBPM(Conductor.bpm - 1); */ - - bpmTxt.text = bpmTxt.text = Std.string(FlxMath.roundDecimal(Conductor.songPosition / 1000, 2)) - + " / " - + Std.string(FlxMath.roundDecimal(FlxG.sound.music.length / 1000, 2)) - + "\nSection: " - + curSection - + "\nCurStep: " - + curStep; super.update(elapsed); } @@ -1147,58 +2005,21 @@ class ChartingState extends MusicBeatState updateGrid(); } - override function beatHit() - { - trace('beat'); - - super.beatHit(); - if (!player2.animation.curAnim.name.startsWith("sing")) - { - player2.playAnim('idle'); - } - player1.dance(); - } - - function recalculateSteps():Int - { - var lastChange:BPMChangeEvent = { - stepTime: 0, - songTime: 0, - bpm: 0 - } - for (i in 0...Conductor.bpmChangeMap.length) - { - if (FlxG.sound.music.time > Conductor.bpmChangeMap[i].songTime) - lastChange = Conductor.bpmChangeMap[i]; - } - - curStep = lastChange.stepTime + Math.floor((FlxG.sound.music.time - lastChange.songTime) / Conductor.stepCrochet); - updateBeat(); - - return curStep; - } - function resetSection(songBeginning:Bool = false):Void { - updateGrid(); - FlxG.sound.music.pause(); + if (!PlayState.isSM) vocals.pause(); // Basically old shit from changeSection??? - FlxG.sound.music.time = sectionStartTime(); - - if (songBeginning) - { - FlxG.sound.music.time = 0; - curSection = 0; - } + FlxG.sound.music.time = 0; + if (!PlayState.isSM) vocals.time = FlxG.sound.music.time; - updateCurStep(); updateGrid(); - updateSectionUI(); + if (!songBeginning) + updateSectionUI(); } function changeSection(sec:Int = 0, ?updateMusic:Bool = true):Void @@ -1215,6 +2036,7 @@ class ChartingState extends MusicBeatState if (updateMusic) { FlxG.sound.music.pause(); + if (!PlayState.isSM) vocals.pause(); /*var daNum:Int = 0; @@ -1226,6 +2048,7 @@ class ChartingState extends MusicBeatState }*/ FlxG.sound.music.time = sectionStartTime(); + if (!PlayState.isSM) vocals.time = FlxG.sound.music.time; updateCurStep(); } @@ -1240,13 +2063,17 @@ class ChartingState extends MusicBeatState function copySection(?sectionNum:Int = 1) { var daSec = FlxMath.maxInt(curSection, sectionNum); + var sect = lastUpdatedSection; + + if (sect != null) + return; for (note in _song.notes[daSec - sectionNum].sectionNotes) { var strum = note[0] + Conductor.stepCrochet * (_song.notes[daSec].lengthInSteps * sectionNum); var copiedNote:Array = [strum, note[1], note[2]]; - _song.notes[daSec].sectionNotes.push(copiedNote); + sect.sectionNotes.push(copiedNote); } updateGrid(); @@ -1254,13 +2081,19 @@ class ChartingState extends MusicBeatState function updateSectionUI():Void { - var sec = _song.notes[curSection]; + var sec = getSectionByTime(Conductor.songPosition); - stepperLength.value = sec.lengthInSteps; - check_mustHitSection.checked = sec.mustHitSection; - check_altAnim.checked = sec.altAnim; - check_changeBPM.checked = sec.changeBPM; - stepperSectionBPM.value = sec.bpm; + if (sec == null) + { + check_mustHitSection.checked = true; + check_altAnim.checked = false; + } + else + { + check_mustHitSection.checked = sec.mustHitSection; + check_altAnim.checked = sec.altAnim; + check_changeBPM.checked = sec.changeBPM; + } } function updateHeads():Void @@ -1285,12 +2118,6 @@ class ChartingState extends MusicBeatState function updateGrid():Void { - addGrid(subDivisions); - - remove(gridBlackLine); - gridBlackLine = new FlxSprite(gridBG.x + gridBG.width / 2).makeGraphic(2, Std.int(gridBG.height), FlxColor.BLACK); - add(gridBlackLine); - while (curRenderedNotes.members.length > 0) { curRenderedNotes.remove(curRenderedNotes.members[0], true); @@ -1301,23 +2128,6 @@ class ChartingState extends MusicBeatState curRenderedSustains.remove(curRenderedSustains.members[0], true); } - var sectionInfo:Array = _song.notes[curSection].sectionNotes; - - if (_song.notes[curSection].changeBPM && _song.notes[curSection].bpm > 0) - { - Conductor.changeBPM(_song.notes[curSection].bpm); - FlxG.log.add('CHANGED BPM!'); - } - else - { - // get last bpm - var daBPM:Float = _song.bpm; - for (i in 0...curSection) - if (_song.notes[i].changeBPM) - daBPM = _song.notes[i].bpm; - Conductor.changeBPM(daBPM); - } - /* // PORT BULLSHIT, INCASE THERE'S NO SUSTAIN DATA FOR A NOTE for (sec in 0..._song.notes.length) { @@ -1332,39 +2142,69 @@ class ChartingState extends MusicBeatState } */ - for (i in sectionInfo) + var currentSection = 0; + + for (section in _song.notes) { - var daNoteInfo = i[1]; - var daStrumTime = i[0]; - var daSus = i[2]; - - var note:Note = new Note(daStrumTime, daNoteInfo % 4,null,false,true); - note.rawNoteData = daNoteInfo; - note.sustainLength = daSus; - note.setGraphicSize(GRID_SIZE, GRID_SIZE); - note.updateHitbox(); - note.x = Math.floor(daNoteInfo * GRID_SIZE); - note.y = Math.floor(getYfromStrum((daStrumTime - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps))); - - if (curSelectedNote != null) - if (curSelectedNote[0] == note.strumTime) - lastNote = note; - - curRenderedNotes.add(note); - - if (daSus > 0) + for (i in section.sectionNotes) { - var sustainVis:FlxSprite = new FlxSprite(note.x + (GRID_SIZE / 2), - note.y + GRID_SIZE).makeGraphic(8, Math.floor(FlxMath.remapToRange(daSus, 0, Conductor.stepCrochet * _song.notes[curSection].lengthInSteps, 0, gridBG.height))); - curRenderedSustains.add(sustainVis); + var seg = TimingStruct.getTimingAtTimestamp(i[0]); + var daNoteInfo = i[1]; + var daStrumTime = i[0]; + var daSus = i[2]; + + var note:Note = new Note(daStrumTime, daNoteInfo % 4,null,false,true); + note.rawNoteData = daNoteInfo; + note.sustainLength = daSus; + note.setGraphicSize(Math.floor(GRID_SIZE), Math.floor(GRID_SIZE)); + note.updateHitbox(); + note.x = Math.floor(daNoteInfo * GRID_SIZE); + + note.y = Math.floor(getYfromStrum(daStrumTime) * zoomFactor); + + if (curSelectedNote != null) + if (curSelectedNote[0] == note.strumTime) + lastNote = note; + + curRenderedNotes.add(note); + + var stepCrochet = (((60 / seg.bpm) * 1000) / 4); + + if (daSus > 0) + { + var sustainVis:FlxSprite = new FlxSprite(note.x + (GRID_SIZE / 2), + note.y + GRID_SIZE).makeGraphic(8, Math.floor((getYfromStrum(daStrumTime + daSus) - note.y) * zoomFactor)); + + note.noteCharterObject = sustainVis; + + curRenderedSustains.add(sustainVis); + } } + currentSection++; } } private function addSection(lengthInSteps:Int = 16):Void { + var daPos:Float = 0; + var start:Float = 0; + + var bpm = _song.bpm; + for (i in 0...curSection) + { + for(ii in TimingStruct.AllTimings) + { + var data = TimingStruct.getTimingAtTimestamp(start); + if ((data != null ? data.bpm : _song.bpm) != bpm && bpm != ii.bpm) + bpm = ii.bpm; + } + start += (4 * (60 / bpm)) * 1000; + } + var sec:SwagSection = { + startTime: daPos, + endTime: Math.POSITIVE_INFINITY, lengthInSteps: lengthInSteps, bpm: _song.bpm, changeBPM: false, @@ -1381,11 +2221,11 @@ class ChartingState extends MusicBeatState { var swagNum:Int = 0; - for (i in _song.notes[curSection].sectionNotes) + for (i in getSectionByTime(note.strumTime).sectionNotes) { if (i[0] == note.strumTime && i[1] == note.rawNoteData) { - curSelectedNote = _song.notes[curSection].sectionNotes[swagNum]; + curSelectedNote = getSectionByTime(note.strumTime).sectionNotes[swagNum]; } swagNum += 1; @@ -1399,20 +2239,40 @@ class ChartingState extends MusicBeatState function deleteNote(note:Note):Void { lastNote = note; - for (i in _song.notes[curSection].sectionNotes) + + var section = getSectionByTime(note.strumTime); + + trace(section); + + var found = false; + + for (i in section.sectionNotes) { if (i[0] == note.strumTime && i[1] == note.rawNoteData) { - _song.notes[curSection].sectionNotes.remove(i); + section.sectionNotes.remove(i); + found = true; + } + } + + if (!found) // backup check + { + for(i in _song.notes) + { + for (n in i.sectionNotes) + if (n[0] == note.strumTime && n[1] == note.rawNoteData) + i.sectionNotes.remove(n); } } + trace("DELETED!"); + updateGrid(); } function clearSection():Void { - _song.notes[curSection].sectionNotes = []; + getSectionByTime(Conductor.songPosition).sectionNotes = []; updateGrid(); } @@ -1429,7 +2289,26 @@ class ChartingState extends MusicBeatState private function newSection(lengthInSteps:Int = 16,mustHitSection:Bool = false,altAnim:Bool = true):SwagSection { + + var daPos:Float = 0; + + var currentSeg = TimingStruct.AllTimings[TimingStruct.AllTimings.length - 1]; + + var currentBeat = 4; + + for(i in _song.notes) + currentBeat += 4; + + if (currentSeg == null) + return null; + + var start:Float = (currentBeat - currentSeg.startBeat) / (currentSeg.bpm / 60); + + daPos = (currentSeg.startTime + start) * 1000; + var sec:SwagSection = { + startTime: daPos, + endTime: Math.POSITIVE_INFINITY, lengthInSteps: lengthInSteps, bpm: _song.bpm, changeBPM: false, @@ -1439,15 +2318,67 @@ class ChartingState extends MusicBeatState altAnim: altAnim }; + return sec; } + function recalculateAllSectionTimes() + { + + /*if (TimingStruct.AllTimings.length > 0) + { + trace("Song length in MS: " + FlxG.sound.music.length); + + for(i in 0...9000000) // REALLY HIGH BEATS just cuz like ig this is the upper limit, I mean ur chart is probably going to run like ass anyways + { + var seg = TimingStruct.getTimingAtBeat(i); + + var time = (i / (seg.bpm / 60)) * 1000; + + if (time > FlxG.sound.music.length) + break; + + lengthInBeats = i; + } + + lengthInSteps = lengthInBeats * 4; + + trace('LENGTH IN STEPS ' + lengthInSteps + ' | LENGTH IN BEATS ' + lengthInBeats); + }*/ + + trace("RECALCULATING SECTION TIMES"); + for (i in 0..._song.notes.length) // loops through sections + { + var section = _song.notes[i]; + + var currentBeat = 4 * i; + + var currentSeg = TimingStruct.getTimingAtBeat(currentBeat); + + if (currentSeg == null) + return; + + var start:Float = (currentBeat - currentSeg.startBeat) / (currentSeg.bpm / 60); + + section.startTime = (currentSeg.startTime + start) * 1000; + + if (i != 0) + _song.notes[i - 1].endTime = section.startTime; + section.endTime = Math.POSITIVE_INFINITY; + + } + once = true; + } + + var once = false; + + function shiftNotes(measure:Int=0,step:Int=0,ms:Int = 0):Void { var newSong = []; - var millisecadd = (((measure*4)+step/4)*(60000/_song.bpm))+ms; - var totaladdsection = Std.int((millisecadd/(60000/_song.bpm)/4)); + var millisecadd = (((measure*4)+step/4)*(60000/currentBPM))+ms; + var totaladdsection = Std.int((millisecadd/(60000/currentBPM)/4)); trace(millisecadd,totaladdsection); if(millisecadd > 0) { @@ -1475,7 +2406,7 @@ class ChartingState extends MusicBeatState { newtiming = 0; } - var futureSection = Math.floor(newtiming/4/(60000/_song.bpm)); + var futureSection = Math.floor(newtiming/4/(60000/currentBPM)); _song.notes[daSection].sectionNotes[daNote][0] = newtiming; newSong[futureSection].sectionNotes.push(_song.notes[daSection].sectionNotes[daNote]); @@ -1485,22 +2416,68 @@ class ChartingState extends MusicBeatState } //trace("DONE BITCH"); _song.notes = newSong; + recalculateAllSectionTimes(); updateGrid(); updateSectionUI(); updateNoteUI(); } + + public function getSectionByTime(ms:Float, ?changeCurSectionIndex:Bool = false):SwagSection + { + var index = 0; + + + + for (i in _song.notes) + { + if (ms >= i.startTime && ms < i.endTime) + { + if (changeCurSectionIndex) + curSection = index; + return i; + } + index++; + } + + + return null; + } + + public function getNoteByTime(ms:Float) + { + for(i in _song.notes) + { + for(n in i.sectionNotes) + if (n[0] == ms) + return i; + } + return null; + } + + private function addNote(?n:Note):Void { - var noteStrum = getStrumTime(dummyArrow.y) + sectionStartTime(); + var strum = getStrumTime(dummyArrow.y) / zoomFactor; + + trace(strum + " from " + dummyArrow.y); + + trace("adding note with " + strum + " from dummyArrow"); + + var section = getSectionByTime(strum); + + if (section == null) + return; + + var noteStrum = strum; var noteData = Math.floor(FlxG.mouse.x / GRID_SIZE); var noteSus = 0; if (n != null) - _song.notes[curSection].sectionNotes.push([n.strumTime, n.noteData, n.sustainLength]); + section.sectionNotes.push([n.strumTime, n.noteData, n.sustainLength]); else - _song.notes[curSection].sectionNotes.push([noteStrum, noteData, noteSus]); + section.sectionNotes.push([noteStrum, noteData, noteSus]); - var thingy = _song.notes[curSection].sectionNotes[_song.notes[curSection].sectionNotes.length - 1]; + var thingy = section.sectionNotes[section.sectionNotes.length - 1]; curSelectedNote = thingy; @@ -1512,12 +2489,12 @@ class ChartingState extends MusicBeatState function getStrumTime(yPos:Float):Float { - return FlxMath.remapToRange(yPos, gridBG.y, gridBG.y + gridBG.height, 0, 16 * Conductor.stepCrochet); + return FlxMath.remapToRange(yPos, 0, lengthInSteps, 0, lengthInSteps); } function getYfromStrum(strumTime:Float):Float { - return FlxMath.remapToRange(strumTime, 0, 16 * Conductor.stepCrochet, gridBG.y, gridBG.y + gridBG.height); + return FlxMath.remapToRange(strumTime, 0, lengthInSteps, 0, lengthInSteps); } /* @@ -1611,7 +2588,7 @@ class ChartingState extends MusicBeatState /** * Called when the save file dialog is cancelled. - */ + */ function onSaveCancel(_):Void { _file.removeEventListener(Event.COMPLETE, onSaveComplete); diff --git a/source/Conductor.hx b/source/Conductor.hx index 4560078..f5c40c1 100644 --- a/source/Conductor.hx +++ b/source/Conductor.hx @@ -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 = []; 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); } } \ No newline at end of file diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index 123e240..12ce62a 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -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 = 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); /* @@ -315,6 +354,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()); } } @@ -328,6 +379,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) { @@ -353,6 +405,7 @@ class FreeplayState extends MusicBeatState FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); + curSelected += change; if (curSelected < 0) @@ -379,7 +432,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; @@ -428,12 +491,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 } diff --git a/source/HealthIcon.hx b/source/HealthIcon.hx index 74f46a1..5a9b044 100644 --- a/source/HealthIcon.hx +++ b/source/HealthIcon.hx @@ -12,10 +12,16 @@ class HealthIcon extends FlxSprite public function new(char:String = 'bf', isPlayer:Bool = false) { super(); - - loadGraphic(Paths.image('iconGrid'), true, 150, 150); 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); diff --git a/source/HelperFunctions.hx b/source/HelperFunctions.hx index b17dc6a..4b704c1 100644 --- a/source/HelperFunctions.hx +++ b/source/HelperFunctions.hx @@ -12,4 +12,5 @@ class HelperFunctions public static function GCD(a, b) { return b == 0 ? FlxMath.absInt(a) : GCD(b, a % b); } + } \ No newline at end of file diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index ab5f444..452ce07 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -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; diff --git a/source/MusicBeatState.hx b/source/MusicBeatState.hx index 9deb2bf..7a3bde8 100644 --- a/source/MusicBeatState.hx +++ b/source/MusicBeatState.hx @@ -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) diff --git a/source/Note.hx b/source/Note.hx index 472dbd2..82d6a6d 100644 --- a/source/Note.hx +++ b/source/Note.hx @@ -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; diff --git a/source/OFLWaveform.hx b/source/OFLWaveform.hx new file mode 100644 index 0000000..46d1512 --- /dev/null +++ b/source/OFLWaveform.hx @@ -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(); + } +} \ No newline at end of file diff --git a/source/OutdatedSubState.hx b/source/OutdatedSubState.hx index f7015c4..3c7487e 100644 --- a/source/OutdatedSubState.hx +++ b/source/OutdatedSubState.hx @@ -51,6 +51,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; @@ -84,10 +91,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; diff --git a/source/PauseSubState.hx b/source/PauseSubState.hx index 0d78ca9..3b406a6 100644 --- a/source/PauseSubState.hx +++ b/source/PauseSubState.hx @@ -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); diff --git a/source/PlayState.hx b/source/PlayState.hx index 969568b..6bf6c36 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -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; @@ -112,6 +118,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; @@ -169,6 +181,8 @@ class PlayState extends MusicBeatState public static var offsetTesting:Bool = false; + public var isSMFile:Bool = false; + var notesHitArray:Array = []; var currentFrames:Int = 0; @@ -257,6 +271,8 @@ class PlayState extends MusicBeatState override public function create() { + + FlxG.mouse.visible = false; instance = this; if (FlxG.save.data.fpsCap > 290) @@ -372,6 +388,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 = []; + + 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); @@ -1604,7 +1661,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; @@ -1689,10 +1759,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'); @@ -1721,6 +1798,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)) { @@ -2071,12 +2153,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; @@ -2528,6 +2675,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); @@ -4164,11 +4314,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); diff --git a/source/Section.hx b/source/Section.hx index c1af6ac..fcb574a 100644 --- a/source/Section.hx +++ b/source/Section.hx @@ -2,6 +2,8 @@ package; typedef SwagSection = { + var startTime:Float; + var endTime:Float; var sectionNotes:Array>; 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> = []; public var lengthInSteps:Int = 16; diff --git a/source/SectionRender.hx b/source/SectionRender.hx new file mode 100644 index 0000000..3410ccb --- /dev/null +++ b/source/SectionRender.hx @@ -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) + { + } +} \ No newline at end of file diff --git a/source/Song.hx b/source/Song.hx index 5329079..abbec7f 100644 --- a/source/Song.hx +++ b/source/Song.hx @@ -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; + var eventObjects:Array; 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; public var bpm:Float; public var needsVoices:Bool = true; + public var eventObjects:Array; 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) { diff --git a/source/TimingStruct.hx b/source/TimingStruct.hx new file mode 100644 index 0000000..82128a3 --- /dev/null +++ b/source/TimingStruct.hx @@ -0,0 +1,55 @@ +import flixel.FlxG; + +class TimingStruct +{ + public static var AllTimings:Array = []; + + 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; + } +} \ No newline at end of file diff --git a/source/TitleState.hx b/source/TitleState.hx index 13c4660..27372b0 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -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 @@ -287,7 +284,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]; diff --git a/source/smTools/SMFile.hx b/source/smTools/SMFile.hx index f4cde5b..fcb6555 100644 --- a/source/smTools/SMFile.hx +++ b/source/smTools/SMFile.hx @@ -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; + 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) { - _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>; + + + 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 = []; + + 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 \ No newline at end of file diff --git a/source/smTools/SMHeader.hx b/source/smTools/SMHeader.hx index cfe7770..656b15a 100644 --- a/source/smTools/SMHeader.hx +++ b/source/smTools/SMHeader.hx @@ -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; public function new(headerData:Array) { _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) diff --git a/source/smTools/SMMeasure.hx b/source/smTools/SMMeasure.hx index bd21dd9..4519cbd 100644 --- a/source/smTools/SMMeasure.hx +++ b/source/smTools/SMMeasure.hx @@ -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 \ No newline at end of file diff --git a/source/smTools/SMNote.hx b/source/smTools/SMNote.hx index 6f2a5bd..0a97f63 100644 --- a/source/smTools/SMNote.hx +++ b/source/smTools/SMNote.hx @@ -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 \ No newline at end of file