From c68b7e4233c7416ee391826eea4e912498c00f19 Mon Sep 17 00:00:00 2001 From: ItsLJcool Date: Thu, 2 Apr 2026 19:38:32 -0700 Subject: [PATCH 1/2] With this one singular commit, I will have introduced HELL --- source/funkin/backend/utils/ScriptedWindow.hx | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 source/funkin/backend/utils/ScriptedWindow.hx diff --git a/source/funkin/backend/utils/ScriptedWindow.hx b/source/funkin/backend/utils/ScriptedWindow.hx new file mode 100644 index 000000000..18e61146c --- /dev/null +++ b/source/funkin/backend/utils/ScriptedWindow.hx @@ -0,0 +1,110 @@ +package funkin.backend.utils; + +import funkin.backend.scripting.Script; + +import funkin.backend.system.FunkinGame; + +import hscript.IHScriptCustomBehaviour; + +import openfl.Lib; + +import openfl.display.Bitmap; +import openfl.display.BitmapData; +import openfl.display.Sprite; +import openfl.display.Window; + +import openfl.events.Event; + +/* https://github.com/openfl/lime/blob/develop/src/lime/ui/WindowAttributes.hx */ +import lime.ui.WindowAttributes; + +class ScriptedWindow +implements IFlxDestroyable implements IHScriptCustomBehaviour { + + public static var default_arguments:Dynamic = { + title: "Codename Engine - Scripted Window", + width: 1280, + height: 720, + frameRate: Options.framerate, + }; + + public var window:Window; + + public var script:Script; + + private var __variables:Array; + + public var game:Sprite = new Sprite(); + + public var _closeWhenMainWindowClosed:Bool = true; + + public function new(path:String, ?attributes:Dynamic, ?shouldCloseAutomatically:Bool = true) { + + _closeWhenMainWindowClosed = shouldCloseAutomatically; + + if (attributes == null) attributes = ScriptedWindow.default_arguments; + if (attributes.title == null) attributes.title = ScriptedWindow.default_arguments.title; + if (attributes.width == null) attributes.width = ScriptedWindow.default_arguments.width; + if (attributes.height == null) attributes.height = ScriptedWindow.default_arguments.height; + if (attributes.frameRate == null) attributes.frameRate = Options.framerate; // so it will constantly update regardless default_framerate + + window = Lib.application.createWindow(attributes); + window.stage.addChild(game); + window.onClose.add(onWindowClose); + + // Ok so if you close the main window it stops the main thread, so be careful 🥶 + Lib.application.window.onClose.add(() -> { + if (_closeWhenMainWindowClosed) window.close(); + }); + + script = Script.create(path); + script.setParent(window); + + script.set("game", game); + script.set("addAsBitmap", addAsBitmap); + script.load(); + + FlxG.signals.preUpdate.add(function() { + script.call("preUpdate", [FlxG.elapsed]); + script.call("update", [FlxG.elapsed]); + }); + + FlxG.signals.postUpdate.add(function() { + script.call("postUpdate", [FlxG.elapsed]); + }); + + __variables = Type.getInstanceFields(Type.getClass(this)); + } + + private inline function addAsBitmap(path:String):Bitmap { + var bitmap:Bitmap = new Bitmap(BitmapData.fromBytes(Assets.getBytes(path))); + game.addChild(bitmap); + return bitmap; + } + + public function hget(name:String):Dynamic + return __variables.contains(name) ? Reflect.getProperty(this, name) : script.get(name); + + public function hset(name:String, val:Dynamic):Dynamic { + if (__variables.contains(name)) + Reflect.setProperty(this, name, val); + else + script.set(name, val); + return val; + } + + private function onWindowClose() { + destroy(); + } + + inline public function close() window.close(); + + public function destroy() { + script.call("destroy"); + FlxDestroyUtil.destroy(script); + } + + public function toString():String { + return 'ScriptedWindow (${script.path})'; + } +} \ No newline at end of file From 2a8ac358ffff6f02e3521978a31b8a0ec4758c14 Mon Sep 17 00:00:00 2001 From: ItsLJcool Date: Thu, 2 Apr 2026 19:58:14 -0700 Subject: [PATCH 2/2] made it so if script doesn't exist we just don't open the window :fivehead: --- source/funkin/backend/utils/ScriptedWindow.hx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/funkin/backend/utils/ScriptedWindow.hx b/source/funkin/backend/utils/ScriptedWindow.hx index 18e61146c..6449824a5 100644 --- a/source/funkin/backend/utils/ScriptedWindow.hx +++ b/source/funkin/backend/utils/ScriptedWindow.hx @@ -1,6 +1,7 @@ package funkin.backend.utils; import funkin.backend.scripting.Script; +import funkin.backend.scripting.DummyScript; import funkin.backend.system.FunkinGame; @@ -38,6 +39,8 @@ implements IFlxDestroyable implements IHScriptCustomBehaviour { public var _closeWhenMainWindowClosed:Bool = true; + public var FAILED_TO_START:Bool = true; + public function new(path:String, ?attributes:Dynamic, ?shouldCloseAutomatically:Bool = true) { _closeWhenMainWindowClosed = shouldCloseAutomatically; @@ -48,6 +51,12 @@ implements IFlxDestroyable implements IHScriptCustomBehaviour { if (attributes.height == null) attributes.height = ScriptedWindow.default_arguments.height; if (attributes.frameRate == null) attributes.frameRate = Options.framerate; // so it will constantly update regardless default_framerate + script = Script.create(path); + if (script is DummyScript) { + destroy(); + return; + } + window = Lib.application.createWindow(attributes); window.stage.addChild(game); window.onClose.add(onWindowClose); @@ -57,7 +66,6 @@ implements IFlxDestroyable implements IHScriptCustomBehaviour { if (_closeWhenMainWindowClosed) window.close(); }); - script = Script.create(path); script.setParent(window); script.set("game", game); @@ -74,6 +82,7 @@ implements IFlxDestroyable implements IHScriptCustomBehaviour { }); __variables = Type.getInstanceFields(Type.getClass(this)); + FAILED_TO_START = false; } private inline function addAsBitmap(path:String):Bitmap {