1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-12-10 05:59:15 +00:00
Funkin/source/Main.hx

260 lines
8.4 KiB
Haxe

package;
import lime.system.System;
import flixel.FlxG;
import flixel.FlxGame;
import flixel.FlxState;
import funkin.ui.FullScreenScaleMode;
import funkin.Preferences;
import funkin.PlayerSettings;
import funkin.util.logging.CrashHandler;
import funkin.ui.debug.FunkinDebugDisplay;
import funkin.ui.debug.FunkinDebugDisplay.DebugDisplayMode;
import funkin.save.Save;
#if hxvlc
import hxvlc.util.Handle;
#end
import openfl.display.Sprite;
import openfl.events.Event;
import openfl.Lib;
import openfl.media.Video;
import openfl.net.NetStream;
import funkin.util.WindowUtil;
using funkin.util.AnsiUtil;
/**
* The main class which initializes HaxeFlixel and starts the game in its initial state.
*/
class Main extends Sprite
{
var gameWidth:Int = 1280; // Width of the game in pixels (might be less / more in actual pixels depending on your zoom).
var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom).
var initialState:Class<FlxState> = funkin.InitState; // The FlxState the game starts with.
var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions.
var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode.
// You can pretty much ignore everything from here on - your code should go in your states.
public static function main():Void
{
// Set the current working directory for Android and iOS devices
#if android
// On Android use External Files Dir.
Sys.setCwd(haxe.io.Path.addTrailingSlash(extension.androidtools.content.Context.getExternalFilesDir()));
#elseif ios
// On iOS use Documents Dir.
Sys.setCwd(haxe.io.Path.addTrailingSlash(lime.system.System.documentsDirectory));
#end
// We need to make the crash handler LITERALLY FIRST so nothing EVER gets past it.
CrashHandler.initialize();
CrashHandler.queryStatus();
Lib.current.addChild(new Main());
}
public function new()
{
super();
// Initialize custom logging.
haxe.Log.trace = funkin.util.logging.AnsiTrace.trace;
funkin.util.logging.AnsiTrace.traceBF();
// Load mods to override assets.
// TODO: Replace with loadEnabledMods() once the user can configure the mod list.
funkin.modding.PolymodHandler.loadAllMods();
if (stage != null)
{
init();
}
else
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
function init(?event:Event):Void
{
if (hasEventListener(Event.ADDED_TO_STAGE))
{
removeEventListener(Event.ADDED_TO_STAGE, init);
}
// Manually crash the game when using a software renderer in order to give a nicer error message.
var context = stage.window.context.type;
if (context != WEBGL && context != OPENGL && context != OPENGLES)
{
var tech:String = #if web "WebGL" #elseif desktop "OpenGL" #else "OpenGL ES" #end;
var requiredVersion:String = #if web '$tech 1.0 or newer' #elseif desktop '$tech 3.0 or newer' #else '$tech 2.0 or newer' #end;
var desc:String = 'Failed to initialize the $tech rendering context!\n\n';
#if web
desc += 'Make sure your graphics card supports $requiredVersion, your graphics drivers are up to date, and hardware acceleration is enabled on your browser.';
#elseif desktop
desc += 'Make sure your graphics card supports $requiredVersion, and your graphics drivers are up to date.';
#else
desc += 'Make sure your device supports $requiredVersion.';
#end
WindowUtil.showError('Failed to initialize $tech', desc);
System.exit(1);
}
setupGame();
}
/**
* The debug display at the top left.
*/
public static var debugDisplay:FunkinDebugDisplay;
function setupGame():Void
{
#if FEATURE_HAXEUI
initHaxeUI();
#end
// addChild gets called by the user settings code.
debugDisplay = new FunkinDebugDisplay(10, 10, 0xFFFFFF);
// Add this signal so the player can toggle the debug display using a hotkey.
FlxG.signals.postUpdate.add(handleDebugDisplayKeys);
#if mobile
// Add this signal so we can reposition and resize the memory and fps counter.
FlxG.signals.preUpdate.add(repositionCounters.bind(true));
#end
// George recommends binding the save before FlxGame is created.
Save.load();
#if hxvlc
// Initialize hxvlc's Handle here so the videos are loading faster.
Handle.initAsync(function(success:Bool):Void {
if (success)
{
trace(' HXVLC '.bold().bg_white() + ' LibVLC instance initialized!');
}
else
{
trace(' HXVLC '.bold().bg_white() + ' LibVLC instance failed to initialize!');
}
});
#end
// Don't call anything from the preferences until the save is loaded!
#if web
// set this variable (which is a function) from the lime version at lime/_internal/backend/html5/HTML5Application.hx
// The framerate cap will more thoroughly initialize via Preferences in InitState.hx
funkin.Preferences.lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
#end
WindowUtil.setVSyncMode(funkin.Preferences.vsyncMode);
var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, Preferences.framerate, Preferences.framerate, skipSplash,
(FlxG.stage.window.fullscreen || Preferences.autoFullscreen));
// FlxG.game._customSoundTray wants just the class, it calls new from
// create() in there, which gets called when it's added to the stage
// which is why it needs to be added before addChild(game) here
@:privateAccess
game._customSoundTray = funkin.ui.options.FunkinSoundTray;
addChild(game);
#if FEATURE_DEBUG_FUNCTIONS
game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil());
funkin.util.macro.ConsoleMacro.init();
#end
#if !html5
FlxG.scaleMode = new FullScreenScaleMode();
#end
#if mobile
// Reposition and resize the memory and fps counter without lerping.
repositionCounters(false);
#end
#if hxcpp_debug_server
trace('hxcpp_debug_server is enabled! You can now connect to the game with a debugger.');
#else
trace('hxcpp_debug_server is disabled! This build does not support debugging.');
#end
}
#if FEATURE_HAXEUI
function initHaxeUI():Void
{
// This has to come before Toolkit.init since locales get initialized there
haxe.ui.locale.LocaleManager.instance.autoSetLocale = false;
// Calling this before any HaxeUI components get used is important:
// - It initializes the theme styles.
// - It scans the class path and registers any HaxeUI components.
haxe.ui.Toolkit.init();
haxe.ui.Toolkit.theme = 'dark'; // don't be cringe
// haxe.ui.Toolkit.theme = 'light'; // embrace cringe
haxe.ui.Toolkit.autoScale = false;
// Don't focus on UI elements when they first appear.
haxe.ui.focus.FocusManager.instance.autoFocus = false;
funkin.input.Cursor.registerHaxeUICursors();
haxe.ui.tooltips.ToolTipManager.defaultDelay = 200;
}
#end
function handleDebugDisplayKeys():Void
{
if (PlayerSettings.player1.controls == null || !PlayerSettings.player1.controls.check(DEBUG_DISPLAY)) return;
var nextMode:DebugDisplayMode;
switch (Preferences.debugDisplay)
{
case DebugDisplayMode.Off:
nextMode = DebugDisplayMode.Simple;
case DebugDisplayMode.Simple:
nextMode = DebugDisplayMode.Advanced;
case DebugDisplayMode.Advanced:
nextMode = DebugDisplayMode.Off;
}
Preferences.debugDisplay = nextMode;
}
#if mobile
function repositionCounters(lerp:Bool):Void
{
// Calling this so it gets scaled based on the resolution of the game and device's resolution.
var scale:Float = Math.min(FlxG.stage.stageWidth / FlxG.width, FlxG.stage.stageHeight / FlxG.height);
#if android
scale = Math.max(scale, 1);
#else
scale = Math.min(scale, 1);
#end
final thypos:Float = Math.max(FullScreenScaleMode.notchSize.x, 10);
if (debugDisplay != null)
{
debugDisplay.scaleX = debugDisplay.scaleY = scale;
if (FlxG.game != null)
{
if (lerp)
{
debugDisplay.x = flixel.math.FlxMath.lerp(debugDisplay.x, FlxG.game.x + thypos, FlxG.elapsed * 3);
}
else
{
debugDisplay.x = FlxG.game.x + FullScreenScaleMode.notchSize.x + 10;
}
debugDisplay.y = FlxG.game.y + (3 * scale);
}
}
}
#end
}