From 796e1fcbabd8703da8686bc2509ae52401978c38 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Fri, 8 Dec 2023 20:21:55 -0500
Subject: [PATCH 1/4] note highlight preview

---
 .../ui/debug/charting/ChartEditorState.hx     | 18 ++++++++++++++-
 .../components/ChartEditorNotePreview.hx      | 23 +++++++++++++------
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index 66effc775..02994bf71 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -720,7 +720,23 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
   /**
    * The notes which are currently in the user's selection.
    */
-  var currentNoteSelection:Array<SongNoteData> = [];
+  var currentNoteSelection(default, set):Array<SongNoteData> = [];
+
+  function set_currentNoteSelection(value:Array<SongNoteData>):Array<SongNoteData>
+  {
+    currentNoteSelection = value;
+
+    if (currentNoteSelection.length > 0)
+    {
+      notePreview.addNotes(currentNoteSelection, Std.int(songLengthInMs), true);
+    }
+    else
+    {
+      notePreviewDirty = true;
+    }
+
+    return currentNoteSelection;
+  }
 
   /**
    * The events which are currently in the user's selection.
diff --git a/source/funkin/ui/debug/charting/components/ChartEditorNotePreview.hx b/source/funkin/ui/debug/charting/components/ChartEditorNotePreview.hx
index 7decc8988..09c99531d 100644
--- a/source/funkin/ui/debug/charting/components/ChartEditorNotePreview.hx
+++ b/source/funkin/ui/debug/charting/components/ChartEditorNotePreview.hx
@@ -26,6 +26,7 @@ class ChartEditorNotePreview extends FlxSprite
   static final UP_COLOR:FlxColor = 0xFF00CC00;
   static final RIGHT_COLOR:FlxColor = 0xFFCC1111;
   static final EVENT_COLOR:FlxColor = 0xFF111111;
+  static final SELECTED_COLOR:FlxColor = 0xFFFFFF00;
 
   var previewHeight:Int;
 
@@ -57,11 +58,11 @@ class ChartEditorNotePreview extends FlxSprite
    * @param note The data for the note.
    * @param songLengthInMs The total length of the song in milliseconds.
    */
-  public function addNote(note:SongNoteData, songLengthInMs:Int):Void
+  public function addNote(note:SongNoteData, songLengthInMs:Int, ?isSelection:Bool = false):Void
   {
     var noteDir:Int = note.getDirection();
     var mustHit:Bool = note.getStrumlineIndex() == 0;
-    drawNote(noteDir, mustHit, Std.int(note.time), songLengthInMs);
+    drawNote(noteDir, mustHit, Std.int(note.time), songLengthInMs, isSelection);
   }
 
   /**
@@ -79,11 +80,11 @@ class ChartEditorNotePreview extends FlxSprite
    * @param notes The data for the notes.
    * @param songLengthInMs The total length of the song in milliseconds.
    */
-  public function addNotes(notes:Array<SongNoteData>, songLengthInMs:Int):Void
+  public function addNotes(notes:Array<SongNoteData>, songLengthInMs:Int, ?isSelection:Bool = false):Void
   {
     for (note in notes)
     {
-      addNote(note, songLengthInMs);
+      addNote(note, songLengthInMs, isSelection);
     }
   }
 
@@ -106,8 +107,9 @@ class ChartEditorNotePreview extends FlxSprite
    * @param mustHit False if opponent, true if player.
    * @param strumTimeInMs Time in milliseconds to strum the note.
    * @param songLengthInMs Length of the song in milliseconds.
+   * @param isSelection If current note is selected note, which then it's forced to be green
    */
-  function drawNote(dir:Int, mustHit:Bool, strumTimeInMs:Int, songLengthInMs:Int):Void
+  public function drawNote(dir:Int, mustHit:Bool, strumTimeInMs:Int, songLengthInMs:Int, ?isSelection:Bool = false):Void
   {
     var color:FlxColor = switch (dir)
     {
@@ -118,13 +120,20 @@ class ChartEditorNotePreview extends FlxSprite
       default: EVENT_COLOR;
     };
 
+    var noteHeight:Int = NOTE_HEIGHT;
+
+    if (isSelection != null && isSelection)
+    {
+      color = SELECTED_COLOR;
+      noteHeight += 1;
+    }
+
     var noteX:Float = NOTE_WIDTH * dir;
     if (mustHit) noteX += NOTE_WIDTH * 4;
     if (dir == -1) noteX = NOTE_WIDTH * 8;
 
     var noteY:Float = FlxMath.remapToRange(strumTimeInMs, 0, songLengthInMs, 0, previewHeight);
-
-    drawRect(noteX, noteY, NOTE_WIDTH, NOTE_HEIGHT, color);
+    drawRect(noteX, noteY, NOTE_WIDTH, noteHeight, color);
   }
 
   function eraseNote(dir:Int, mustHit:Bool, strumTimeInMs:Int, songLengthInMs:Int):Void

