diff --git a/assets/images/characters/bf.png b/assets/images/characters/bf.png index 4866768c..4d3c1487 100644 Binary files a/assets/images/characters/bf.png and b/assets/images/characters/bf.png differ diff --git a/assets/images/characters/bf.xml b/assets/images/characters/bf.xml index 50b7bd2e..89452dd4 100644 --- a/assets/images/characters/bf.xml +++ b/assets/images/characters/bf.xml @@ -1,501 +1,353 @@  - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/menus/options/checkboxThingie.png b/assets/images/menus/options/checkboxThingie.png new file mode 100644 index 00000000..de33a7a5 Binary files /dev/null and b/assets/images/menus/options/checkboxThingie.png differ diff --git a/assets/images/menus/options/checkboxThingie.xml b/assets/images/menus/options/checkboxThingie.xml new file mode 100644 index 00000000..40f9ad6c --- /dev/null +++ b/assets/images/menus/options/checkboxThingie.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/buildnumber.txt b/buildnumber.txt index 707e2574..3cdc9881 100644 --- a/buildnumber.txt +++ b/buildnumber.txt @@ -1 +1 @@ -853 \ No newline at end of file +889 \ No newline at end of file diff --git a/source/funkin/desktop/sprites/WindowText.hx b/source/funkin/desktop/sprites/WindowText.hx index 30758494..da01b572 100644 --- a/source/funkin/desktop/sprites/WindowText.hx +++ b/source/funkin/desktop/sprites/WindowText.hx @@ -5,7 +5,6 @@ import flixel.addons.ui.FlxUIText; import funkin.desktop.theme.Theme.ThemeData; class WindowText extends FlxText { - // TODO: VISUAL STYLES SHIT public function new(x:Float, y:Float, w:Float, t:String) { super(x, y, w, t); color = 0xFF000000; diff --git a/source/funkin/options/OptionsMenu.hx b/source/funkin/options/OptionsMenu.hx index 4d7247eb..24c123bb 100644 --- a/source/funkin/options/OptionsMenu.hx +++ b/source/funkin/options/OptionsMenu.hx @@ -1,5 +1,6 @@ package funkin.options; +import flixel.FlxState; import flixel.addons.transition.FlxTransitionableState; import flixel.group.FlxGroup.FlxTypedGroup; import funkin.ui.Alphabet; @@ -9,9 +10,16 @@ import flixel.FlxG; import flixel.effects.FlxFlicker; import funkin.menus.MainMenuState; +import funkin.options.categories.*; + +typedef OptionCategory = { + var name:String; + var desc:String; + var state:Class; +} class OptionsMenu extends MusicBeatState { public static var fromPlayState:Bool = false; - public var options = [ + public var options:Array = [ { name: 'Controls', desc: 'Change Controls for Player 1 and Player 2!', @@ -20,7 +28,17 @@ class OptionsMenu extends MusicBeatState { { name: 'Gameplay', desc: 'Change Gameplay options such as Downscroll, Scroll Speed...', - state: null + state: GameplayOptions + }, + { + name: 'Behaviour', + desc: 'Change Behaviour options such as Naughtyness, Flashing lights...', + state: BehaviourOptions + }, + { + name: 'Save Data', + desc: 'Use this menu to reset save data or engine settings.', + state: SaveDataOptions } ]; @@ -44,7 +62,7 @@ class OptionsMenu extends MusicBeatState { super.create(); alphabets = new FlxTypedGroup(); for(k=>e in options) { - var alphabet = new Alphabet(0, (k+1) * 100, e.name, true, false); + var alphabet = new Alphabet(0, (k+1) * (100), e.name, true, false); alphabet.screenCenter(X); alphabets.add(alphabet); } diff --git a/source/funkin/options/OptionsScreen.hx b/source/funkin/options/OptionsScreen.hx index 1f9f91c1..8be076c8 100644 --- a/source/funkin/options/OptionsScreen.hx +++ b/source/funkin/options/OptionsScreen.hx @@ -1,16 +1,28 @@ package funkin.options; +import flixel.math.FlxMath; import flixel.util.FlxColor; import flixel.FlxSprite; import flixel.FlxG; +import funkin.options.type.OptionType; /** * Direct replica from Week 7 lol */ class OptionsScreen extends MusicBeatState { public static inline var defaultBGColor:FlxColor = 0xFFFDE871; - public var bgColor:FlxColor = 0xFFFDE871; + public static var instance:OptionsScreen; + + // public var bgColor:FlxColor = 0xFFFDE871; public var bg:FlxSprite; + public var curSelected:Int = -1; + + public var options:Array = []; + + public function new() { + super(); + instance = this; + } public override function create() { super.create(); @@ -22,5 +34,35 @@ class OptionsScreen extends MusicBeatState { bg.screenCenter(); bg.antialiasing = true; add(bg); + + for(k=>option in options) { + option.setPosition(0, 10 + (k * 120)); + add(option); + } + changeSelection(1); + } + + public override function update(elapsed:Float) { + super.update(elapsed); + changeSelection((controls.DOWN_P ? 1 : 0) + (controls.UP_P ? -1 : 0)); + if (controls.ACCEPT) { + options[curSelected].onSelect(); + } + if (controls.BACK) + FlxG.switchState(new OptionsMenu(false)); + } + + public function changeSelection(change:Int) { + if (change == 0 && curSelected != -1) return; + curSelected = FlxMath.wrap(curSelected + change, 0, options.length - 1); + for(e in options) + e.selected = false; + options[curSelected].selected = true; + CoolUtil.playMenuSFX(0); + } + + public override function destroy() { + super.destroy(); + instance = null; } } \ No newline at end of file diff --git a/source/funkin/options/categories/BehaviourOptions.hx b/source/funkin/options/categories/BehaviourOptions.hx new file mode 100644 index 00000000..86966853 --- /dev/null +++ b/source/funkin/options/categories/BehaviourOptions.hx @@ -0,0 +1,12 @@ +package funkin.options.categories; + +class BehaviourOptions extends OptionsScreen { + public override function create() { + options = [ + new Checkbox("Naughtyness", "naughtyness"), + new Checkbox("Flashing Menu", "flashingMenu"), + new Checkbox("Camera Zoom on Beat", "camZoomOnBeat"), + ]; + super.create(); + } +} \ No newline at end of file diff --git a/source/funkin/options/categories/GameplayOptions.hx b/source/funkin/options/categories/GameplayOptions.hx new file mode 100644 index 00000000..323ff46d --- /dev/null +++ b/source/funkin/options/categories/GameplayOptions.hx @@ -0,0 +1,11 @@ +package funkin.options.categories; + +class GameplayOptions extends OptionsScreen { + public override function create() { + options = [ + new Checkbox("Downscroll", "downscroll"), + new Checkbox("Auto Pause", "autoPause"), + ]; + super.create(); + } +} \ No newline at end of file diff --git a/source/funkin/options/categories/SaveDataOptions.hx b/source/funkin/options/categories/SaveDataOptions.hx new file mode 100644 index 00000000..80659019 --- /dev/null +++ b/source/funkin/options/categories/SaveDataOptions.hx @@ -0,0 +1,12 @@ +package funkin.options.categories; + +class SaveDataOptions extends OptionsScreen { + public override function create() { + options = [ + new TextOption("Reset Save Data", function() { + + }) + ]; + super.create(); + } +} \ No newline at end of file diff --git a/source/funkin/options/categories/import.hx b/source/funkin/options/categories/import.hx new file mode 100644 index 00000000..046ac6ef --- /dev/null +++ b/source/funkin/options/categories/import.hx @@ -0,0 +1,3 @@ +package funkin.options.categories; + +import funkin.options.type.*; \ No newline at end of file diff --git a/source/funkin/options/type/Checkbox.hx b/source/funkin/options/type/Checkbox.hx new file mode 100644 index 00000000..b35819b7 --- /dev/null +++ b/source/funkin/options/type/Checkbox.hx @@ -0,0 +1,65 @@ +package funkin.options.type; + +import flixel.FlxSprite; +import flixel.math.FlxPoint; + +@:allow() +class Checkbox extends TextOption { + + public var checkbox:FlxSprite; + public var checked:Bool; + + private function get_selected() { + + } + public var optionName:String; + + private var offsets:Map = [ + "checked" => FlxPoint.get(1, -1), + "unchecked" => FlxPoint.get(-12, -72), + "checking" => FlxPoint.get(12, 30) + ]; + private var baseCheckboxOffset:FlxPoint = FlxPoint.get(); + + public function new(text:String, optionName:String) { + super(text, null); + + checkbox = new FlxSprite(10, -40); + checkbox.frames = Paths.getSparrowAtlas('menus/options/checkboxThingie'); + checkbox.animation.addByPrefix("checked", "Check Box Selected Static", 24); + checkbox.animation.addByPrefix("unchecked", "Check Box unselected", 24); + checkbox.animation.addByPrefix("checking", "Check Box selecting animation", 24, false); + checkbox.antialiasing = true; + checkbox.scale.set(0.75, 0.75); + checkbox.updateHitbox(); + add(checkbox); + + baseCheckboxOffset.set(checkbox.offset.x, checkbox.offset.y); + + this.optionName = optionName; + checked = Reflect.field(Options, optionName); + } + + public override function update(elapsed:Float) { + if (checkbox.animation.curAnim == null || (checkbox.animation.curAnim.finished || (checkbox.animation.curAnim.reversed && checkbox.animation.curAnim.curFrame <= 0))) { + checkbox.animation.play(checked ? "checked" : "unchecked", true); + } + super.update(elapsed); + var offset = offsets[checkbox.animation.curAnim.name]; + if (offset != null) + checkbox.offset.set( + (offset.x * checkbox.scale.x) + baseCheckboxOffset.x, + (offset.y * checkbox.scale.y) + baseCheckboxOffset.y); + } + + public override function onSelect() { + Reflect.setField(Options, optionName, checked = !checked); + checkbox.animation.play("checking", true, !checked); + } + + public override function destroy() { + super.destroy(); + for(e in offsets) e.put(); + baseCheckboxOffset.put(); + } +} \ No newline at end of file diff --git a/source/funkin/options/type/OptionType.hx b/source/funkin/options/type/OptionType.hx new file mode 100644 index 00000000..dcdaea59 --- /dev/null +++ b/source/funkin/options/type/OptionType.hx @@ -0,0 +1,22 @@ +package funkin.options.type; + +import funkin.system.Controls; +import flixel.group.FlxSpriteGroup; +import funkin.options.OptionsScreen; + +class OptionType extends FlxSpriteGroup { + public var controls(get, null):Controls; + public var selected:Bool = false; + + private function get_controls() {return PlayerSettings.player1.controls;} + + public function onSelect() { + + } + + public override function update(elapsed:Float) { + super.update(elapsed); + alpha = (selected ? 1 : 0.6); + } +} + \ No newline at end of file diff --git a/source/funkin/options/type/TextOption.hx b/source/funkin/options/type/TextOption.hx new file mode 100644 index 00000000..d868813a --- /dev/null +++ b/source/funkin/options/type/TextOption.hx @@ -0,0 +1,24 @@ +package funkin.options.type; + +import funkin.ui.Alphabet; + +class TextOption extends OptionType { + public var selectCallback:Void->Void; + + private var __text:Alphabet; + + public var text(get, set):String; + private function get_text() {return __text.text;} + private function set_text(v:String) {return __text.text = v;} + + public function new(text:String, selectCallback:Void->Void) { + super(); + this.selectCallback = selectCallback; + add(__text = new Alphabet(100, 20, text, true)); + } + + public override function onSelect() { + super.onSelect(); + selectCallback(); + } +} \ No newline at end of file diff --git a/source/funkin/system/Main.hx b/source/funkin/system/Main.hx index 4d01f45b..86d9be46 100644 --- a/source/funkin/system/Main.hx +++ b/source/funkin/system/Main.hx @@ -134,6 +134,7 @@ class Main extends Sprite Options.load(); AudioSwitchFix.init(); + WindowsAPI.setDarkMode(true); var diamond:FlxGraphic = FlxGraphic.fromClass(GraphicTransTileDiamond); diamond.persist = true; diff --git a/source/funkin/windows/WindowsAPI.hx b/source/funkin/windows/WindowsAPI.hx index 467c3a7a..d21ab0b0 100644 --- a/source/funkin/windows/WindowsAPI.hx +++ b/source/funkin/windows/WindowsAPI.hx @@ -7,9 +7,27 @@ package funkin.windows; * Does not have any effect on other platforms. */ class WindowsAPI { - public static function registerAudio() { + @:dox(hide) public static function registerAudio() { #if windows native.WinAPI.registerAudio(); #end } + + /** + * Allocates a new console. The console will automatically be opened + */ + public static function allocConsole() { + #if windows + native.WinAPI.allocConsole(); + #end + } + + /** + * Sets the window titlebar to dark mode (Windows 10 only) + */ + public static function setDarkMode(enable:Bool) { + #if windows + native.WinAPI.setDarkMode(enable); + #end + } } \ No newline at end of file diff --git a/source/native/WinAPI.hx b/source/native/WinAPI.hx index a4d7e937..c6ab3d63 100644 --- a/source/native/WinAPI.hx +++ b/source/native/WinAPI.hx @@ -7,6 +7,7 @@ package native; + ') @@ -15,6 +16,15 @@ package native; #include "mmdeviceapi.h" #include "combaseapi.h" #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define SAFE_RELEASE(punk) \\ if ((punk) != NULL) \\ @@ -116,5 +126,47 @@ class WinAPI { public static function registerAudio() { funkin.system.Main.audioDisconnected = false; } + + @:functionCode(' + int darkMode = enable ? 1 : 0; + HWND window = GetActiveWindow(); + if (S_OK != DwmSetWindowAttribute(window, 19, &darkMode, sizeof(darkMode))) { + DwmSetWindowAttribute(window, 20, &darkMode, sizeof(darkMode)); + } + ') + public static function setDarkMode(enable:Bool) {} + + @:functionCode(' + // https://stackoverflow.com/questions/15543571/allocconsole-not-displaying-cout + + if (!AllocConsole()) + return; + + FILE* fDummy; + freopen_s(&fDummy, "CONOUT$", "w", stdout); + freopen_s(&fDummy, "CONOUT$", "w", stderr); + freopen_s(&fDummy, "CONIN$", "r", stdin); + std::cout.clear(); + std::clog.clear(); + std::cerr.clear(); + std::cin.clear(); + + // std::wcout, std::wclog, std::wcerr, std::wcin + HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + SetStdHandle(STD_OUTPUT_HANDLE, hConOut); + SetStdHandle(STD_ERROR_HANDLE, hConOut); + SetStdHandle(STD_INPUT_HANDLE, hConIn); + std::wcout.clear(); + std::wclog.clear(); + std::wcerr.clear(); + std::wcin.clear(); + ') + public static function allocConsole() { + // LogsOverlay.consoleOpened = LogsOverlay.consoleVisible = true; + haxe.Log.trace = function(v:Dynamic, ?infos:haxe.PosInfos) { + // nothing here so that it keeps shit clean + } + } } #end \ No newline at end of file