diff --git a/.gitignore b/.gitignore
index 259123b1..7a1c38d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,5 +8,6 @@ latest/windows/haxe/
.haxelib/
pages/
docs/doc.xml
-mods/Baldi's Basics in Funkin'/
-dev-libs/
\ No newline at end of file
+mods/*
+!mods/readme.txt
+dev-libs/
diff --git a/assets/data/scripts/week6-pause.hx b/assets/data/scripts/week6-pause.hx
index f5fa3394..4eb71349 100644
--- a/assets/data/scripts/week6-pause.hx
+++ b/assets/data/scripts/week6-pause.hx
@@ -92,15 +92,11 @@ function update(elapsed) {
if (!canDoShit) return;
var oldSec = curSelected;
- if (controls.DOWN_P)
- changeSelection(1, false);
- if (controls.UP_P)
- changeSelection(-1);
- if (oldSec != curSelected) {
+ changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
+
+ if (oldSec != curSelected)
FlxG.sound.play(Paths.sound(isThorns ? 'pixel/type' : 'pixel/pixelText'));
- }
-
if (controls.ACCEPT) {
FlxG.sound.play(Paths.sound(isThorns ? 'pixel/ANGRY' : 'pixel/clickText'));
@@ -118,7 +114,7 @@ function update(elapsed) {
}
}
-function changeSelection(change) {
+function changeSelection(change) { // this overrides the function inside of the normal pause btw, so no event gets called - Nex
curSelected += change;
if (curSelected < 0)
diff --git a/libs.xml b/libs.xml
index 0bb13c52..a4b43767 100644
--- a/libs.xml
+++ b/libs.xml
@@ -16,7 +16,7 @@
-
+
diff --git a/source/funkin/backend/scripting/HScript.hx b/source/funkin/backend/scripting/HScript.hx
index 5ecb6299..62a80fe4 100644
--- a/source/funkin/backend/scripting/HScript.hx
+++ b/source/funkin/backend/scripting/HScript.hx
@@ -79,8 +79,10 @@ class HScript extends Script {
var code = Assets.getText(p);
var expr:Expr = null;
try {
- if (code != null && code.trim() != "")
+ if (code != null && code.trim() != "") {
+ parser.line = 1; // fun fact: this is all you need to reuse a parser without issues. all the other vars get reset on parse.
expr = parser.parseString(code, cl.join("/") + "." + hxExt);
+ }
} catch(e:Error) {
_errorHandler(e);
} catch(e) {
diff --git a/source/funkin/backend/system/Main.hx b/source/funkin/backend/system/Main.hx
index b60dee80..9ada0694 100644
--- a/source/funkin/backend/system/Main.hx
+++ b/source/funkin/backend/system/Main.hx
@@ -156,6 +156,9 @@ class Main extends Sprite
FlxG.signals.postStateSwitch.add(onStateSwitchPost);
FlxG.mouse.useSystemCursor = true;
+ #if DARK_MODE_WINDOW
+ if(funkin.backend.utils.NativeAPI.hasVersion("Windows 10")) funkin.backend.utils.NativeAPI.redrawWindowHeader();
+ #end
ModsFolder.init();
#if MOD_SUPPORT
diff --git a/source/funkin/backend/utils/NativeAPI.hx b/source/funkin/backend/utils/NativeAPI.hx
index 45759231..e7623620 100644
--- a/source/funkin/backend/utils/NativeAPI.hx
+++ b/source/funkin/backend/utils/NativeAPI.hx
@@ -3,6 +3,7 @@ package funkin.backend.utils;
import funkin.backend.utils.native.*;
import flixel.util.typeLimit.OneOfTwo;
import flixel.util.typeLimit.OneOfThree;
+import flixel.util.FlxColor;
/**
* Class for functions that talk to a lower level than haxe, such as message boxes, and more.
@@ -84,12 +85,86 @@ class NativeAPI {
#end
}
+ /**
+ * WINDOW COLOR MODE FUNCTIONS.
+ */
+
+ /**
+ * Switch the window's color mode to dark or light mode.
+ */
public static function setDarkMode(title:String, enable:Bool) {
#if windows
+ if(title == null) title = lime.app.Application.current.window.title;
Windows.setDarkMode(title, enable);
#end
}
+ /**
+ * Switch the window's color to any color.
+ *
+ * WARNING: This is exclusive to windows 11 users, unfortunately.
+ *
+ * NOTE: Setting the color to 0x00000000 (FlxColor.TRANSPARENT) will set the border (must have setBorder on) invisible.
+ */
+ public static function setWindowBorderColor(title:String, color:FlxColor, setHeader:Bool = true, setBorder:Bool = true) {
+ #if windows
+ if(title == null) title = lime.app.Application.current.window.title;
+ Windows.setWindowBorderColor(title, [color.red, color.green, color.blue, color.alpha], setHeader, setBorder);
+ #end
+ }
+
+ /**
+ * Resets the window's border color to the default one.
+ *
+ * WARNING: This is exclusive to windows 11 users, unfortunately.
+ **/
+ public static function resetWindowBorderColor(title:String, setHeader:Bool = true, setBorder:Bool = true) {
+ #if windows
+ if(title == null) title = lime.app.Application.current.window.title;
+ Windows.setWindowBorderColor(title, [-1, -1, -1, -1], setHeader, setBorder);
+ #end
+ }
+
+ /**
+ * Switch the window's title text to any color.
+ *
+ * WARNING: This is exclusive to windows 11 users, unfortunately.
+ */
+ public static function setWindowTitleColor(title:String, color:FlxColor) {
+ #if windows
+ if(title == null) title = lime.app.Application.current.window.title;
+ Windows.setWindowTitleColor(title, [color.red, color.green, color.blue, color.alpha]);
+ #end
+ }
+
+ /**
+ * Resets the window's title color to the default one.
+ *
+ * WARNING: This is exclusive to windows 11 users, unfortunately.
+ **/
+ public static function resetWindowTitleColor(title:String) {
+ #if windows
+ if(title == null) title = lime.app.Application.current.window.title;
+ Windows.setWindowTitleColor(title, [-1, -1, -1, -1]);
+ #end
+ }
+
+ /**
+ * Forces the window header to redraw, causes a small visual jitter so use it sparingly.
+ */
+ public static function redrawWindowHeader() {
+ #if windows
+ flixel.FlxG.stage.window.borderless = true;
+ flixel.FlxG.stage.window.borderless = false;
+ #end
+ }
+
+ /**
+ * Can be used to check if your using a specific version of an OS (or if your using a certain OS).
+ */
+ public static function hasVersion(vers:String)
+ return lime.system.System.platformLabel.toLowerCase().indexOf(vers.toLowerCase()) != -1;
+
/**
* Shows a message box
*/
diff --git a/source/funkin/backend/utils/native/Windows.hx b/source/funkin/backend/utils/native/Windows.hx
index a536c75f..8653d2e8 100644
--- a/source/funkin/backend/utils/native/Windows.hx
+++ b/source/funkin/backend/utils/native/Windows.hx
@@ -134,13 +134,57 @@ class Windows {
HWND window = FindWindowA(NULL, title.c_str());
// Look for child windows if top level aint found
if (window == NULL) window = FindWindowExA(GetActiveWindow(), NULL, NULL, title.c_str());
+ // If still not found, try to get the active window
+ if (window == NULL) window = GetActiveWindow();
+ if (window == NULL) return;
- if (window != NULL && S_OK != DwmSetWindowAttribute(window, 19, &darkMode, sizeof(darkMode))) {
+ if (S_OK != DwmSetWindowAttribute(window, 19, &darkMode, sizeof(darkMode))) {
DwmSetWindowAttribute(window, 20, &darkMode, sizeof(darkMode));
}
+ UpdateWindow(window);
')
public static function setDarkMode(title:String, enable:Bool) {}
+ @:functionCode('
+ HWND window = FindWindowA(NULL, title.c_str());
+ if (window == NULL) window = FindWindowExA(GetActiveWindow(), NULL, NULL, title.c_str());
+ if (window == NULL) window = GetActiveWindow();
+ if (window == NULL) return;
+
+ COLORREF finalColor;
+ if(color[0] == -1 && color[1] == -1 && color[2] == -1 && color[3] == -1) { // bad fix, I know :sob:
+ finalColor = 0xFFFFFFFF; // Default border
+ } else if(color[3] == 0) {
+ finalColor = 0xFFFFFFFE; // No border (must have setBorder as true)
+ } else {
+ finalColor = RGB(color[0], color[1], color[2]); // Use your custom color
+ }
+
+ if(setHeader) DwmSetWindowAttribute(window, 35, &finalColor, sizeof(COLORREF));
+ if(setBorder) DwmSetWindowAttribute(window, 34, &finalColor, sizeof(COLORREF));
+
+ UpdateWindow(window);
+ ')
+ public static function setWindowBorderColor(title:String, color:Array, setHeader:Bool = true, setBorder:Bool = true) {}
+
+ @:functionCode('
+ HWND window = FindWindowA(NULL, title.c_str());
+ if (window == NULL) window = FindWindowExA(GetActiveWindow(), NULL, NULL, title.c_str());
+ if (window == NULL) window = GetActiveWindow();
+ if (window == NULL) return;
+
+ COLORREF finalColor;
+ if(color[0] == -1 && color[1] == -1 && color[2] == -1 && color[3] == -1) { // bad fix, I know :sob:
+ finalColor = 0xFFFFFFFF; // Default border
+ } else {
+ finalColor = RGB(color[0], color[1], color[2]); // Use your custom color
+ }
+
+ DwmSetWindowAttribute(window, 36, &finalColor, sizeof(COLORREF));
+ UpdateWindow(window);
+ ')
+ public static function setWindowTitleColor(title:String, color:Array) {}
+
@:functionCode('
// https://stackoverflow.com/questions/15543571/allocconsole-not-displaying-cout
diff --git a/source/funkin/editors/EditorPicker.hx b/source/funkin/editors/EditorPicker.hx
index a6b70d54..ce957733 100644
--- a/source/funkin/editors/EditorPicker.hx
+++ b/source/funkin/editors/EditorPicker.hx
@@ -226,4 +226,4 @@ class EditorPickerOption extends FlxTypedSpriteGroup {
callback();
});
}
-}
\ No newline at end of file
+}
diff --git a/source/funkin/editors/charter/ChartDataScreen.hx b/source/funkin/editors/charter/ChartDataScreen.hx
index bc0762ad..e3e1d9cc 100644
--- a/source/funkin/editors/charter/ChartDataScreen.hx
+++ b/source/funkin/editors/charter/ChartDataScreen.hx
@@ -23,6 +23,7 @@ class ChartDataScreen extends UISubstateWindow {
public override function create() {
FlxG.sound.music.pause();
Charter.instance.vocals.pause();
+ for (strumLine in Charter.instance.strumLines.members) strumLine.vocals.pause();
winTitle = 'Chart Properties';
winWidth = 420; winHeight = 230; // guys look, the funny numbers!
diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx
index 131346ce..99a87ded 100644
--- a/source/funkin/editors/charter/Charter.hx
+++ b/source/funkin/editors/charter/Charter.hx
@@ -332,6 +332,7 @@ class Charter extends UIState {
null,
{
label: "↑ Speed 25%",
+ keybind: [PERIOD],
onSelect: _playback_speed_raise
},
{
@@ -340,6 +341,7 @@ class Charter extends UIState {
},
{
label: "↓ Speed 25%",
+ keybind: [COMMA],
onSelect: _playback_speed_lower
},
null,
@@ -353,6 +355,22 @@ class Charter extends UIState {
keybind: [D],
onSelect: _playback_forward
},
+ {
+ label: "Go to start of section",
+ keybind: [SHIFT, S],
+ onSelect: _playback_section_start
+ },
+ null,
+ {
+ label: "Go back a step",
+ keybind: [W],
+ onSelect: _playback_back_step
+ },
+ {
+ label: "Go forward a step",
+ keybind: [S],
+ onSelect: _playback_forward_step
+ },
null,
{
label: "Metronome",
@@ -1583,6 +1601,18 @@ class Charter extends UIState {
if (FlxG.sound.music.playing) return;
Conductor.songPosition += (Conductor.beatsPerMeasure * __crochet);
}
+ function _playback_section_start(_) {
+ if(FlxG.sound.music.playing) return;
+ Conductor.songPosition = (Conductor.beatsPerMeasure * (60000 / Conductor.bpm)) * curMeasure;
+ }
+ function _playback_back_step(_) {
+ if (FlxG.sound.music.playing) return;
+ Conductor.songPosition -= Conductor.stepCrochet;
+ }
+ function _playback_forward_step(_) {
+ if (FlxG.sound.music.playing) return;
+ Conductor.songPosition += Conductor.stepCrochet;
+ }
function _song_start(_) {
if (FlxG.sound.music.playing) return;
Conductor.songPosition = 0;
diff --git a/source/funkin/editors/charter/CharterEvent.hx b/source/funkin/editors/charter/CharterEvent.hx
index 1a0abe81..c7092527 100644
--- a/source/funkin/editors/charter/CharterEvent.hx
+++ b/source/funkin/editors/charter/CharterEvent.hx
@@ -1,6 +1,7 @@
package funkin.editors.charter;
import flixel.math.FlxPoint;
+import flixel.system.FlxAssets.FlxGraphicAsset;
import funkin.backend.chart.ChartData.ChartEvent;
import funkin.editors.charter.Charter.ICharterSelectable;
import funkin.editors.charter.CharterBackdropGroup.EventBackdrop;
@@ -47,14 +48,34 @@ class CharterEvent extends UISliceSprite implements ICharterSelectable {
private static function generateDefaultIcon(name:String) {
var isBase64:Bool = false;
var path:String = Paths.image('editors/charter/event-icons/$name');
- if (!Assets.exists(path)) path = Paths.image('editors/charter/event-icons/Unknown');
- if (Assets.exists(Paths.pack('events/$name'))) {
- var packimg = Assets.getText(Paths.pack('events/$name')).split('________PACKSEP________')[3];
- if (isBase64 = (packimg != null))
- path = Assets.getText(Paths.pack('events/$name')).split('________PACKSEP________')[3];
+ var defaultPath = Paths.image('editors/charter/event-icons/Unknown');
+ if (!Assets.exists(path)) path = defaultPath;
+
+ var packPath = Paths.pack('events/$name');
+ if (Assets.exists(packPath)) {
+ var packText = Assets.getText(packPath).split('________PACKSEP________');
+ var packImg = packText[3];
+ if(packImg != null && packImg.length > 0) {
+ isBase64 = !packImg.startsWith("assets/");
+ path = packImg;
+ }
}
- var spr = new FlxSprite().loadGraphic(isBase64 ? openfl.display.BitmapData.fromBase64(path.trim(), 'UTF8') : path);
- return spr;
+ path = path.trim();
+
+ var graphic:FlxGraphicAsset = try {
+ isBase64 ? openfl.display.BitmapData.fromBase64(path, 'UTF8') : path;
+ } catch(e:Dynamic) {
+ Logs.trace('Failed to load event icon: ${e.toString()}', ERROR);
+ isBase64 = false;
+ defaultPath;
+ }
+
+ if(!isBase64) {
+ if (!Assets.exists(graphic))
+ graphic = defaultPath;
+ }
+
+ return new FlxSprite().loadGraphic(graphic);
}
public static function generateEventIcon(event:ChartEvent) {
diff --git a/source/funkin/editors/charter/CharterEventScreen.hx b/source/funkin/editors/charter/CharterEventScreen.hx
index f3df422a..d54393d6 100644
--- a/source/funkin/editors/charter/CharterEventScreen.hx
+++ b/source/funkin/editors/charter/CharterEventScreen.hx
@@ -43,6 +43,7 @@ class CharterEventScreen extends UISubstateWindow {
FlxG.sound.music.pause(); // prevent the song from continuing
Charter.instance.vocals.pause();
+ for (strumLine in Charter.instance.strumLines.members) strumLine.vocals.pause();
events = chartEvent.events.copy();
diff --git a/source/funkin/editors/charter/CharterMetaDataScreen.hx b/source/funkin/editors/charter/CharterMetaDataScreen.hx
index 0ab7900c..bdc38f87 100644
--- a/source/funkin/editors/charter/CharterMetaDataScreen.hx
+++ b/source/funkin/editors/charter/CharterMetaDataScreen.hx
@@ -39,6 +39,7 @@ class CharterMetaDataScreen extends UISubstateWindow {
FlxG.sound.music.pause();
Charter.instance.vocals.pause();
+ for (strumLine in Charter.instance.strumLines.members) strumLine.vocals.pause();
function addLabelOn(ui:UISprite, text:String)
add(new UIText(ui.x, ui.y - 24, 0, text));
diff --git a/source/funkin/editors/charter/CharterNoteTypesList.hx b/source/funkin/editors/charter/CharterNoteTypesList.hx
index 50f23a2e..859b32c5 100644
--- a/source/funkin/editors/charter/CharterNoteTypesList.hx
+++ b/source/funkin/editors/charter/CharterNoteTypesList.hx
@@ -13,6 +13,7 @@ class CharterNoteTypesList extends UISubstateWindow {
public override function create() {
FlxG.sound.music.pause();
Charter.instance.vocals.pause();
+ for (strumLine in Charter.instance.strumLines.members) strumLine.vocals.pause();
winTitle = 'Note Types List Editor';
winWidth = 380; winHeight = 390;
diff --git a/source/funkin/editors/charter/CharterStrumlineScreen.hx b/source/funkin/editors/charter/CharterStrumlineScreen.hx
index 6b24b654..d5a1ef00 100644
--- a/source/funkin/editors/charter/CharterStrumlineScreen.hx
+++ b/source/funkin/editors/charter/CharterStrumlineScreen.hx
@@ -51,6 +51,7 @@ class CharterStrumlineScreen extends UISubstateWindow {
FlxG.sound.music.pause();
Charter.instance.vocals.pause();
+ for (strumLine in Charter.instance.strumLines.members) strumLine.vocals.pause();
super.create();
diff --git a/source/funkin/editors/ui/UISlider.hx b/source/funkin/editors/ui/UISlider.hx
index d07bb915..13b67dae 100644
--- a/source/funkin/editors/ui/UISlider.hx
+++ b/source/funkin/editors/ui/UISlider.hx
@@ -27,6 +27,7 @@ class UISlider extends UISprite {
public var value(default, set):Float = 0;
public function set_value(newVal:Float):Float {
+ newVal = FlxMath.bound(newVal, segments[0].start, segments[segments.length-1].end);
__barProgress = __calcProgress(newVal); if (onChange != null) onChange(newVal);
if (valueStepper != null) valueStepper.value = newVal;
return value = newVal;
diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx
index a7d8d17b..5d353e80 100644
--- a/source/funkin/game/PlayState.hx
+++ b/source/funkin/game/PlayState.hx
@@ -716,7 +716,7 @@ class PlayState extends MusicBeatState
startingPos,
strumLine.strumScale == null ? 1 : strumLine.strumScale,
strumLine.type == 2 || (!coopMode && !((strumLine.type == 1 && !opponentMode) || (strumLine.type == 0 && opponentMode))),
- strumLine.type != 1, coopMode ? (strumLine.type == 1 ? controlsP1 : controlsP2) : controls,
+ strumLine.type != 1, coopMode ? ((strumLine.type == 1) != opponentMode ? controlsP1 : controlsP2) : controls,
strumLine.vocalsSuffix
);
strLine.cameras = [camHUD];
diff --git a/source/funkin/menus/FreeplayState.hx b/source/funkin/menus/FreeplayState.hx
index 30518112..93435aa5 100644
--- a/source/funkin/menus/FreeplayState.hx
+++ b/source/funkin/menus/FreeplayState.hx
@@ -218,7 +218,7 @@ class FreeplayState extends MusicBeatState
lerpScore = intendedScore;
if (canSelect) {
- changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0));
+ changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
changeDiff((controls.LEFT_P ? -1 : 0) + (controls.RIGHT_P ? 1 : 0));
changeCoopMode((FlxG.keys.justPressed.TAB ? 1 : 0));
// putting it before so that its actually smooth
diff --git a/source/funkin/menus/MainMenuState.hx b/source/funkin/menus/MainMenuState.hx
index 325b7024..14600f83 100644
--- a/source/funkin/menus/MainMenuState.hx
+++ b/source/funkin/menus/MainMenuState.hx
@@ -106,11 +106,12 @@ class MainMenuState extends MusicBeatState
*/
}
- if (controls.UP_P)
- changeItem(-1);
+ var upP = controls.UP_P;
+ var downP = controls.DOWN_P;
+ var scroll = FlxG.mouse.wheel;
- if (controls.DOWN_P)
- changeItem(1);
+ if (upP || downP || scroll != 0) // like this we wont break mods that expect a 0 change event when calling sometimes - Nex
+ changeItem((upP ? -1 : 0) + (downP ? 1 : 0) - scroll);
if (controls.BACK)
FlxG.switchState(new TitleState());
@@ -124,9 +125,7 @@ class MainMenuState extends MusicBeatState
#end
if (controls.ACCEPT)
- {
selectItem();
- }
}
super.update(elapsed);
diff --git a/source/funkin/menus/ModSwitchMenu.hx b/source/funkin/menus/ModSwitchMenu.hx
index 4746b565..38175085 100644
--- a/source/funkin/menus/ModSwitchMenu.hx
+++ b/source/funkin/menus/ModSwitchMenu.hx
@@ -42,7 +42,7 @@ class ModSwitchMenu extends MusicBeatSubstate {
public override function update(elapsed:Float) {
super.update(elapsed);
- changeSelection((controls.DOWN_P ? 1 : 0) + (controls.UP_P ? -1 : 0));
+ changeSelection((controls.DOWN_P ? 1 : 0) + (controls.UP_P ? -1 : 0) - FlxG.mouse.wheel);
if (controls.ACCEPT) {
ModsFolder.switchMod(mods[curSelected]);
@@ -67,4 +67,4 @@ class ModSwitchMenu extends MusicBeatSubstate {
alphabets.members[curSelected].alpha = 1;
}
}
-#end
\ No newline at end of file
+#end
diff --git a/source/funkin/menus/PauseSubState.hx b/source/funkin/menus/PauseSubState.hx
index 1ab70f33..b543742a 100644
--- a/source/funkin/menus/PauseSubState.hx
+++ b/source/funkin/menus/PauseSubState.hx
@@ -127,13 +127,12 @@ class PauseSubState extends MusicBeatSubstate
var upP = controls.UP_P;
var downP = controls.DOWN_P;
- var accepted = controls.ACCEPT;
+ var scroll = FlxG.mouse.wheel;
- if (upP)
- changeSelection(-1);
- if (downP)
- changeSelection(1);
- if (accepted)
+ if (upP || downP || scroll != 0) // like this we wont break mods that expect a 0 change event when calling sometimes - Nex
+ changeSelection((upP ? -1 : 0) + (downP ? 1 : 0) - scroll);
+
+ if (controls.ACCEPT)
selectOption();
}
diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx
index 8cc0c431..4890c23d 100644
--- a/source/funkin/menus/StoryMenuState.hx
+++ b/source/funkin/menus/StoryMenuState.hx
@@ -149,7 +149,7 @@ class StoryMenuState extends MusicBeatState {
}
changeDifficulty((controls.LEFT_P ? -1 : 0) + (controls.RIGHT_P ? 1 : 0));
- changeWeek((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0));
+ changeWeek((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
if (controls.ACCEPT)
selectWeek();