diff --git a/source/funkin/editors/SaveSubstate.hx b/source/funkin/editors/SaveSubstate.hx index 5a3fe81b..aed0c120 100644 --- a/source/funkin/editors/SaveSubstate.hx +++ b/source/funkin/editors/SaveSubstate.hx @@ -34,14 +34,12 @@ class SaveSubstate extends MusicBeatSubstate { var fileDialog = new FileDialog(); fileDialog.onCancel.add(function() { - trace("h"); close(); }); fileDialog.onSelect.add(function(str) { #if desktop File.saveContent(str, data); #end - trace("h"); close(); }); fileDialog.browse(SAVE, options.saveExt.getDefault(Path.extension(options.defaultSaveFile)), options.defaultSaveFile); diff --git a/source/funkin/editors/charter/CharterSelection.hx b/source/funkin/editors/charter/CharterSelection.hx index b0002c51..df83eb40 100644 --- a/source/funkin/editors/charter/CharterSelection.hx +++ b/source/funkin/editors/charter/CharterSelection.hx @@ -29,12 +29,12 @@ class CharterSelection extends EditorTreeMenu { list.push(new NewOption("New Difficulty", "New Difficulty", function() { })); - optionsTree.add(new OptionsScreen(s.name, "Select a difficulty to continue, or press 1 to add a new one.", list)); + optionsTree.add(new OptionsScreen(s.name, "Select a difficulty to continue.", list)); }) ]; list.insert(0, new NewOption("New Chart", "New Chart", function() { - + FlxG.state.openSubState(new SongCreationScreen()); })); main = new OptionsScreen("Chart Editor", "Select a song to modify the charts from.", list); diff --git a/source/funkin/editors/charter/SongCreationScreen.hx b/source/funkin/editors/charter/SongCreationScreen.hx new file mode 100644 index 00000000..d6967892 --- /dev/null +++ b/source/funkin/editors/charter/SongCreationScreen.hx @@ -0,0 +1,195 @@ +package funkin.editors.charter; + +import flixel.group.FlxGroup; +import funkin.backend.chart.ChartData; +import haxe.io.Bytes; + +typedef SongCreationData = { + var song:ChartData; + var instBytes:Bytes; + var voicesBytes:Bytes; +} + +class SongCreationScreen extends UISubstateWindow { + private var onSave:SongCreationData -> Void = null; + + public var songNameTextBox:UITextBox; + public var bpmStepper:UINumericStepper; + public var beatsPerMesureStepper:UINumericStepper; + public var stepsPerBeatStepper :UINumericStepper; + public var needsVoicesCheckbox:UICheckbox; + + public var displayNameTextBox:UITextBox; + public var iconTextBox:UITextBox; + public var iconSprite:FlxSprite; + public var opponentModeCheckbox:UICheckbox; + public var coopAllowedCheckbox:UICheckbox; + public var colorWheel:UIColorwheel; + public var difficulitesTextBox:UITextBox; + + public var backButton:UIButton; + public var saveButton:UIButton; + public var closeButton:UIButton; + + public var songDataGroup:FlxGroup = new FlxGroup(); + public var menuDataGroup:FlxGroup = new FlxGroup(); + + public var pages:Array = []; + public var pageSizes:Array = []; + public var curPage:Int = 0; + + public function new(?onSave:SongCreationData->Void) { + super(); + if (onSave != null) this.onSave = onSave; + } + + public override function create() { + winTitle = "Creating New Song"; + + winWidth = 748 - 32 + 40; + winHeight = 520; + + super.create(); + + function addLabelOn(ui:UISprite, text:String) + ui.members.push(new UIText(ui.x, ui.y - 24, 0, text)); + + var songTitle:UIText; + songDataGroup.add(songTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Song Info", 28)); + + songNameTextBox = new UITextBox(songTitle.x, songTitle.y + songTitle.height + 36, "Song Name"); + songDataGroup.add(songNameTextBox); + addLabelOn(songNameTextBox, "Song Name"); + + bpmStepper = new UINumericStepper(songNameTextBox.x + 320 + 26, songNameTextBox.y, 100, 1, 2, 1, null, 90); + songDataGroup.add(bpmStepper); + addLabelOn(bpmStepper, "BPM"); + + beatsPerMesureStepper = new UINumericStepper(bpmStepper.x + 60 + 26, bpmStepper.y, 4, 1, 0, 1, null, 54); + songDataGroup.add(beatsPerMesureStepper); + addLabelOn(beatsPerMesureStepper, "Time Signature"); + + songDataGroup.add(new UIText(beatsPerMesureStepper.x + 30, beatsPerMesureStepper.y + 3, 0, "/", 22)); + + stepsPerBeatStepper = new UINumericStepper(beatsPerMesureStepper.x + 30 + 24, beatsPerMesureStepper.y, 4, 1, 0, 1, null, 54); + songDataGroup.add(stepsPerBeatStepper); + + needsVoicesCheckbox = new UICheckbox(stepsPerBeatStepper.x + 80 + 26, stepsPerBeatStepper.y, "Voices", true); + songDataGroup.add(needsVoicesCheckbox); + addLabelOn(needsVoicesCheckbox, "Needs Voices"); + needsVoicesCheckbox.y += 6; needsVoicesCheckbox.x += 4; + + var menuTitle:UIText; + menuDataGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Menus Data (Freeplay/Story)", 28)); + + displayNameTextBox = new UITextBox(menuTitle.x, menuTitle.y + menuTitle.height + 36, "Display Name"); + menuDataGroup.add(displayNameTextBox); + addLabelOn(displayNameTextBox, "Display Name"); + + iconTextBox = new UITextBox(displayNameTextBox.x + 320 + 26, displayNameTextBox.y, "Icon", 150); + iconTextBox.onChange = (newIcon:String) -> {updateIcon(newIcon);} + menuDataGroup.add(iconTextBox); + addLabelOn(iconTextBox, "Icon"); + + updateIcon("Icon"); + + opponentModeCheckbox = new UICheckbox(displayNameTextBox.x, iconTextBox.y + 10 + 32 + 26, "Opponent Mode", true); + menuDataGroup.add(opponentModeCheckbox); + addLabelOn(opponentModeCheckbox, "Modes Allowed"); + + coopAllowedCheckbox = new UICheckbox(opponentModeCheckbox.x + 150 + 26, opponentModeCheckbox.y, "Co-op Mode", true); + menuDataGroup.add(coopAllowedCheckbox); + + colorWheel = new UIColorwheel(iconTextBox.x, coopAllowedCheckbox.y, 0xFFFFFF); + menuDataGroup.add(colorWheel); + addLabelOn(colorWheel, "Color"); + + difficulitesTextBox = new UITextBox(opponentModeCheckbox.x, opponentModeCheckbox.y + 6 + 32 + 26, ""); + menuDataGroup.add(difficulitesTextBox); + addLabelOn(difficulitesTextBox, "Difficulties"); + + for (checkbox in [opponentModeCheckbox, coopAllowedCheckbox]) + {checkbox.y += 6; checkbox.x += 4;} + + saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20 - 125, windowSpr.y + windowSpr.bHeight - 16 - 32, "Save & Close", function() { + if (curPage == pages.length-1) { + if (onSave != null) onSave(null); + close(); + } else { + curPage++; + refreshPages(); + } + + updatePagesTexts(); + }, 125); + add(saveButton); + + backButton = new UIButton(saveButton.x - 20 - saveButton.bWidth, saveButton.y, "< Back", function() { + curPage--; + refreshPages(); + + updatePagesTexts(); + }, 125); + add(backButton); + + closeButton = new UIButton(backButton.x - 20 - saveButton.bWidth, saveButton.y, "Cancel", function() { + close(); + }, 125); + add(closeButton); + closeButton.color = 0xFFFF0000; + + pages.push(cast add(songDataGroup)); + pageSizes.push(FlxPoint.get(748 - 32 + 40, 520)); + + pages.push(cast add(menuDataGroup)); + pageSizes.push(FlxPoint.get(748 - 32 + 40, 400)); + + refreshPages(); + updatePagesTexts(); + } + + function refreshPages() { + for (i=>page in pages) + page.visible = page.exists = i == curPage; + } + + function updatePagesTexts() { + windowSpr.bWidth = Std.int(pageSizes[curPage].x); + windowSpr.bHeight = Std.int(pageSizes[curPage].y); + + titleSpr.x = windowSpr.x + 25; + titleSpr.y = windowSpr.y + ((30 - titleSpr.height) / 2); + + saveButton.field.text = curPage == pages.length-1 ? "Save & Close" : 'Next (${curPage+1+1}/${pages.length}) >'; + titleSpr.text = 'Creating New Song (${curPage+1}/${pages.length})'; + + backButton.field.text = '< (${curPage}/${pages.length}) Back'; + backButton.visible = backButton.exists = curPage > 0; + + backButton.x = (saveButton.x = windowSpr.x + windowSpr.bWidth - 20 - 125) - 20 - saveButton.bWidth; + closeButton.x = (curPage > 0 ? backButton : saveButton).x - 20 - saveButton.bWidth; + + for (button in [saveButton, backButton, closeButton]) + button.y = windowSpr.y + windowSpr.bHeight - 16 - 32; + } + + function updateIcon(icon:String) { + if (iconSprite == null) menuDataGroup.add(iconSprite = new FlxSprite()); + + if (iconSprite.animation.exists(icon)) return; + @:privateAccess iconSprite.animation.clearAnimations(); + + var path:String = Paths.image('icons/$icon'); + if (!Assets.exists(path)) path = Paths.image('icons/face'); + + iconSprite.loadGraphic(path, true, 150, 150); + iconSprite.animation.add(icon, [0], 0, false); + iconSprite.antialiasing = true; + iconSprite.animation.play(icon); + + iconSprite.scale.set(0.5, 0.5); + iconSprite.updateHitbox(); + iconSprite.setPosition(iconTextBox.x + 150 + 8, (iconTextBox.y + 16) - (iconSprite.height/2)); + } + +} \ No newline at end of file diff --git a/source/funkin/editors/ui/UIState.hx b/source/funkin/editors/ui/UIState.hx index f264e8ca..01d330c5 100644 --- a/source/funkin/editors/ui/UIState.hx +++ b/source/funkin/editors/ui/UIState.hx @@ -12,7 +12,6 @@ import openfl.ui.MouseCursor; import flixel.math.FlxRect; class UIState extends MusicBeatState { - public var curContextMenu:UIContextMenu = null; public static var state(get, null):UIState; diff --git a/source/funkin/options/TreeMenu.hx b/source/funkin/options/TreeMenu.hx index fbfebf11..adca29d9 100644 --- a/source/funkin/options/TreeMenu.hx +++ b/source/funkin/options/TreeMenu.hx @@ -1,5 +1,6 @@ package funkin.options; +import funkin.editors.ui.UIState; import flixel.FlxState; import funkin.backend.FunkinText; import flixel.tweens.FlxTween; @@ -9,7 +10,7 @@ import flixel.util.typeLimit.OneOfTwo; import funkin.options.type.OptionType; import funkin.options.categories.*; -class TreeMenu extends MusicBeatState { +class TreeMenu extends UIState { public var main:OptionsScreen; public var optionsTree:OptionsTree; public var pathLabel:FunkinText;