From ac3f27edd48a6ad0f89a475148db8b97c47be006 Mon Sep 17 00:00:00 2001 From: Cameron Taylor <cameron.taylor.ninja@gmail.com> Date: Mon, 11 Dec 2023 00:19:33 -0500 Subject: [PATCH 1/8] icon char select in progres --- assets | 2 +- source/funkin/play/character/CharacterData.hx | 27 ++++++++ .../ui/debug/charting/ChartEditorState.hx | 62 +++++++++++++++++++ source/funkin/ui/freeplay/SongMenuItem.hx | 1 + 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/assets b/assets index 3c8ac202b..32364eacf 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3c8ac202bbb93bf84c7dcd0697a9d7121d3c5283 +Subproject commit 32364eacf09940cdba39457a2bb32ac1bca958be diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index abe8bf992..f1f5ebebe 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -280,6 +280,33 @@ class CharacterDataParser return characterCache.keys().array(); } + public static function getCharPixelIconAsset(char:String):String + { + var icon:String = char; + + switch (icon) + { + case "bf-christmas" | "bf-car" | "bf-pixel" | "bf-holding-gf": + icon = "bf"; + case "monster-christmas": + icon = "monster"; + case "mom-car": + icon = "mommy"; + case "pico-blazin": + icon = "pico"; + case "gf-christmas" | "gf-car" | "gf-pixel" | "gf-tankmen": + icon = "gf"; + case "dad": + icon = "daddy"; + case "darnell-blazin": + icon = "darnell"; + case "senpai-angry": + icon = "senpai"; + } + + return Paths.image("freeplay/icons/" + icon + "pixel"); + } + /** * Clears the character data cache. */ diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 66effc775..2cab863b8 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1,6 +1,9 @@ package funkin.ui.debug.charting; import funkin.util.logging.CrashHandler; +import haxe.ui.containers.HBox; +import haxe.ui.containers.Grid; +import haxe.ui.containers.ScrollView; import haxe.ui.containers.menus.MenuBar; import flixel.addons.display.FlxSliceSprite; import flixel.addons.display.FlxTiledSprite; @@ -106,6 +109,7 @@ import haxe.ui.containers.menus.MenuItem; import haxe.ui.containers.menus.MenuCheckBox; import haxe.ui.containers.TreeView; import haxe.ui.containers.TreeViewNode; +import haxe.ui.components.Image; import haxe.ui.core.Component; import haxe.ui.core.Screen; import haxe.ui.events.DragEvent; @@ -114,6 +118,7 @@ import haxe.ui.events.UIEvent; import haxe.ui.events.UIEvent; import haxe.ui.focus.FocusManager; import openfl.display.BitmapData; +import flixel.input.mouse.FlxMouseEvent; using Lambda; @@ -2082,6 +2087,63 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState healthIconBF.flipX = true; add(healthIconBF); healthIconBF.zIndex = 30; + + FlxMouseEvent.add(healthIconDad, function(_) { + trace("clicked dad"); + + var toolbox:CollapsibleDialog = cast haxe.ui.RuntimeComponentBuilder.fromAsset(Paths.ui('chart-editor/toolbox/iconselector')); + toolbox.showDialog(false); + var scrollView = toolbox.findComponent('charSelectScroll'); + + var hbox = new Grid(); + hbox.columns = 5; + hbox.width = 100; + scrollView.addComponent(hbox); + + var charIds:Array<String> = CharacterDataParser.listCharacterIds(); + + charIds.sort(function(a, b) { + var result:Int = 0; + + if (a < b) + { + result = -1; + } + else if (a > b) + { + result = 1; + } + + return result; + }); + + for (char in charIds) + { + var image = new haxe.ui.components.Button(); + image.width = 70; + image.height = 70; + + image.icon = CharacterDataParser.getCharPixelIconAsset(char); + image.onClick = _ -> { + toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.APPLY); + // var label = toolbox.findComponent('charIconName'); + // label.text = char; + }; + + image.onMouseOver = _ -> { + var label = toolbox.findComponent('charIconName'); + label.text = char; + }; + hbox.addComponent(image); + } + + toolbox.x = FlxG.mouse.screenX; + toolbox.y = FlxG.mouse.screenY; + }); + + FlxMouseEvent.add(healthIconBF, function(_) { + trace("clicked bf"); + }); } function buildNotePreview():Void diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 477047c68..4e0772dfe 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -175,6 +175,7 @@ class SongMenuItem extends FlxSpriteGroup trace(char); // TODO: Put this in the character metadata where it belongs. + // TODO: Also, can use CharacterDataParser.getCharPixelIconAsset() switch (char) { case "monster-christmas": From 181e3f85b851fd7a9e580a54b9e85251e1675cf8 Mon Sep 17 00:00:00 2001 From: Cameron Taylor <cameron.taylor.ninja@gmail.com> Date: Mon, 11 Dec 2023 02:26:37 -0500 Subject: [PATCH 2/8] switching opp --- source/funkin/ui/debug/charting/ChartEditorState.hx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 2cab863b8..b6f687c75 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2123,9 +2123,14 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState image.width = 70; image.height = 70; + if (char == currentSongMetadata.playData.characters.opponent) image.selected = true; + image.icon = CharacterDataParser.getCharPixelIconAsset(char); image.onClick = _ -> { + healthIconsDirty = true; + currentSongMetadata.playData.characters.opponent = char; toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.APPLY); + // var label = toolbox.findComponent('charIconName'); // label.text = char; }; From 9ffffe9c8afdde6ab256933ed1aa739b523e30e4 Mon Sep 17 00:00:00 2001 From: Cameron Taylor <cameron.taylor.ninja@gmail.com> Date: Mon, 11 Dec 2023 02:40:58 -0500 Subject: [PATCH 3/8] player char select --- .../ui/debug/charting/ChartEditorState.hx | 130 ++++++++++-------- 1 file changed, 74 insertions(+), 56 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index b6f687c75..d5f6fd9ae 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2089,68 +2089,86 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState healthIconBF.zIndex = 30; FlxMouseEvent.add(healthIconDad, function(_) { - trace("clicked dad"); - - var toolbox:CollapsibleDialog = cast haxe.ui.RuntimeComponentBuilder.fromAsset(Paths.ui('chart-editor/toolbox/iconselector')); - toolbox.showDialog(false); - var scrollView = toolbox.findComponent('charSelectScroll'); - - var hbox = new Grid(); - hbox.columns = 5; - hbox.width = 100; - scrollView.addComponent(hbox); - - var charIds:Array<String> = CharacterDataParser.listCharacterIds(); - - charIds.sort(function(a, b) { - var result:Int = 0; - - if (a < b) - { - result = -1; - } - else if (a > b) - { - result = 1; - } - - return result; - }); - - for (char in charIds) - { - var image = new haxe.ui.components.Button(); - image.width = 70; - image.height = 70; - - if (char == currentSongMetadata.playData.characters.opponent) image.selected = true; - - image.icon = CharacterDataParser.getCharPixelIconAsset(char); - image.onClick = _ -> { - healthIconsDirty = true; - currentSongMetadata.playData.characters.opponent = char; - toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.APPLY); - - // var label = toolbox.findComponent('charIconName'); - // label.text = char; - }; - - image.onMouseOver = _ -> { - var label = toolbox.findComponent('charIconName'); - label.text = char; - }; - hbox.addComponent(image); - } - - toolbox.x = FlxG.mouse.screenX; - toolbox.y = FlxG.mouse.screenY; + createAndOpenCharSelect(1); }); FlxMouseEvent.add(healthIconBF, function(_) { - trace("clicked bf"); + createAndOpenCharSelect(0); }); } + /** + * @param charType 0 == BF, 1 == Dad + */ + function createAndOpenCharSelect(charType:Int = 0):Void + { + var charData = currentSongMetadata.playData.characters; + var currentChar:String = switch (charType) + { + case 0: charData.player; + case 1: charData.opponent; + default: throw 'Invalid charType: ' + charType; + }; + var toolbox:CollapsibleDialog = cast haxe.ui.RuntimeComponentBuilder.fromAsset(Paths.ui('chart-editor/toolbox/iconselector')); + toolbox.showDialog(false); + var scrollView = toolbox.findComponent('charSelectScroll'); + + var hbox = new Grid(); + hbox.columns = 5; + hbox.width = 100; + scrollView.addComponent(hbox); + + var charIds:Array<String> = CharacterDataParser.listCharacterIds(); + + charIds.sort(function(a, b) { + var result:Int = 0; + + if (a < b) + { + result = -1; + } + else if (a > b) + { + result = 1; + } + + return result; + }); + + for (char in charIds) + { + var image = new haxe.ui.components.Button(); + image.width = 70; + image.height = 70; + + if (char == currentChar) image.selected = true; + + image.icon = CharacterDataParser.getCharPixelIconAsset(char); + image.onClick = _ -> { + healthIconsDirty = true; + switch (charType) + { + case 0: currentSongMetadata.playData.characters.player = char; + case 1: currentSongMetadata.playData.characters.opponent = char; + default: throw 'Invalid charType: ' + charType; + }; + toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.APPLY); + + // var label = toolbox.findComponent('charIconName'); + // label.text = char; + }; + + image.onMouseOver = _ -> { + var label = toolbox.findComponent('charIconName'); + label.text = char; + }; + hbox.addComponent(image); + } + + toolbox.x = FlxG.mouse.screenX; + toolbox.y = FlxG.mouse.screenY; + } + function buildNotePreview():Void { var height:Int = FlxG.height - MENU_BAR_HEIGHT - GRID_TOP_PAD - PLAYBAR_HEIGHT - GRID_TOP_PAD - GRID_TOP_PAD; From 05f977f85fcf38987f9da2dd6c978be94127c06d Mon Sep 17 00:00:00 2001 From: Cameron Taylor <cameron.taylor.ninja@gmail.com> Date: Mon, 11 Dec 2023 03:38:44 -0500 Subject: [PATCH 4/8] character selector --- .../ui/debug/charting/ChartEditorState.hx | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index d5f6fd9ae..76247bde2 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2089,11 +2089,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState healthIconBF.zIndex = 30; FlxMouseEvent.add(healthIconDad, function(_) { - createAndOpenCharSelect(1); + if (!isCursorOverHaxeUI) createAndOpenCharSelect(1); }); FlxMouseEvent.add(healthIconBF, function(_) { - createAndOpenCharSelect(0); + if (!isCursorOverHaxeUI) createAndOpenCharSelect(0); }); } @@ -2110,7 +2110,28 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState default: throw 'Invalid charType: ' + charType; }; var toolbox:CollapsibleDialog = cast haxe.ui.RuntimeComponentBuilder.fromAsset(Paths.ui('chart-editor/toolbox/iconselector')); + toolbox.title += " - " + switch (charType) + { + case 0: "Player"; + case 1: "Opponent"; + default: throw 'Invalid charType: ' + charType; + }; + + var _overlay = new Component(); + _overlay.id = "modal-background"; + _overlay.addClass("modal-background"); + _overlay.percentWidth = _overlay.percentHeight = 100; + _overlay.opacity = 0; + FlxTween.tween(_overlay, {opacity: 0.2}, 0.1, {ease: FlxEase.quartOut}); + _overlay.onClick = function(_) { + toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.CANCEL); + Screen.instance.removeComponent(_overlay); + }; + + Screen.instance.addComponent(_overlay); + toolbox.showDialog(false); + toolbox.closable = false; var scrollView = toolbox.findComponent('charSelectScroll'); var hbox = new Grid(); @@ -2153,7 +2174,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState default: throw 'Invalid charType: ' + charType; }; toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.APPLY); - + Screen.instance.removeComponent(_overlay); // var label = toolbox.findComponent('charIconName'); // label.text = char; }; @@ -2165,8 +2186,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState hbox.addComponent(image); } - toolbox.x = FlxG.mouse.screenX; - toolbox.y = FlxG.mouse.screenY; + toolbox.x = FlxG.mouse.screenX - toolbox.width / 2; + toolbox.y = FlxG.mouse.screenY - 16; } function buildNotePreview():Void From b33f27f0973c5eb12e3f2babb4c2041129d34c47 Mon Sep 17 00:00:00 2001 From: Cameron Taylor <cameron.taylor.ninja@gmail.com> Date: Mon, 11 Dec 2023 04:35:39 -0500 Subject: [PATCH 5/8] tiny lil polish and cleanin --- .../ui/debug/charting/ChartEditorState.hx | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 76247bde2..e49dde838 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2110,6 +2110,10 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState default: throw 'Invalid charType: ' + charType; }; var toolbox:CollapsibleDialog = cast haxe.ui.RuntimeComponentBuilder.fromAsset(Paths.ui('chart-editor/toolbox/iconselector')); + + toolbox.x = FlxG.mouse.screenX - toolbox.width / 2; + toolbox.y = FlxG.mouse.screenY - 16; + toolbox.title += " - " + switch (charType) { case 0: "Player"; @@ -2118,21 +2122,38 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState }; var _overlay = new Component(); + + var hideCharIconPicker = function() { + FlxTween.tween(_overlay, {opacity: 0}, 0.05, + { + ease: FlxEase.quartOut + }); + FlxTween.tween(toolbox, {opacity: 0, y: toolbox.y + 10}, 0.1, + { + ease: FlxEase.quartOut, + onComplete: function(_) { + toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.CANCEL); + Screen.instance.removeComponent(_overlay); + } + }); + }; + _overlay.id = "modal-background"; _overlay.addClass("modal-background"); _overlay.percentWidth = _overlay.percentHeight = 100; _overlay.opacity = 0; FlxTween.tween(_overlay, {opacity: 0.2}, 0.1, {ease: FlxEase.quartOut}); _overlay.onClick = function(_) { - toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.CANCEL); - Screen.instance.removeComponent(_overlay); + hideCharIconPicker(); }; Screen.instance.addComponent(_overlay); toolbox.showDialog(false); + toolbox.opacity = 0; + FlxTween.tween(toolbox, {opacity: 1, y: toolbox.y + 10}, 0.1, {ease: FlxEase.quartOut}); toolbox.closable = false; - var scrollView = toolbox.findComponent('charSelectScroll'); + var scrollView:ScrollView = cast toolbox.findComponent('charSelectScroll'); var hbox = new Grid(); hbox.columns = 5; @@ -2156,13 +2177,19 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState return result; }); - for (char in charIds) + for (ind => char in charIds) { var image = new haxe.ui.components.Button(); image.width = 70; image.height = 70; + image.iconPosition = "top"; + image.text = char; - if (char == currentChar) image.selected = true; + if (char == currentChar) + { + scrollView.hscrollPos = Math.floor(ind / 5) * 80; + image.selected = true; + } image.icon = CharacterDataParser.getCharPixelIconAsset(char); image.onClick = _ -> { @@ -2173,8 +2200,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState case 1: currentSongMetadata.playData.characters.opponent = char; default: throw 'Invalid charType: ' + charType; }; - toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.APPLY); - Screen.instance.removeComponent(_overlay); + hideCharIconPicker(); + // var label = toolbox.findComponent('charIconName'); // label.text = char; }; @@ -2185,9 +2212,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState }; hbox.addComponent(image); } - - toolbox.x = FlxG.mouse.screenX - toolbox.width / 2; - toolbox.y = FlxG.mouse.screenY - 16; } function buildNotePreview():Void From 52f16ce457e57985228df1d81d07c24ec704009d Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 12 Dec 2023 05:24:43 -0500 Subject: [PATCH 6/8] Redo icon dialog and add support to metadata dialog. --- assets | 2 +- source/funkin/play/character/CharacterData.hx | 7 +- .../ui/debug/charting/ChartEditorState.hx | 253 +++--------------- .../charting/dialogs/ChartEditorBaseDialog.hx | 35 +++ .../charting/dialogs/ChartEditorBaseMenu.hx | 24 ++ .../ChartEditorCharacterIconSelectorMenu.hx | 129 +++++++++ .../dialogs/ChartEditorUploadChartDialog.hx | 1 + .../handlers/ChartEditorDialogHandler.hx | 11 + .../ChartEditorImportExportHandler.hx | 2 +- .../handlers/ChartEditorToolboxHandler.hx | 207 +++----------- .../toolboxes/ChartEditorBaseToolbox.hx | 28 ++ .../toolboxes/ChartEditorMetadataToolbox.hx | 203 ++++++++++++++ 12 files changed, 511 insertions(+), 391 deletions(-) create mode 100644 source/funkin/ui/debug/charting/dialogs/ChartEditorBaseMenu.hx create mode 100644 source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx create mode 100644 source/funkin/ui/debug/charting/toolboxes/ChartEditorBaseToolbox.hx create mode 100644 source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx diff --git a/assets b/assets index 32364eacf..e591e9acc 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 32364eacf09940cdba39457a2bb32ac1bca958be +Subproject commit e591e9acc12b9aba6124332c4d66453f1f83368c diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index f1f5ebebe..16cc8b299 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -280,6 +280,9 @@ class CharacterDataParser return characterCache.keys().array(); } + /** + * TODO: Hardcode this. + */ public static function getCharPixelIconAsset(char:String):String { var icon:String = char; @@ -290,9 +293,9 @@ class CharacterDataParser icon = "bf"; case "monster-christmas": icon = "monster"; - case "mom-car": + case "mom" | "mom-car": icon = "mommy"; - case "pico-blazin": + case "pico-blazin" | "pico-playable" | "pico-speaker": icon = "pico"; case "gf-christmas" | "gf-car" | "gf-pixel" | "gf-tankmen": icon = "gf"; diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index e49dde838..2f7df7330 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -110,6 +110,7 @@ import haxe.ui.containers.menus.MenuCheckBox; import haxe.ui.containers.TreeView; import haxe.ui.containers.TreeViewNode; import haxe.ui.components.Image; +import funkin.ui.debug.charting.toolboxes.ChartEditorBaseToolbox; import haxe.ui.core.Component; import haxe.ui.core.Screen; import haxe.ui.events.DragEvent; @@ -2087,131 +2088,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState healthIconBF.flipX = true; add(healthIconBF); healthIconBF.zIndex = 30; - - FlxMouseEvent.add(healthIconDad, function(_) { - if (!isCursorOverHaxeUI) createAndOpenCharSelect(1); - }); - - FlxMouseEvent.add(healthIconBF, function(_) { - if (!isCursorOverHaxeUI) createAndOpenCharSelect(0); - }); - } - - /** - * @param charType 0 == BF, 1 == Dad - */ - function createAndOpenCharSelect(charType:Int = 0):Void - { - var charData = currentSongMetadata.playData.characters; - var currentChar:String = switch (charType) - { - case 0: charData.player; - case 1: charData.opponent; - default: throw 'Invalid charType: ' + charType; - }; - var toolbox:CollapsibleDialog = cast haxe.ui.RuntimeComponentBuilder.fromAsset(Paths.ui('chart-editor/toolbox/iconselector')); - - toolbox.x = FlxG.mouse.screenX - toolbox.width / 2; - toolbox.y = FlxG.mouse.screenY - 16; - - toolbox.title += " - " + switch (charType) - { - case 0: "Player"; - case 1: "Opponent"; - default: throw 'Invalid charType: ' + charType; - }; - - var _overlay = new Component(); - - var hideCharIconPicker = function() { - FlxTween.tween(_overlay, {opacity: 0}, 0.05, - { - ease: FlxEase.quartOut - }); - FlxTween.tween(toolbox, {opacity: 0, y: toolbox.y + 10}, 0.1, - { - ease: FlxEase.quartOut, - onComplete: function(_) { - toolbox.hideDialog(haxe.ui.containers.dialogs.Dialog.DialogButton.CANCEL); - Screen.instance.removeComponent(_overlay); - } - }); - }; - - _overlay.id = "modal-background"; - _overlay.addClass("modal-background"); - _overlay.percentWidth = _overlay.percentHeight = 100; - _overlay.opacity = 0; - FlxTween.tween(_overlay, {opacity: 0.2}, 0.1, {ease: FlxEase.quartOut}); - _overlay.onClick = function(_) { - hideCharIconPicker(); - }; - - Screen.instance.addComponent(_overlay); - - toolbox.showDialog(false); - toolbox.opacity = 0; - FlxTween.tween(toolbox, {opacity: 1, y: toolbox.y + 10}, 0.1, {ease: FlxEase.quartOut}); - toolbox.closable = false; - var scrollView:ScrollView = cast toolbox.findComponent('charSelectScroll'); - - var hbox = new Grid(); - hbox.columns = 5; - hbox.width = 100; - scrollView.addComponent(hbox); - - var charIds:Array<String> = CharacterDataParser.listCharacterIds(); - - charIds.sort(function(a, b) { - var result:Int = 0; - - if (a < b) - { - result = -1; - } - else if (a > b) - { - result = 1; - } - - return result; - }); - - for (ind => char in charIds) - { - var image = new haxe.ui.components.Button(); - image.width = 70; - image.height = 70; - image.iconPosition = "top"; - image.text = char; - - if (char == currentChar) - { - scrollView.hscrollPos = Math.floor(ind / 5) * 80; - image.selected = true; - } - - image.icon = CharacterDataParser.getCharPixelIconAsset(char); - image.onClick = _ -> { - healthIconsDirty = true; - switch (charType) - { - case 0: currentSongMetadata.playData.characters.player = char; - case 1: currentSongMetadata.playData.characters.opponent = char; - default: throw 'Invalid charType: ' + charType; - }; - hideCharIconPicker(); - - // var label = toolbox.findComponent('charIconName'); - // label.text = char; - }; - - image.onMouseOver = _ -> { - var label = toolbox.findComponent('charIconName'); - label.text = char; - }; - hbox.addComponent(image); - } } function buildNotePreview():Void @@ -2406,6 +2282,21 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (!Preferences.debugDisplay) menubar.paddingLeft = null; this.setupNotifications(); + + // Setup character dropdowns. + FlxMouseEvent.add(healthIconDad, function(_) { + if (!isCursorOverHaxeUI) + { + this.openCharacterDropdown(CharacterType.DAD, true); + } + }); + + FlxMouseEvent.add(healthIconBF, function(_) { + if (!isCursorOverHaxeUI) + { + this.openCharacterDropdown(CharacterType.BF, true); + } + }); } /** @@ -2446,13 +2337,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState else { Conductor.currentTimeChange.bpm += 1; - refreshMetadataToolbox(); + this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); } } playbarBPM.onRightClick = _ -> { Conductor.currentTimeChange.bpm -= 1; - refreshMetadataToolbox(); + this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); } // Add functionality to the menu items. @@ -3509,6 +3400,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var overlapsSelection:Bool = FlxG.mouse.overlaps(renderedSelectionSquares); + var overlapsHealthIcons:Bool = FlxG.mouse.overlaps(healthIconBF) || FlxG.mouse.overlaps(healthIconDad); + if (FlxG.mouse.justPressedMiddle) { if (scrollAnchorScreenPos == null) @@ -3528,11 +3421,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { scrollAnchorScreenPos = null; } - else if (gridPlayheadScrollArea != null && FlxG.mouse.overlaps(gridPlayheadScrollArea)) + else if (gridPlayheadScrollArea != null && FlxG.mouse.overlaps(gridPlayheadScrollArea) && !isCursorOverHaxeUI) { gridPlayheadScrollAreaPressed = true; } - else if (notePreview != null && FlxG.mouse.overlaps(notePreview)) + else if (notePreview != null && FlxG.mouse.overlaps(notePreview) && !isCursorOverHaxeUI) { // Clicked note preview notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); @@ -4220,6 +4113,10 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { targetCursorMode = Cell; } + else if (overlapsHealthIcons) + { + targetCursorMode = Pointer; + } } } @@ -4250,7 +4147,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState difficultySelectDirty = false; // Manage the Select Difficulty tree view. - var difficultyToolbox:Null<CollapsibleDialog> = this.getToolbox(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT); + var difficultyToolbox:Null<CollapsibleDialog> = this.getToolbox_OLD(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT); if (difficultyToolbox == null) return; var treeView:Null<TreeView> = difficultyToolbox.findComponent('difficultyToolboxTree'); @@ -4297,7 +4194,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handlePlayerPreviewToolbox():Void { // Manage the Select Difficulty tree view. - var charPreviewToolbox:Null<CollapsibleDialog> = this.getToolbox(CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT); + var charPreviewToolbox:Null<CollapsibleDialog> = this.getToolbox_OLD(CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT); if (charPreviewToolbox == null) return; // TODO: Re-enable the player preview once we figure out the performance issues. @@ -4333,7 +4230,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handleOpponentPreviewToolbox():Void { // Manage the Select Difficulty tree view. - var charPreviewToolbox:Null<CollapsibleDialog> = this.getToolbox(CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT); + var charPreviewToolbox:Null<CollapsibleDialog> = this.getToolbox_OLD(CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT); if (charPreviewToolbox == null) return; // TODO: Re-enable the player preview once we figure out the performance issues. @@ -5042,7 +4939,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState Conductor.mapTimeChanges(this.currentSongMetadata.timeChanges); refreshDifficultyTreeSelection(); - refreshMetadataToolbox(); + this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); } else { @@ -5051,7 +4948,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState selectedDifficulty = prevDifficulty; refreshDifficultyTreeSelection(); - refreshMetadataToolbox(); + this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); } } else @@ -5070,7 +4967,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState selectedDifficulty = nextDifficulty; refreshDifficultyTreeSelection(); - refreshMetadataToolbox(); + this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); } else { @@ -5079,7 +4976,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState selectedDifficulty = nextDifficulty; refreshDifficultyTreeSelection(); - refreshMetadataToolbox(); + this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); } } @@ -5192,7 +5089,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (treeView == null) { // Manage the Select Difficulty tree view. - var difficultyToolbox:Null<CollapsibleDialog> = this.getToolbox(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT); + var difficultyToolbox:Null<CollapsibleDialog> = this.getToolbox_OLD(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT); if (difficultyToolbox == null) return; treeView = difficultyToolbox.findComponent('difficultyToolboxTree'); @@ -5212,7 +5109,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { if (treeView == null) { - var difficultyToolbox:Null<CollapsibleDialog> = this.getToolbox(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT); + var difficultyToolbox:Null<CollapsibleDialog> = this.getToolbox_OLD(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT); if (difficultyToolbox == null) return null; treeView = difficultyToolbox.findComponent('difficultyToolboxTree'); @@ -5256,8 +5153,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState trace('Changing difficulty to "$variation:$difficulty"'); selectedVariation = variation; selectedDifficulty = difficulty; - // refreshDifficultyTreeSelection(treeView); - refreshMetadataToolbox(); + this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); } // case 'song': // case 'variation': @@ -5266,82 +5162,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState trace('Selected wrong node type, resetting selection.'); var currentTreeDifficultyNode = getCurrentTreeDifficultyNode(treeView); if (currentTreeDifficultyNode != null) treeView.selectedNode = currentTreeDifficultyNode; - refreshMetadataToolbox(); - } - } - - /** - * When the difficulty changes, update the song metadata toolbox to reflect the new data. - */ - function refreshMetadataToolbox():Void - { - var toolbox:Null<CollapsibleDialog> = this.getToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); - if (toolbox == null) return; - - var inputSongName:Null<TextField> = toolbox.findComponent('inputSongName', TextField); - if (inputSongName != null) inputSongName.value = currentSongMetadata.songName; - - var inputSongArtist:Null<TextField> = toolbox.findComponent('inputSongArtist', TextField); - if (inputSongArtist != null) inputSongArtist.value = currentSongMetadata.artist; - - var inputStage:Null<DropDown> = toolbox.findComponent('inputStage', DropDown); - if (inputStage != null) inputStage.value = currentSongMetadata.playData.stage; - - var inputNoteStyle:Null<DropDown> = toolbox.findComponent('inputNoteStyle', DropDown); - if (inputNoteStyle != null) inputNoteStyle.value = currentSongMetadata.playData.noteStyle; - - var inputBPM:Null<NumberStepper> = toolbox.findComponent('inputBPM', NumberStepper); - if (inputBPM != null) inputBPM.value = currentSongMetadata.timeChanges[0].bpm; - - var labelScrollSpeed:Null<Label> = toolbox.findComponent('labelScrollSpeed', Label); - if (labelScrollSpeed != null) labelScrollSpeed.text = 'Scroll Speed: ${currentSongChartScrollSpeed}x'; - - var inputScrollSpeed:Null<Slider> = toolbox.findComponent('inputScrollSpeed', Slider); - if (inputScrollSpeed != null) inputScrollSpeed.value = currentSongChartScrollSpeed; - - var frameVariation:Null<Frame> = toolbox.findComponent('frameVariation', Frame); - if (frameVariation != null) frameVariation.text = 'Variation: ${selectedVariation.toTitleCase()}'; - var frameDifficulty:Null<Frame> = toolbox.findComponent('frameDifficulty', Frame); - if (frameDifficulty != null) frameDifficulty.text = 'Difficulty: ${selectedDifficulty.toTitleCase()}'; - - var inputStage:Null<DropDown> = toolbox.findComponent('inputStage', DropDown); - var stageId:String = currentSongMetadata.playData.stage; - var stageData:Null<StageData> = StageDataParser.parseStageData(stageId); - if (inputStage != null) - { - inputStage.value = (stageData != null) ? - {id: stageId, text: stageData.name} : - {id: "mainStage", text: "Main Stage"}; - } - - var inputCharacterPlayer:Null<DropDown> = toolbox.findComponent('inputCharacterPlayer', DropDown); - var charIdPlayer:String = currentSongMetadata.playData.characters.player; - var charDataPlayer:Null<CharacterData> = CharacterDataParser.fetchCharacterData(charIdPlayer); - if (inputCharacterPlayer != null) - { - inputCharacterPlayer.value = (charDataPlayer != null) ? - {id: charIdPlayer, text: charDataPlayer.name} : - {id: "bf", text: "Boyfriend"}; - } - - var inputCharacterOpponent:Null<DropDown> = toolbox.findComponent('inputCharacterOpponent', DropDown); - var charIdOpponent:String = currentSongMetadata.playData.characters.opponent; - var charDataOpponent:Null<CharacterData> = CharacterDataParser.fetchCharacterData(charIdOpponent); - if (inputCharacterOpponent != null) - { - inputCharacterOpponent.value = (charDataOpponent != null) ? - {id: charIdOpponent, text: charDataOpponent.name} : - {id: "dad", text: "Dad"}; - } - - var inputCharacterGirlfriend:Null<DropDown> = toolbox.findComponent('inputCharacterGirlfriend', DropDown); - var charIdGirlfriend:String = currentSongMetadata.playData.characters.girlfriend; - var charDataGirlfriend:Null<CharacterData> = CharacterDataParser.fetchCharacterData(charIdGirlfriend); - if (inputCharacterGirlfriend != null) - { - inputCharacterGirlfriend.value = (charDataGirlfriend != null) ? - {id: charIdGirlfriend, text: charDataGirlfriend.name} : - {id: "none", text: "None"}; + this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); } } diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx index a180825a8..e3d6fd13a 100644 --- a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx @@ -2,8 +2,12 @@ package funkin.ui.debug.charting.dialogs; import haxe.ui.containers.dialogs.Dialog; import haxe.ui.containers.dialogs.Dialog.DialogEvent; +import haxe.ui.animation.AnimationBuilder; +import haxe.ui.styles.EasingFunction; import haxe.ui.core.Component; +// @:nullSafety // TODO: Fix null safety when used with HaxeUI build macros. + @:access(funkin.ui.debug.charting.ChartEditorState) class ChartEditorBaseDialog extends Dialog { @@ -25,6 +29,12 @@ class ChartEditorBaseDialog extends Dialog this.onDialogClosed = event -> onClose(event); } + private override function onReady():Void + { + _overlay.opacity = 0; + fadeInDialogOverlay(); + } + /** * Called when the dialog is closed. * Override this to add custom behavior. @@ -54,6 +64,31 @@ class ChartEditorBaseDialog extends Dialog this.closable = params.closable ?? false; } + + static final OVERLAY_EASE_DURATION:Float = 5.0; + static final OVERLAY_EASE_TYPE:String = "linear"; + + function fadeInDialogOverlay():Void + { + if (!modal) + { + trace('Dialog is not modal, skipping overlay fade...'); + return; + } + + if (_overlay == null) + { + trace('[WARN] Dialog overlay is null, skipping overlay fade...'); + return; + } + + var builder = new AnimationBuilder(_overlay, OVERLAY_EASE_DURATION, "linear"); + builder.setPosition(0, "opacity", 0, true); // 0% absolute + builder.setPosition(100, "opacity", 0.80, true); + + trace('Fading in dialog overlay...'); + builder.play(); + } } typedef DialogParams = diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseMenu.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseMenu.hx new file mode 100644 index 000000000..cb4cb447b --- /dev/null +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseMenu.hx @@ -0,0 +1,24 @@ +package funkin.ui.debug.charting.dialogs; + +import haxe.ui.containers.dialogs.Dialog; +import haxe.ui.containers.dialogs.Dialog.DialogEvent; +import haxe.ui.animation.AnimationBuilder; +import haxe.ui.styles.EasingFunction; +import haxe.ui.core.Component; +import haxe.ui.containers.menus.Menu; + +// @:nullSafety // TODO: Fix null safety when used with HaxeUI build macros. +@:access(funkin.ui.debug.charting.ChartEditorState) +class ChartEditorBaseMenu extends Menu +{ + var state:ChartEditorState; + + public function new(state:ChartEditorState) + { + super(); + + this.state = state; + + // this.destroyOnClose = true; + } +} diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx new file mode 100644 index 000000000..357a739fd --- /dev/null +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx @@ -0,0 +1,129 @@ +package funkin.ui.debug.charting.dialogs; + +import flixel.math.FlxPoint; +import funkin.play.character.BaseCharacter.CharacterType; +import funkin.play.character.CharacterData; +import funkin.play.character.CharacterData.CharacterDataParser; +import funkin.play.components.HealthIcon; +import funkin.ui.debug.charting.dialogs.ChartEditorBaseDialog.DialogParams; +import funkin.util.SortUtil; +import haxe.ui.components.Label; +import haxe.ui.containers.Grid; +import haxe.ui.containers.HBox; +import haxe.ui.containers.ScrollView; +import haxe.ui.containers.ScrollView; +import haxe.ui.core.Screen; + +// @:nullSafety // TODO: Fix null safety when used with HaxeUI build macros. +@:access(funkin.ui.debug.charting.ChartEditorState) +@:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/dialogs/character-icon-selector.xml")) +class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu +{ + public var charSelectScroll:ScrollView; + public var charIconName:Label; + + public function new(state2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false) + { + super(state2); + + initialize(charType, lockPosition); + } + + function initialize(charType:CharacterType, lockPosition:Bool) + { + var currentCharId:String = switch (charType) + { + case BF: state.currentSongMetadata.playData.characters.player; + case GF: state.currentSongMetadata.playData.characters.girlfriend; + case DAD: state.currentSongMetadata.playData.characters.opponent; + default: throw 'Invalid charType: ' + charType; + }; + + // Position this menu. + var targetHealthIcon:Null<HealthIcon> = switch (charType) + { + case BF: state.healthIconBF; + case DAD: state.healthIconDad; + default: null; + }; + + if (lockPosition && targetHealthIcon != null) + { + var healthIconBottomCenter:FlxPoint = new FlxPoint(targetHealthIcon.x + targetHealthIcon.width / 2, targetHealthIcon.y + targetHealthIcon.height); + + this.x = healthIconBottomCenter.x - this.width / 2; + this.y = healthIconBottomCenter.y; + } + else + { + this.x = Screen.instance.currentMouseX; + this.y = Screen.instance.currentMouseY; + } + + var charGrid = new Grid(); + charGrid.columns = 5; + charGrid.width = 100; + charSelectScroll.addComponent(charGrid); + + var charIds:Array<String> = CharacterDataParser.listCharacterIds(); + charIds.sort(SortUtil.alphabetically); + + var defaultText:String = '(choose a character)'; + + for (charIndex => charId in charIds) + { + var charData:CharacterData = CharacterDataParser.fetchCharacterData(charId); + + var charButton = new haxe.ui.components.Button(); + charButton.width = 70; + charButton.height = 70; + charButton.padding = 8; + charButton.iconPosition = "top"; + + if (charId == currentCharId) + { + // Scroll to the character if it is already selected. + charSelectScroll.hscrollPos = Math.floor(charIndex / 5) * 80; + charButton.selected = true; + + defaultText = '${charData.name} [${charId}]'; + } + + var LIMIT = 6; + charButton.icon = CharacterDataParser.getCharPixelIconAsset(charId); + charButton.text = charData.name.length > LIMIT ? '${charData.name.substr(0, LIMIT)}.' : '${charData.name}'; + + charButton.onClick = _ -> { + switch (charType) + { + case BF: state.currentSongMetadata.playData.characters.player = charId; + case GF: state.currentSongMetadata.playData.characters.girlfriend = charId; + case DAD: state.currentSongMetadata.playData.characters.opponent = charId; + default: throw 'Invalid charType: ' + charType; + }; + + state.healthIconsDirty = true; + state.refreshToolbox(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); + }; + + charButton.onMouseOver = _ -> { + charIconName.text = '${charData.name} [${charId}]'; + }; + charButton.onMouseOut = _ -> { + charIconName.text = defaultText; + }; + charGrid.addComponent(charButton); + } + + charIconName.text = defaultText; + } + + public static function build(state2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false):ChartEditorCharacterIconSelectorMenu + { + var menu = new ChartEditorCharacterIconSelectorMenu(state2, charType, lockPosition); + + Screen.instance.addComponent(menu); + + return menu; + } +} diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx index 49d5593b0..597f3fb2c 100644 --- a/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx @@ -11,6 +11,7 @@ import haxe.ui.containers.dialogs.Dialogs; import haxe.ui.notifications.NotificationManager; import haxe.ui.notifications.NotificationType; +// @:nullSafety // TODO: Fix null safety when used with HaxeUI build macros. @:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/dialogs/upload-chart.xml")) class ChartEditorUploadChartDialog extends ChartEditorBaseDialog { diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx index 46b4b5dc4..666b3656c 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx @@ -16,6 +16,7 @@ import funkin.play.song.Song; import funkin.play.stage.StageData; import funkin.ui.debug.charting.dialogs.ChartEditorAboutDialog; import funkin.ui.debug.charting.dialogs.ChartEditorBaseDialog.DialogDropTarget; +import funkin.ui.debug.charting.dialogs.ChartEditorCharacterIconSelectorMenu; import funkin.ui.debug.charting.dialogs.ChartEditorUploadChartDialog; import funkin.ui.debug.charting.dialogs.ChartEditorWelcomeDialog; import funkin.ui.debug.charting.util.ChartEditorDropdowns; @@ -39,6 +40,7 @@ import haxe.ui.containers.dialogs.Dialog; import haxe.ui.containers.dialogs.Dialog.DialogButton; import haxe.ui.containers.dialogs.Dialogs; import haxe.ui.containers.Form; +import haxe.ui.containers.menus.Menu; import haxe.ui.containers.VBox; import haxe.ui.core.Component; import haxe.ui.events.UIEvent; @@ -286,6 +288,15 @@ class ChartEditorDialogHandler }; } + public static function openCharacterDropdown(state:ChartEditorState, charType:CharacterType, lockPosition:Bool = false):Null<Menu> + { + var menu = ChartEditorCharacterIconSelectorMenu.build(state, charType, lockPosition); + + menu.zIndex = 1000; + + return menu; + } + public static function openCreateSongWizardBasicOnly(state:ChartEditorState, closable:Bool):Void { // Step 1. Song Metadata diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx index 1726fe4a2..0c8d6a205 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx @@ -99,7 +99,7 @@ class ChartEditorImportExportHandler state.switchToCurrentInstrumental(); state.postLoadInstrumental(); - state.refreshMetadataToolbox(); + state.refreshToolbox(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); state.success('Success', 'Loaded song (${rawSongMetadata[0].songName})'); } diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx index 5834de2ee..2e6e28598 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx @@ -11,7 +11,6 @@ import funkin.play.character.BaseCharacter.CharacterType; import funkin.play.event.SongEvent; import funkin.data.event.SongEventData; import funkin.data.song.SongData.SongTimeChange; -import funkin.ui.debug.charting.commands.ChangeStartingBPMCommand; import funkin.play.character.BaseCharacter.CharacterType; import funkin.play.character.CharacterData; import funkin.play.character.CharacterData.CharacterDataParser; @@ -35,6 +34,8 @@ import haxe.ui.containers.Box; import haxe.ui.containers.dialogs.CollapsibleDialog; import haxe.ui.containers.dialogs.Dialog.DialogButton; import haxe.ui.containers.dialogs.Dialog.DialogEvent; +import funkin.ui.debug.charting.toolboxes.ChartEditorBaseToolbox; +import funkin.ui.debug.charting.toolboxes.ChartEditorMetadataToolbox; import haxe.ui.containers.Frame; import haxe.ui.containers.Grid; import haxe.ui.containers.TreeView; @@ -83,7 +84,8 @@ class ChartEditorToolboxHandler case ChartEditorState.CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT: onShowToolboxDifficulty(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT: - onShowToolboxMetadata(state, toolbox); + // TODO: Fix this. + cast(toolbox, ChartEditorBaseToolbox).refresh(); case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT: onShowToolboxPlayerPreview(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT: @@ -136,6 +138,22 @@ class ChartEditorToolboxHandler } } + public static function refreshToolbox(state:ChartEditorState, id:String):Void + { + var toolbox:Null<ChartEditorBaseToolbox> = cast state.activeToolboxes.get(id); + + if (toolbox == null) return; + + if (toolbox != null) + { + toolbox.refresh(); + } + else + { + trace('ChartEditorToolboxHandler.refreshToolbox() - Could not retrieve toolbox: $id'); + } + } + public static function rememberOpenToolboxes(state:ChartEditorState):Void {} public static function openRememberedToolboxes(state:ChartEditorState):Void {} @@ -205,7 +223,19 @@ class ChartEditorToolboxHandler * @param id The asset ID of the toolbox layout. * @return The toolbox. */ - public static function getToolbox(state:ChartEditorState, id:String):Null<CollapsibleDialog> + public static function getToolbox_OLD(state:ChartEditorState, id:String):Null<CollapsibleDialog> + { + var toolbox:Null<CollapsibleDialog> = state.activeToolboxes.get(id); + + // Initialize the toolbox without showing it. + if (toolbox == null) toolbox = initToolbox(state, id); + + if (toolbox == null) throw 'ChartEditorToolboxHandler.getToolbox_OLD() - Could not retrieve or build toolbox: $id'; + + return toolbox; + } + + public static function getToolbox(state:ChartEditorState, id:String):Null<ChartEditorBaseToolbox> { var toolbox:Null<CollapsibleDialog> = state.activeToolboxes.get(id); @@ -214,7 +244,7 @@ class ChartEditorToolboxHandler if (toolbox == null) throw 'ChartEditorToolboxHandler.getToolbox() - Could not retrieve or build toolbox: $id'; - return toolbox; + return cast toolbox; } static function buildToolboxNoteDataLayout(state:ChartEditorState):Null<CollapsibleDialog> @@ -505,180 +535,15 @@ class ChartEditorToolboxHandler static function onHideToolboxDifficulty(state:ChartEditorState, toolbox:CollapsibleDialog):Void {} - static function buildToolboxMetadataLayout(state:ChartEditorState):Null<CollapsibleDialog> + static function buildToolboxMetadataLayout(state:ChartEditorState):Null<ChartEditorBaseToolbox> { - var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT); + var toolbox:ChartEditorBaseToolbox = ChartEditorMetadataToolbox.build(state); if (toolbox == null) return null; - // Starting position. - toolbox.x = 150; - toolbox.y = 250; - - toolbox.onDialogClosed = function(event:UIEvent) { - state.menubarItemToggleToolboxMetadata.selected = false; - } - - var inputSongName:Null<TextField> = toolbox.findComponent('inputSongName', TextField); - if (inputSongName == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputSongName component.'; - inputSongName.onChange = function(event:UIEvent) { - var valid:Bool = event.target.text != null && event.target.text != ''; - - if (valid) - { - inputSongName.removeClass('invalid-value'); - state.currentSongMetadata.songName = event.target.text; - } - else - { - state.currentSongMetadata.songName = ''; - } - }; - inputSongName.value = state.currentSongMetadata.songName; - - var inputSongArtist:Null<TextField> = toolbox.findComponent('inputSongArtist', TextField); - if (inputSongArtist == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputSongArtist component.'; - inputSongArtist.onChange = function(event:UIEvent) { - var valid:Bool = event.target.text != null && event.target.text != ''; - - if (valid) - { - inputSongArtist.removeClass('invalid-value'); - state.currentSongMetadata.artist = event.target.text; - } - else - { - state.currentSongMetadata.artist = ''; - } - }; - inputSongArtist.value = state.currentSongMetadata.artist; - - var inputStage:Null<DropDown> = toolbox.findComponent('inputStage', DropDown); - if (inputStage == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputStage component.'; - inputStage.onChange = function(event:UIEvent) { - var valid:Bool = event.data != null && event.data.id != null; - - if (valid) - { - state.currentSongMetadata.playData.stage = event.data.id; - } - }; - var startingValueStage = ChartEditorDropdowns.populateDropdownWithStages(inputStage, state.currentSongMetadata.playData.stage); - inputStage.value = startingValueStage; - - var inputNoteStyle:Null<DropDown> = toolbox.findComponent('inputNoteStyle', DropDown); - if (inputNoteStyle == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputNoteStyle component.'; - inputNoteStyle.onChange = function(event:UIEvent) { - if (event.data?.id == null) return; - state.currentSongNoteStyle = event.data.id; - }; - inputNoteStyle.value = state.currentSongNoteStyle; - - // By using this flag, we prevent the dropdown value from changing while it is being populated. - - var inputCharacterPlayer:Null<DropDown> = toolbox.findComponent('inputCharacterPlayer', DropDown); - if (inputCharacterPlayer == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterPlayer component.'; - inputCharacterPlayer.onChange = function(event:UIEvent) { - if (event.data?.id == null) return; - state.currentSongMetadata.playData.characters.player = event.data.id; - }; - var startingValuePlayer = ChartEditorDropdowns.populateDropdownWithCharacters(inputCharacterPlayer, CharacterType.BF, - state.currentSongMetadata.playData.characters.player); - inputCharacterPlayer.value = startingValuePlayer; - - var inputCharacterOpponent:Null<DropDown> = toolbox.findComponent('inputCharacterOpponent', DropDown); - if (inputCharacterOpponent == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterOpponent component.'; - inputCharacterOpponent.onChange = function(event:UIEvent) { - if (event.data?.id == null) return; - state.currentSongMetadata.playData.characters.opponent = event.data.id; - }; - var startingValueOpponent = ChartEditorDropdowns.populateDropdownWithCharacters(inputCharacterOpponent, CharacterType.DAD, - state.currentSongMetadata.playData.characters.opponent); - inputCharacterOpponent.value = startingValueOpponent; - - var inputCharacterGirlfriend:Null<DropDown> = toolbox.findComponent('inputCharacterGirlfriend', DropDown); - if (inputCharacterGirlfriend == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterGirlfriend component.'; - inputCharacterGirlfriend.onChange = function(event:UIEvent) { - if (event.data?.id == null) return; - state.currentSongMetadata.playData.characters.girlfriend = event.data.id == "none" ? "" : event.data.id; - }; - var startingValueGirlfriend = ChartEditorDropdowns.populateDropdownWithCharacters(inputCharacterGirlfriend, CharacterType.GF, - state.currentSongMetadata.playData.characters.girlfriend); - inputCharacterGirlfriend.value = startingValueGirlfriend; - - var inputBPM:Null<NumberStepper> = toolbox.findComponent('inputBPM', NumberStepper); - if (inputBPM == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputBPM component.'; - inputBPM.onChange = function(event:UIEvent) { - if (event.value == null || event.value <= 0) return; - - // Use a command so we can undo/redo this action. - var startingBPM = state.currentSongMetadata.timeChanges[0].bpm; - if (event.value != startingBPM) - { - state.performCommand(new ChangeStartingBPMCommand(event.value)); - } - }; - inputBPM.value = state.currentSongMetadata.timeChanges[0].bpm; - - var inputOffsetInst:Null<NumberStepper> = toolbox.findComponent('inputOffsetInst', NumberStepper); - if (inputOffsetInst == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputOffsetInst component.'; - inputOffsetInst.onChange = function(event:UIEvent) { - if (event.value == null) return; - - state.currentInstrumentalOffset = event.value; - Conductor.instrumentalOffset = event.value; - // Update song length. - state.songLengthInMs = (state.audioInstTrack?.length ?? 1000.0) + Conductor.instrumentalOffset; - }; - inputOffsetInst.value = state.currentInstrumentalOffset; - - var inputOffsetVocal:Null<NumberStepper> = toolbox.findComponent('inputOffsetVocal', NumberStepper); - if (inputOffsetVocal == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputOffsetVocal component.'; - inputOffsetVocal.onChange = function(event:UIEvent) { - if (event.value == null) return; - - state.currentSongMetadata.offsets.setVocalOffset(state.currentSongMetadata.playData.characters.player, event.value); - }; - inputOffsetVocal.value = state.currentSongMetadata.offsets.getVocalOffset(state.currentSongMetadata.playData.characters.player); - - var labelScrollSpeed:Null<Label> = toolbox.findComponent('labelScrollSpeed', Label); - if (labelScrollSpeed == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find labelScrollSpeed component.'; - - var inputScrollSpeed:Null<Slider> = toolbox.findComponent('inputScrollSpeed', Slider); - if (inputScrollSpeed == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputScrollSpeed component.'; - inputScrollSpeed.onChange = function(event:UIEvent) { - var valid:Bool = event.target.value != null && event.target.value > 0; - - if (valid) - { - inputScrollSpeed.removeClass('invalid-value'); - state.currentSongChartScrollSpeed = event.target.value; - } - else - { - state.currentSongChartScrollSpeed = 1.0; - } - labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x'; - }; - inputScrollSpeed.value = state.currentSongChartScrollSpeed; - labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x'; - - var frameVariation:Null<Frame> = toolbox.findComponent('frameVariation', Frame); - if (frameVariation == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find frameVariation component.'; - frameVariation.text = 'Variation: ${state.selectedVariation.toTitleCase()}'; - - var frameDifficulty:Null<Frame> = toolbox.findComponent('frameDifficulty', Frame); - if (frameDifficulty == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find frameDifficulty component.'; - frameDifficulty.text = 'Difficulty: ${state.selectedDifficulty.toTitleCase()}'; - return toolbox; } - static function onShowToolboxMetadata(state:ChartEditorState, toolbox:CollapsibleDialog):Void - { - state.refreshMetadataToolbox(); - } - static function onHideToolboxMetadata(state:ChartEditorState, toolbox:CollapsibleDialog):Void {} static function buildToolboxPlayerPreviewLayout(state:ChartEditorState):Null<CollapsibleDialog> diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorBaseToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorBaseToolbox.hx new file mode 100644 index 000000000..c4c532205 --- /dev/null +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorBaseToolbox.hx @@ -0,0 +1,28 @@ +package funkin.ui.debug.charting.toolboxes; + +import haxe.ui.containers.dialogs.Dialog; +import haxe.ui.containers.dialogs.CollapsibleDialog; +import haxe.ui.containers.dialogs.Dialog.DialogEvent; +import haxe.ui.core.Component; + +/** + * The base class for the Toolboxes (manipulatable, arrangeable control windows) in the Chart Editor. + */ +// @:nullSafety // TODO: Fix null safety when used with HaxeUI build macros. +@:access(funkin.ui.debug.charting.ChartEditorState) +class ChartEditorBaseToolbox extends CollapsibleDialog +{ + var state:ChartEditorState; + + private function new(state:ChartEditorState) + { + super(); + + this.state = state; + } + + /** + * Override to implement this. + */ + public function refresh() {} +} diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx new file mode 100644 index 000000000..e0ee4aca3 --- /dev/null +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx @@ -0,0 +1,203 @@ +package funkin.ui.debug.charting.toolboxes; + +import funkin.play.character.BaseCharacter.CharacterType; +import funkin.play.character.CharacterData; +import funkin.play.stage.StageData; +import funkin.ui.debug.charting.commands.ChangeStartingBPMCommand; +import funkin.ui.debug.charting.util.ChartEditorDropdowns; +import haxe.ui.components.Button; +import haxe.ui.components.CheckBox; +import haxe.ui.components.DropDown; +import haxe.ui.components.HorizontalSlider; +import haxe.ui.components.Label; +import haxe.ui.components.NumberStepper; +import haxe.ui.components.Slider; +import haxe.ui.components.TextField; +import haxe.ui.containers.Box; +import haxe.ui.containers.Frame; +import haxe.ui.events.UIEvent; + +/** + * The toolbox which allows modifying information like Song Title, Scroll Speed, Characters/Stages, and starting BPM. + */ +// @:nullSafety // TODO: Fix null safety when used with HaxeUI build macros. +@:access(funkin.ui.debug.charting.ChartEditorState) +@:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/toolboxes/metadata.xml")) +class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox +{ + var inputSongName:TextField; + var inputSongArtist:TextField; + var inputStage:DropDown; + var inputNoteStyle:DropDown; + var buttonCharacterPlayer:Button; + var buttonCharacterGirlfriend:Button; + var buttonCharacterOpponent:Button; + var inputBPM:NumberStepper; + var inputOffsetInst:NumberStepper; + var inputOffsetVocal:NumberStepper; + var labelScrollSpeed:Label; + var inputScrollSpeed:Slider; + var frameVariation:Frame; + var frameDifficulty:Frame; + + public function new(state2:ChartEditorState) + { + super(state2); + + initialize(); + + this.onDialogClosed = onClose; + } + + function onClose(event:UIEvent) + { + state.menubarItemToggleToolboxMetadata.selected = false; + } + + function initialize():Void + { + // Starting position. + // TODO: Save and load this. + this.x = 150; + this.y = 250; + + inputSongName.onChange = function(event:UIEvent) { + var valid:Bool = event.target.text != null && event.target.text != ''; + + if (valid) + { + inputSongName.removeClass('invalid-value'); + state.currentSongMetadata.songName = event.target.text; + } + else + { + state.currentSongMetadata.songName = ''; + } + }; + + inputSongArtist.onChange = function(event:UIEvent) { + var valid:Bool = event.target.text != null && event.target.text != ''; + + if (valid) + { + inputSongArtist.removeClass('invalid-value'); + state.currentSongMetadata.artist = event.target.text; + } + else + { + state.currentSongMetadata.artist = ''; + } + }; + + inputStage.onChange = function(event:UIEvent) { + var valid:Bool = event.data != null && event.data.id != null; + + if (valid) + { + state.currentSongMetadata.playData.stage = event.data.id; + } + }; + var startingValueStage = ChartEditorDropdowns.populateDropdownWithStages(inputStage, state.currentSongMetadata.playData.stage); + inputStage.value = startingValueStage; + + inputNoteStyle.onChange = function(event:UIEvent) { + if (event.data?.id == null) return; + state.currentSongNoteStyle = event.data.id; + }; + + inputBPM.onChange = function(event:UIEvent) { + if (event.value == null || event.value <= 0) return; + + // Use a command so we can undo/redo this action. + var startingBPM = state.currentSongMetadata.timeChanges[0].bpm; + if (event.value != startingBPM) + { + state.performCommand(new ChangeStartingBPMCommand(event.value)); + } + }; + + inputOffsetInst.onChange = function(event:UIEvent) { + if (event.value == null) return; + + state.currentInstrumentalOffset = event.value; + Conductor.instrumentalOffset = event.value; + // Update song length. + state.songLengthInMs = (state.audioInstTrack?.length ?? 1000.0) + Conductor.instrumentalOffset; + }; + + inputOffsetVocal.onChange = function(event:UIEvent) { + if (event.value == null) return; + + state.currentSongMetadata.offsets.setVocalOffset(state.currentSongMetadata.playData.characters.player, event.value); + }; + inputScrollSpeed.onChange = function(event:UIEvent) { + var valid:Bool = event.target.value != null && event.target.value > 0; + + if (valid) + { + inputScrollSpeed.removeClass('invalid-value'); + state.currentSongChartScrollSpeed = event.target.value; + } + else + { + state.currentSongChartScrollSpeed = 1.0; + } + labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x'; + }; + + buttonCharacterOpponent.onClick = function(_) { + state.openCharacterDropdown(CharacterType.DAD, false); + }; + + buttonCharacterGirlfriend.onClick = function(_) { + state.openCharacterDropdown(CharacterType.GF, false); + }; + + buttonCharacterPlayer.onClick = function(_) { + state.openCharacterDropdown(CharacterType.BF, false); + }; + + refresh(); + } + + public override function refresh():Void + { + inputSongName.value = state.currentSongMetadata.songName; + inputSongArtist.value = state.currentSongMetadata.artist; + inputStage.value = state.currentSongMetadata.playData.stage; + inputNoteStyle.value = state.currentSongMetadata.playData.noteStyle; + inputBPM.value = state.currentSongMetadata.timeChanges[0].bpm; + inputScrollSpeed.value = state.currentSongChartScrollSpeed; + labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x'; + frameVariation.text = 'Variation: ${state.selectedVariation.toTitleCase()}'; + frameDifficulty.text = 'Difficulty: ${state.selectedDifficulty.toTitleCase()}'; + + var stageId:String = state.currentSongMetadata.playData.stage; + var stageData:Null<StageData> = StageDataParser.parseStageData(stageId); + if (inputStage != null) + { + inputStage.value = (stageData != null) ? + {id: stageId, text: stageData.name} : + {id: "mainStage", text: "Main Stage"}; + } + + var LIMIT = 6; + + var charDataOpponent:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.opponent); + buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.opponent); + buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}'; + + var charDataGirlfriend:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.girlfriend); + buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.girlfriend); + buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}'; + + var charDataPlayer:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.player); + buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.player); + buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}'; + } + + public static function build(state:ChartEditorState):ChartEditorMetadataToolbox + { + return new ChartEditorMetadataToolbox(state); + } +} From b09ed369e8401cf4b81365f09082b17418d32954 Mon Sep 17 00:00:00 2001 From: Cameron Taylor <cameron.taylor.ninja@gmail.com> Date: Wed, 13 Dec 2023 09:20:15 -0500 Subject: [PATCH 7/8] f --- .../funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx index e3d6fd13a..3de67b826 100644 --- a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx @@ -84,7 +84,7 @@ class ChartEditorBaseDialog extends Dialog var builder = new AnimationBuilder(_overlay, OVERLAY_EASE_DURATION, "linear"); builder.setPosition(0, "opacity", 0, true); // 0% absolute - builder.setPosition(100, "opacity", 0.80, true); + builder.setPosition(100, "opacity", 1, true); trace('Fading in dialog overlay...'); builder.play(); From 4193cd4ee2f38162a49dffbb20c46052a1fd96c0 Mon Sep 17 00:00:00 2001 From: Cameron Taylor <cameron.taylor.ninja@gmail.com> Date: Wed, 13 Dec 2023 18:24:55 -0500 Subject: [PATCH 8/8] proper dialog fading --- hmm.json | 4 ++-- .../ui/debug/charting/ChartEditorState.hx | 2 +- .../charting/dialogs/ChartEditorBaseDialog.hx | 23 ++++++++++++++----- .../ChartEditorNotificationHandler.hx | 14 ++++++----- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/hmm.json b/hmm.json index 0f06acaa7..a10eed1a6 100644 --- a/hmm.json +++ b/hmm.json @@ -49,14 +49,14 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "5d4ac180f85b39e72624f4b8d17925d91ebe4278", + "ref": "032192e849cdb7d1070c0a3241c58ee555ffaccc", "url": "https://github.com/haxeui/haxeui-core" }, { "name": "haxeui-flixel", "type": "git", "dir": null, - "ref": "89a4cf621e5c204922f7a12fbde5d1d84f8b47f5", + "ref": "d90758b229d05206400df867d333c79d9fdbd478", "url": "https://github.com/haxeui/haxeui-flixel" }, { diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 9a2bfe63c..3696369d4 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2643,7 +2643,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState * Open the backups folder in the file explorer. * Don't call this on HTML5. */ - function openBackupsFolder():Void + function openBackupsFolder(?_):Void { #if sys // TODO: Is there a way to open a folder and highlight a file in it? diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx index 3de67b826..6f76e543e 100644 --- a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx @@ -29,6 +29,12 @@ class ChartEditorBaseDialog extends Dialog this.onDialogClosed = event -> onClose(event); } + public override function showDialog(modal:Bool = true):Void + { + super.showDialog(modal); + fadeInComponent(this, 1); + } + private override function onReady():Void { _overlay.opacity = 0; @@ -65,8 +71,8 @@ class ChartEditorBaseDialog extends Dialog this.closable = params.closable ?? false; } - static final OVERLAY_EASE_DURATION:Float = 5.0; - static final OVERLAY_EASE_TYPE:String = "linear"; + static final OVERLAY_EASE_DURATION:Float = 0.2; + static final OVERLAY_EASE_TYPE:String = "easeOut"; function fadeInDialogOverlay():Void { @@ -82,11 +88,16 @@ class ChartEditorBaseDialog extends Dialog return; } - var builder = new AnimationBuilder(_overlay, OVERLAY_EASE_DURATION, "linear"); - builder.setPosition(0, "opacity", 0, true); // 0% absolute - builder.setPosition(100, "opacity", 1, true); + fadeInComponent(_overlay, 0.5); + } - trace('Fading in dialog overlay...'); + function fadeInComponent(component:Component, fadeTo:Float = 1):Void + { + var builder = new AnimationBuilder(component, OVERLAY_EASE_DURATION, OVERLAY_EASE_TYPE); + builder.setPosition(0, "opacity", 0, true); // 0% absolute + builder.setPosition(100, "opacity", fadeTo, true); + + trace('Fading in dialog component...'); builder.play(); } } diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorNotificationHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorNotificationHandler.hx index 14d95347b..10da77694 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorNotificationHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorNotificationHandler.hx @@ -5,6 +5,7 @@ import haxe.ui.containers.HBox; import haxe.ui.notifications.Notification; import haxe.ui.notifications.NotificationManager; import haxe.ui.notifications.NotificationType; +import haxe.ui.notifications.NotificationData.NotificationActionData; class ChartEditorNotificationHandler { @@ -77,7 +78,7 @@ class ChartEditorNotificationHandler * @param actions The actions to add to the notification. * @return The notification that was sent. */ - public static function infoWithActions(state:ChartEditorState, title:String, body:String, actions:Array<NotificationAction>):Notification + public static function infoWithActions(state:ChartEditorState, title:String, body:String, actions:Array<NotificationActionData>):Notification { return sendNotification(state, title, body, NotificationType.Info, actions); } @@ -101,7 +102,8 @@ class ChartEditorNotificationHandler NotificationManager.instance.removeNotification(notif); } - static function sendNotification(state:ChartEditorState, title:String, body:String, ?type:NotificationType, ?actions:Array<NotificationAction>):Notification + static function sendNotification(state:ChartEditorState, title:String, body:String, ?type:NotificationType, + ?actions:Array<NotificationActionData>):Notification { var actionNames:Array<String> = actions == null ? [] : actions.map(action -> action.text); @@ -111,10 +113,10 @@ class ChartEditorNotificationHandler body: body, type: type ?? NotificationType.Default, expiryMs: Constants.NOTIFICATION_DISMISS_TIME, - actions: actionNames + actions: actions }); - if (actionNames.length > 0) + if (actions != null && actions.length > 0) { // TODO: Tell Ian that this is REALLY dumb. var actionsContainer:HBox = notif.findComponent('actionsContainer', HBox); @@ -122,13 +124,13 @@ class ChartEditorNotificationHandler if (Std.isOfType(component, Button)) { var button:Button = cast component; - var action:Null<NotificationAction> = actions.find(action -> action.text == button.text); + var action:Null<NotificationActionData> = actions.find(action -> action.text == button.text); if (action != null && action.callback != null) { button.onClick = function(_) { // Don't allow actions to be clicked while the playtest is open. if (state.subState != null) return; - action.callback(); + action.callback(action); }; } }