246 lines
7.2 KiB
Haxe
246 lines
7.2 KiB
Haxe
package funkin.backend.system;
|
|
|
|
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
|
|
import flixel.addons.transition.FlxTransitionableState;
|
|
import flixel.addons.transition.TransitionData;
|
|
import flixel.graphics.FlxGraphic;
|
|
import flixel.math.FlxPoint;
|
|
import flixel.math.FlxRect;
|
|
import flixel.system.ui.FlxSoundTray;
|
|
import funkin.backend.assets.AssetsLibraryList;
|
|
import funkin.backend.assets.ModsFolder;
|
|
import funkin.backend.system.framerate.SystemInfo;
|
|
import funkin.backend.system.modules.*;
|
|
import funkin.editors.SaveWarning;
|
|
import openfl.Assets;
|
|
import openfl.Lib;
|
|
import openfl.display.Sprite;
|
|
import openfl.text.TextFormat;
|
|
import openfl.utils.AssetLibrary;
|
|
|
|
#if ALLOW_MULTITHREADING
|
|
import sys.thread.Thread;
|
|
#end
|
|
#if android
|
|
import android.content.Context;
|
|
import android.os.Build;
|
|
#end
|
|
|
|
class Main extends Sprite
|
|
{
|
|
public static var instance:Main;
|
|
|
|
public static var modToLoad:String = null;
|
|
public static var forceGPUOnlyBitmapsOff:Bool = #if windows false #else true #end;
|
|
public static var noTerminalColor:Bool = false;
|
|
|
|
public static var scaleMode:FunkinRatioScaleMode;
|
|
#if !mobile
|
|
public static var framerateSprite:funkin.backend.system.framerate.Framerate;
|
|
#end
|
|
|
|
var gameWidth:Int = 1280; // Width of the game in pixels (might be less / more in actual pixels).
|
|
var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels).
|
|
var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode.
|
|
var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets
|
|
|
|
public static var game:FunkinGame;
|
|
|
|
/**
|
|
* The time since the game was focused last time in seconds.
|
|
*/
|
|
public static var timeSinceFocus(get, never):Float;
|
|
public static var time:Int = 0;
|
|
|
|
// You can pretty much ignore everything from here on - your code should go in your states.
|
|
|
|
#if ALLOW_MULTITHREADING
|
|
public static var gameThreads:Array<Thread> = [];
|
|
#end
|
|
|
|
public function new()
|
|
{
|
|
super();
|
|
|
|
instance = this;
|
|
|
|
CrashHandler.init();
|
|
|
|
addChild(game = new FunkinGame(gameWidth, gameHeight, MainState, Options.framerate, Options.framerate, skipSplash, startFullscreen));
|
|
|
|
#if (!mobile && !web)
|
|
addChild(framerateSprite = new funkin.backend.system.framerate.Framerate());
|
|
SystemInfo.init();
|
|
#end
|
|
}
|
|
|
|
@:dox(hide)
|
|
public static var audioDisconnected:Bool = false;
|
|
|
|
public static var changeID:Int = 0;
|
|
public static var pathBack = #if windows
|
|
"../../../../"
|
|
#elseif mac
|
|
"../../../../../../../"
|
|
#else
|
|
""
|
|
#end;
|
|
public static var startedFromSource:Bool = #if TEST_BUILD true #else false #end;
|
|
|
|
|
|
private static var __threadCycle:Int = 0;
|
|
public static function execAsync(func:Void->Void) {
|
|
#if ALLOW_MULTITHREADING
|
|
var thread = gameThreads[(__threadCycle++) % gameThreads.length];
|
|
thread.events.run(func);
|
|
#else
|
|
func();
|
|
#end
|
|
}
|
|
|
|
private static function getTimer():Int {
|
|
return time = Lib.getTimer();
|
|
}
|
|
|
|
public static function loadGameSettings() {
|
|
WindowUtils.init();
|
|
SaveWarning.init();
|
|
MemoryUtil.init();
|
|
@:privateAccess
|
|
FlxG.game.getTimer = getTimer;
|
|
#if ALLOW_MULTITHREADING
|
|
for(i in 0...4)
|
|
gameThreads.push(Thread.createWithEventLoop(function() {Thread.current().events.promise();}));
|
|
#end
|
|
FunkinCache.init();
|
|
Paths.assetsTree = new AssetsLibraryList();
|
|
|
|
#if UPDATE_CHECKING
|
|
funkin.backend.system.updating.UpdateUtil.init();
|
|
#end
|
|
ShaderResizeFix.init();
|
|
Logs.init();
|
|
Paths.init();
|
|
|
|
hscript.Interp.importRedirects = funkin.backend.scripting.Script.getDefaultImportRedirects();
|
|
|
|
#if GLOBAL_SCRIPT
|
|
funkin.backend.scripting.GlobalScript.init();
|
|
#end
|
|
|
|
#if (sys && TEST_BUILD)
|
|
trace("Used cne test / cne build. Switching into source assets.");
|
|
#if MOD_SUPPORT
|
|
ModsFolder.modsPath = './${pathBack}mods/';
|
|
ModsFolder.addonsPath = './${pathBack}addons/';
|
|
#end
|
|
Paths.assetsTree.__defaultLibraries.push(ModsFolder.loadLibraryFromFolder('assets', './${pathBack}assets/', true));
|
|
#elseif USE_ADAPTED_ASSETS
|
|
Paths.assetsTree.__defaultLibraries.push(ModsFolder.loadLibraryFromFolder('assets', './assets/', true));
|
|
#end
|
|
|
|
|
|
var lib = new AssetLibrary();
|
|
@:privateAccess
|
|
lib.__proxy = Paths.assetsTree;
|
|
Assets.registerLibrary('default', lib);
|
|
|
|
funkin.options.PlayerSettings.init();
|
|
funkin.savedata.FunkinSave.init();
|
|
Options.load();
|
|
|
|
FlxG.fixedTimestep = false;
|
|
|
|
FlxG.scaleMode = scaleMode = new FunkinRatioScaleMode();
|
|
|
|
Conductor.init();
|
|
AudioSwitchFix.init();
|
|
EventManager.init();
|
|
FlxG.signals.focusGained.add(onFocus);
|
|
FlxG.signals.preStateSwitch.add(onStateSwitch);
|
|
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
|
|
ModsFolder.switchMod(modToLoad.getDefault(Options.lastLoadedMod));
|
|
#end
|
|
|
|
initTransition();
|
|
}
|
|
|
|
public static function refreshAssets() @:privateAccess {
|
|
var game = FlxG.game;
|
|
var daSndTray = Type.createInstance(game._customSoundTray = funkin.menus.ui.FunkinSoundTray, []);
|
|
var index:Int = game.numChildren - 1;
|
|
|
|
if(game.soundTray != null)
|
|
{
|
|
var newIndex:Int = game.getChildIndex(game.soundTray);
|
|
if(newIndex != -1) index = newIndex;
|
|
game.removeChild(game.soundTray);
|
|
game.soundTray.__cleanup();
|
|
}
|
|
|
|
game.addChildAt(game.soundTray = daSndTray, index);
|
|
}
|
|
|
|
public static function initTransition() {
|
|
var diamond:FlxGraphic = FlxGraphic.fromClass(GraphicTransTileDiamond);
|
|
diamond.persist = true;
|
|
diamond.destroyOnNoUse = false;
|
|
|
|
FlxTransitionableState.defaultTransIn = new TransitionData(FADE, 0xFF000000, 1, new FlxPoint(0, -1), {asset: diamond, width: 32, height: 32},
|
|
new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
|
|
FlxTransitionableState.defaultTransOut = new TransitionData(FADE, 0xFF000000, 0.7, new FlxPoint(0, 1),
|
|
{asset: diamond, width: 32, height: 32}, new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
|
|
}
|
|
|
|
public static function onFocus() {
|
|
_tickFocused = FlxG.game.ticks;
|
|
}
|
|
|
|
private static function onStateSwitch() {
|
|
scaleMode.resetSize();
|
|
}
|
|
|
|
private static function onStateSwitchPost() {
|
|
// manual asset clearing since base openfl one does'nt clear lime one
|
|
// does'nt clear bitmaps since flixel fork does it auto
|
|
|
|
@:privateAccess {
|
|
// clear uint8 pools
|
|
for(length=>pool in openfl.display3D.utils.UInt8Buff._pools) {
|
|
for(b in pool.clear())
|
|
b.destroy();
|
|
}
|
|
|
|
openfl.display3D.utils.UInt8Buff._pools.clear();
|
|
}
|
|
|
|
MemoryUtil.clearMajor();
|
|
}
|
|
|
|
public static var noCwdFix:Bool = false;
|
|
public static function fixWorkingDirectory() {
|
|
#if windows
|
|
if (!noCwdFix && !sys.FileSystem.exists('manifest/default.json')) {
|
|
Sys.setCwd(haxe.io.Path.directory(Sys.programPath()));
|
|
}
|
|
#elseif android
|
|
Sys.setCwd(Path.addTrailingSlash(VERSION.SDK_INT > 30 ? Context.getObbDir() : Context.getExternalFilesDir()));
|
|
#elseif (ios || switch)
|
|
Sys.setCwd(Path.addTrailingSlash(openfl.filesystem.File.applicationStorageDirectory.nativePath));
|
|
#end
|
|
}
|
|
|
|
private static var _tickFocused:Float = 0;
|
|
public static function get_timeSinceFocus():Float {
|
|
return (FlxG.game.ticks - _tickFocused) / 1000;
|
|
}
|
|
}
|