From 6f141e5f52810ae1dcc062ba33d27a31d200cc6c Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Fri, 8 Dec 2023 22:28:34 -0500
Subject: [PATCH 2/4] copy text popup

---
 .../ui/debug/charting/ChartEditorState.hx     | 29 ++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index 66effc775..b52ab10bc 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -114,6 +114,7 @@ import haxe.ui.events.UIEvent;
 import haxe.ui.events.UIEvent;
 import haxe.ui.focus.FocusManager;
 import openfl.display.BitmapData;
+import flixel.text.FlxText;
 
 using Lambda;
 
@@ -1618,6 +1619,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
    */
   var healthIconBF:Null<HealthIcon> = null;
 
+  /**
+   * The text that pop's up when copying something
+   */
+  var txtCopyNotif:Null<FlxText> = null;
+
   /**
    * The purple background sprite.
    */
@@ -2273,6 +2279,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
 
     add(playbarHeadLayout);
 
+    txtCopyNotif = new FlxText(0, 0, 0, '', 24);
+    txtCopyNotif.setBorderStyle(OUTLINE, 0xFF074809, 1);
+    txtCopyNotif.color = 0xFF52FF77;
+    txtCopyNotif.zIndex = 120;
+    add(txtCopyNotif);
+
     if (!Preferences.debugDisplay) menubar.paddingLeft = null;
 
     this.setupNotifications();
@@ -4444,7 +4456,22 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
     // CTRL + C = Copy
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.C)
     {
-      // Copy selected notes.
+      if (currentNoteSelection.length > 0)
+      {
+        txtCopyNotif.visible = true;
+        txtCopyNotif.text = "Copied " + currentNoteSelection.length + " notes to clipboard";
+        txtCopyNotif.x = FlxG.mouse.x - (txtCopyNotif.width / 2);
+        txtCopyNotif.y = FlxG.mouse.y - 16;
+        FlxTween.tween(txtCopyNotif, {y: txtCopyNotif.y - 32}, 0.5,
+          {
+            type: FlxTween.ONESHOT,
+            ease: FlxEase.quadOut,
+            onComplete: function(_) {
+              txtCopyNotif.visible = false;
+            }
+          });
+      }
+
       // We don't need a command for this since we can't undo it.
       SongDataUtils.writeItemsToClipboard(
         {

From 87c866f662963989c475e8205d37bd9cbb4550d2 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Fri, 8 Dec 2023 22:55:14 -0500
Subject: [PATCH 3/4] copy notifier polish

---
 .../ui/debug/charting/ChartEditorState.hx     | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index b52ab10bc..6686da462 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -4470,6 +4470,32 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
               txtCopyNotif.visible = false;
             }
           });
+
+        for (note in renderedNotes.members)
+        {
+          if (isNoteSelected(note.noteData))
+          {
+            FlxTween.globalManager.cancelTweensOf(note);
+            FlxTween.globalManager.cancelTweensOf(note.scale);
+            note.playNoteAnimation();
+            var prevX:Float = note.scale.x;
+            var prevY:Float = note.scale.y;
+
+            note.scale.x *= 1.2;
+            note.scale.y *= 1.2;
+
+            note.angle = FlxG.random.bool() ? -10 : 10;
+            FlxTween.tween(note, {"angle": 0}, 0.8, {ease: FlxEase.elasticOut});
+
+            FlxTween.tween(note.scale, {"y": prevX, "x": prevY}, 0.7,
+              {
+                ease: FlxEase.elasticOut,
+                onComplete: function(_) {
+                  note.playNoteAnimation();
+                }
+              });
+          }
+        }
       }
 
       // We don't need a command for this since we can't undo it.

From e24c5877a99b20db45c45ceda45476ac853816bc Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Sun, 10 Dec 2023 23:33:08 -0500
Subject: [PATCH 4/4] Some quick fixes to get Mac to build.

---
 .../dialogs/ChartEditorUploadChartDialog.hx   | 51 +++----------------
 .../dialogs/ChartEditorWelcomeDialog.hx       | 21 ++------
 .../ChartEditorNotificationHandler.hx         |  3 +-
 3 files changed, 10 insertions(+), 65 deletions(-)

diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx
index 49d5593b0..ec6a850f9 100644
--- a/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx
+++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx
@@ -113,41 +113,17 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
       var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFCPath(state, path.toString());
       if (result != null)
       {
-        #if !mac
-        NotificationManager.instance.addNotification(
-          {
-            title: 'Success',
-            body: result.length == 0 ? 'Loaded chart (${path.toString()})' : 'Loaded chart (${path.toString()})\n${result.join("\n")}',
-            type: result.length == 0 ? NotificationType.Success : NotificationType.Warning,
-            expiryMs: Constants.NOTIFICATION_DISMISS_TIME
-          });
-        #end
+        state.success('Loaded Chart', result.length == 0 ? 'Loaded chart (${path.toString()})' : 'Loaded chart (${path.toString()})\n${result.join("\n")}');
         this.hideDialog(DialogButton.APPLY);
       }
       else
       {
-        #if !mac
-        NotificationManager.instance.addNotification(
-          {
-            title: 'Failure',
-            body: 'Failed to load chart (${path.toString()})',
-            type: NotificationType.Error,
-            expiryMs: Constants.NOTIFICATION_DISMISS_TIME
-          });
-        #end
+        state.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()})');
       }
     }
     catch (err)
     {
-      #if !mac
-      NotificationManager.instance.addNotification(
-        {
-          title: 'Failure',
-          body: 'Failed to load chart (${path.toString()}): ${err}',
-          type: NotificationType.Error,
-          expiryMs: Constants.NOTIFICATION_DISMISS_TIME
-        });
-      #end
+      state.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()}): ${err}');
     }
   }
 
@@ -165,15 +141,8 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
         var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFC(state, selectedFile.bytes);
         if (result != null)
         {
-          #if !mac
-          NotificationManager.instance.addNotification(
-            {
-              title: 'Success',
-              body: 'Loaded chart (${selectedFile.name})',
-              type: NotificationType.Success,
-              expiryMs: Constants.NOTIFICATION_DISMISS_TIME
-            });
-          #end
+          state.success('Loaded Chart',
+            result.length == 0 ? 'Loaded chart (${selectedFile.name})' : 'Loaded chart (${selectedFile.name})\n${result.join("\n")}');
 
           if (selectedFile.fullPath != null) state.currentWorkingFilePath = selectedFile.fullPath;
           this.hideDialog(DialogButton.APPLY);
@@ -181,15 +150,7 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
       }
       catch (err)
       {
-        #if !mac
-        NotificationManager.instance.addNotification(
-          {
-            title: 'Failure',
-            body: 'Failed to load chart (${selectedFile.name}): ${err}',
-            type: NotificationType.Error,
-            expiryMs: Constants.NOTIFICATION_DISMISS_TIME
-          });
-        #end
+        state.failure('Failed to Load Chart', 'Failed to load chart (${selectedFile.name}): ${err}');
       }
     }
   }
diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx
index 744bf4ac4..2a30c7d9e 100644
--- a/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx
+++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx
@@ -102,27 +102,12 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
       var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFCPath(state, chartPath);
       if (result != null)
       {
-        #if !mac
-        NotificationManager.instance.addNotification(
-          {
-            title: 'Success',
-            body: result.length == 0 ? 'Loaded chart (${chartPath.toString()})' : 'Loaded chart (${chartPath.toString()})\n${result.join("\n")}',
-            type: result.length == 0 ? NotificationType.Success : NotificationType.Warning,
-            expiryMs: Constants.NOTIFICATION_DISMISS_TIME
-          });
-        #end
+        state.success('Loaded Chart',
+          result.length == 0 ? 'Loaded chart (${chartPath.toString()})' : 'Loaded chart (${chartPath.toString()})\n${result.join("\n")}');
       }
       else
       {
-        #if !mac
-        NotificationManager.instance.addNotification(
-          {
-            title: 'Failure',
-            body: 'Failed to load chart (${chartPath.toString()})',
-            type: NotificationType.Error,
-            expiryMs: Constants.NOTIFICATION_DISMISS_TIME
-          });
-        #end
+        state.error('Failed to Load Chart', 'Failed to load chart (${chartPath.toString()})');
       }
     }
 
diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorNotificationHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorNotificationHandler.hx
index 5c340feb7..14d95347b 100644
--- a/source/funkin/ui/debug/charting/handlers/ChartEditorNotificationHandler.hx
+++ b/source/funkin/ui/debug/charting/handlers/ChartEditorNotificationHandler.hx
@@ -103,7 +103,6 @@ class ChartEditorNotificationHandler
 
   static function sendNotification(state:ChartEditorState, title:String, body:String, ?type:NotificationType, ?actions:Array<NotificationAction>):Notification
   {
-    #if !mac
     var actionNames:Array<String> = actions == null ? [] : actions.map(action -> action.text);
 
     var notif = NotificationManager.instance.addNotification(
@@ -138,7 +137,7 @@ class ChartEditorNotificationHandler
     }
 
     return notif;
-    #else
+    #if false
     // TODO: Implement notifications on Mac OS OR... make sure the null is handled properly on mac?
     return null;
     trace('WARNING: Notifications are not supported on Mac OS.');