From 99703cf03ed3018c875dcc0a3852665328fb18d8 Mon Sep 17 00:00:00 2001 From: JeremyStarTM Date: Fri, 25 Aug 2023 14:34:57 +0200 Subject: [PATCH] CORE rewrite (#1) Reviewed-on: https://git.staropensource.de/StarOpenSource/core/pulls/1 Rewrote CORE and improved the startup process and startup time significantly. The documentation has been beefed up too and is now much better. Existing projects may need major refactoring however. Co-authored-by: JeremyStarTM Co-committed-by: JeremyStarTM --- .gitignore | 1 + Makefile | 14 +- README.md | 13 +- assets/testproject/init.gd | 9 + .../mods/testmod/coredevprj.coremod | 18 ++ assets/testproject/mods/testmod/testmod.gd | 15 + assets/testproject/project.godot | 29 ++ background.tscn | 38 --- moam.gd => cml.gd | 91 +++--- core.gd | 242 ++++++++------ coreinit.gd | 246 +++++++++++--- coreinit.tscn | 5 +- coreloader.gd | 66 ---- corelog.gd | 78 +++-- corelog.tscn | 52 +++ count_characters.sh | 18 +- debugdisplay.gd | 71 ++++ debugdisplay.tscn | 34 ++ docs/breaking-commits.md | 9 + docs/index.md | 6 +- docs/install.md | 149 ++++++--- docs/licensing.md | 2 +- docs/quickstartguide.md | 57 ++++ docs/references/CORE.md | 57 ++++ docs/references/Configuration_File.md | 142 ++++++++ docs/references/DebugDisplay.md | 9 + docs/references/Events.md | 43 +++ docs/references/Logger.md | 76 +++++ docs/references/Miscellaneous.md | 51 +++ docs/references/Preprocessor.md | 96 ++++++ .../{resmgr.gd.md => ResourceManager.md} | 16 +- docs/references/SceneManager.md | 79 +++++ docs/references/SplashScreen.md | 14 + docs/references/config.gd.md | 130 -------- docs/references/core.gd.md | 59 ---- docs/references/events.gd.md | 96 ------ docs/references/index.md | 22 +- docs/references/moam.gd.md | 61 ---- docs/references/preprocessor.gd.md | 219 ------------- docs/references/smgr.gd.md | 137 -------- docs/references/splash.gd.md | 45 --- docs/references/wmgr.gd.md | 125 ------- docs/troubleshooting.md | 41 +-- docs/update.md | 2 - events.gd | 115 ++++--- logger.gd | 143 +++++--- misc.gd | 68 ++++ mkdocs.yml | 3 +- mkdown.gd | 27 +- preprocessor.gd | 305 +++++------------- resmgr.gd | 111 +++++-- smgr.gd | 304 +++++++++-------- splash.gd | 51 ++- splash.tscn | 2 +- wmgr.gd | 108 ------- 55 files changed, 2035 insertions(+), 1985 deletions(-) create mode 100644 assets/testproject/init.gd create mode 100644 assets/testproject/mods/testmod/coredevprj.coremod create mode 100644 assets/testproject/mods/testmod/testmod.gd create mode 100644 assets/testproject/project.godot delete mode 100644 background.tscn rename moam.gd => cml.gd (50%) delete mode 100644 coreloader.gd create mode 100644 corelog.tscn create mode 100644 debugdisplay.gd create mode 100644 debugdisplay.tscn create mode 100644 docs/breaking-commits.md create mode 100644 docs/quickstartguide.md create mode 100644 docs/references/CORE.md create mode 100644 docs/references/Configuration_File.md create mode 100644 docs/references/DebugDisplay.md create mode 100644 docs/references/Events.md create mode 100644 docs/references/Logger.md create mode 100644 docs/references/Miscellaneous.md create mode 100644 docs/references/Preprocessor.md rename docs/references/{resmgr.gd.md => ResourceManager.md} (81%) create mode 100644 docs/references/SceneManager.md create mode 100644 docs/references/SplashScreen.md delete mode 100644 docs/references/config.gd.md delete mode 100644 docs/references/core.gd.md delete mode 100644 docs/references/events.gd.md delete mode 100644 docs/references/moam.gd.md delete mode 100644 docs/references/preprocessor.gd.md delete mode 100644 docs/references/smgr.gd.md delete mode 100644 docs/references/splash.gd.md delete mode 100644 docs/references/wmgr.gd.md create mode 100644 misc.gd delete mode 100644 wmgr.gd diff --git a/.gitignore b/.gitignore index f447156..68b1ba1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.import config.gd +devprj diff --git a/Makefile b/Makefile index c1701bd..da04150 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ #!/bin/make CORE=$(shell pwd) +ASSETS=$(CORE)/assets DOCSCONF=$(CORE)/mkdocs.yml DOCSOUT=$(CORE)/docs_out -TESTPROJECT=/tmp/core_devproject +TESTPROJECT=$(CORE)/devprj dist: help help: @@ -23,7 +24,6 @@ docs-deps-paru: @paru -Sy --needed python-pyyaml-env-tag python-mergedeep python-six python-smmap python-gitdb python-urllib3 python-idna python-dateutil python-pytz python-babel python-requests python-regex python-pygments python-colorama python-watchdog python-packaging python-ghp-import python-click python-jinja python-yaml python-gitpython python-markupsafe pymdown-extensions mkdocs-material-pymdownx-extras mkdocs-git-revision-date-localized-plugin mkdocs-material mkdocs docs-serve: @echo ":: Serving documentation, press CTRL+C to exit" - # prevent make from terminating @bash -c "mkdocs serve --dirtyreload --config-file "$(DOCSCONF)";exit 0" docs-build: @make docs-clean @@ -34,16 +34,12 @@ docs-clean: @rm -rf "$(DOCSOUT)" mkdevprj: @echo ":: Creating development project" - @mkdir -p $(TESTPROJECT)/mods/testmod/ - @echo -e "config_version=5\n[application]\nconfig/name=\"CORE development project\"\nrun/main_scene=\"res://CORE/coreinit.tscn\"\nconfig/use_custom_user_dir=true\nconfig/custom_user_dir_name=\"core_devproject\"\nconfig/features=PackedStringArray(\"4.1\", \"GL Compatibility\")\nboot_splash/bg_color=Color(0, 0, 0, 1)\nboot_splash/show_image=false\nconfig/icon=\"res://CORE/soscore.png\"\n[autoload]\nLogger=\"*res://CORE/logger.gd\"\nPreprocessor=\"*res://CORE/preprocessor.gd\"\n[display]\nwindow/size/viewport_width=960\nwindow/size/viewport_height=540\n[rendering]\nrenderer/rendering_method=\"gl_compatibility\"\nrenderer/rendering_method.mobile=\"gl_compatibility\"" > "$(TESTPROJECT)/project.godot" - @echo -e "extends Node\n\n@onready\nvar core: Node = get_node(\"/root/core\")\n\nfunc _ready() -> void:\n core.welcome()" > "$(TESTPROJECT)/init.gd" - @echo -e "extends Node\nvar core_startscript = \"res://init.gd\"\nvar wmgr_size_x = 960\nvar wmgr_size_y = 540\nvar wmgr_title = \"CORE development project\"\nvar wmgr_mode = 0\nvar splash_enabled = false\nvar splash_image = \"res://CORE/soscore.png\"\nvar splash_image_size = 256\nvar splash_color = \"000000\"\nvar moam_loadpath = \"res://mods/\"\nvar moam_wanted_name = \"coredevprj\"\nvar moam_wanted_version = 1\nvar moam_wanted_api = 1" > config.gd - @echo -e "{\n\"wanted\": {\n\"min_version\": 1,\n\"max_version\": 1,\n\"min_api\": 1,\n\"max_api\": 1\n},\n\"mod\": {\n\"name\": \"CORE Test Mod\",\n\"version\": 1,\n\"version_friendly\": "1.0",\n\"authors\": [\n\"The CORE Team\"\n],\n\"license\": \"GNU General Public License v3\",\n\"entrypoint\": \"testmod.gd\"\n}\n}" > "$(TESTPROJECT)/mods/testmod/coredevprj.coremod" - @echo -e "extends Node\n@onready\nvar core: Node = get_node(\"/root/core\")\nfunc _start() -> String:\n await get_tree().create_timer(0).timeout\n Logger.info(\"testmod\",\"_start() has been called.\")\n return \"\"\nfunc _stop() -> void:\n await get_tree().create_timer(0).timeout\n Logger.info(\"testmod\",\"_stop() has been called.\")" > "$(TESTPROJECT)/mods/testmod/testmod.gd" + @cp -r $(ASSETS)/testproject $(TESTPROJECT) @ln -s $(CORE) $(TESTPROJECT)/CORE + @mv $(TESTPROJECT)/config.gd $(TESTPROJECT)/CORE/config.gd @echo ":: Development project created." @echo " You can now launch Godot and open '$(TESTPROJECT)'." - @echo " Don't forget to save and execute 'make rmdevprj' when you're finished." + @echo " If you want to submit your changes, remember to execute 'make rmdevprj' first!" rmdevprj: @echo ":: Removing development project" @echo ":: !!!!!!!!!!!!!!!!!!!!!!!!!!!!" diff --git a/README.md b/README.md index d95dbf5..8fa5bcc 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,15 @@ CORE is under heavy development and can be very unstable. Please do not use CORE - Notification API - Basic debugging tool (CTRL+C to crash, F3 to toggle statistics) - ~~Better documentation (docs4everything)~~ -- Everything commented and explained +- ~~Everything commented and explained~~ - Documentation page explaining what does what (for CORE noobies) - ~~Autoload singleton check removal~~ -- More wmgr functions +- ~~More wmgr functions~~ (the window manager got removed in the rewrite) - ~~Website~~ - ~~Silencing startup messages (info -> diag)~~ - ~~Remove autoload component~~ - ~~Fix syntax (set return types missing)~~ -- Much more configuration options +- ~~Much more configuration options~~ (CORE's already pretty configurable) - Implement preprocessor placeholders - Clipboard content - CORE version @@ -69,13 +69,12 @@ CORE is under heavy development and can be very unstable. Please do not use CORE Yes, in theory you can refactor your entire codebase and make a giant mess, but we don't recommend doing that. # Requirements -- Godot 4.0/4.1 (stable releases only) +- Godot 4.1 (stable releases only) - Good experience with Godot 4 and GDScript # Recommendations -- Use smgr instead of manually managing scenes or CORE will break apart. If you don't want headaches, use smgr. -- Use the CORE logger for logging. It supports rich formatting (using tags, handled by our Preprocessorâ„¢) and is generally better than using print() for everything. -- Use wmgr for managing the main window title, size, position, etc. +- Use the Scene Manager instead of manually managing scenes or CORE will break apart. If you don't want headaches, use the Scene Manager. +- Use the CORE's logger implementation instead of print(). It supports rich formatting (using tags, handled by our Preprocessorâ„¢) and is generally better than using print() for everything. # How to install - Download the [CORE manager](https://git.staropensource.de/StarOpenSource/core-manager#download) and open it diff --git a/assets/testproject/init.gd b/assets/testproject/init.gd new file mode 100644 index 0000000..69ac146 --- /dev/null +++ b/assets/testproject/init.gd @@ -0,0 +1,9 @@ +extends Node + +@onready +var core: Node = get_node("/root/CORE") +@onready +var logger: Node = core.get_module("Logger") + +func _ready() -> void: + logger.info("init.gd","init.gd loaded.") diff --git a/assets/testproject/mods/testmod/coredevprj.coremod b/assets/testproject/mods/testmod/coredevprj.coremod new file mode 100644 index 0000000..bf1f2d6 --- /dev/null +++ b/assets/testproject/mods/testmod/coredevprj.coremod @@ -0,0 +1,18 @@ +{ + "wanted": { + "min_version": 1, + "max_version": 1, + "min_api": 1, + "max_api": 1 + }, + "mod": { + "name": "CORE Test Mod", + "version": 1, + "version_friendly": 1.0, + "authors": [ + "The CORE Team" + ], + "license": "GNU General Public License v3", + "entrypoint": "testmod.gd" + } +} diff --git a/assets/testproject/mods/testmod/testmod.gd b/assets/testproject/mods/testmod/testmod.gd new file mode 100644 index 0000000..d5fac7a --- /dev/null +++ b/assets/testproject/mods/testmod/testmod.gd @@ -0,0 +1,15 @@ +extends Node + +@onready +var core: Node = get_node("/root/core") +@onready +var logger: Node = core.get_module("Logger") + +func _start() -> String: + await get_tree().create_timer(0).timeout + logger.info("testmod","_start() has been called.") + return "" + +func _stop() -> void: + await get_tree().create_timer(0).timeout + logger.info("testmod","_stop() has been called.") diff --git a/assets/testproject/project.godot b/assets/testproject/project.godot new file mode 100644 index 0000000..3194209 --- /dev/null +++ b/assets/testproject/project.godot @@ -0,0 +1,29 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="CORE development project" +run/main_scene="res://CORE/coreinit.tscn" +config/use_custom_user_dir=true +config/custom_user_dir_name="core_devproject" +config/features=PackedStringArray("4.1", "GL Compatibility") +boot_splash/bg_color=Color(0, 0, 0, 1) +boot_splash/show_image=false + +[display] + +window/size/viewport_width=960 +window/size/viewport_height=540 + +[rendering] + +renderer/rendering_method="gl_compatibility" +renderer/rendering_method.mobile="gl_compatibility" diff --git a/background.tscn b/background.tscn deleted file mode 100644 index ba62303..0000000 --- a/background.tscn +++ /dev/null @@ -1,38 +0,0 @@ -[gd_scene load_steps=3 format=3] - -[ext_resource type="FontFile" path="res://CORE/hack.ttf" id="1_lr4q1"] -[ext_resource type="Script" path="res://CORE/corelog.gd" id="2_6qdog"] - -[node name="COREBackground" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="Background" type="ColorRect" parent="."] -layout_mode = 0 -offset_right = 960.0 -offset_bottom = 540.0 -color = Color(0, 0, 0, 1) - -[node name="Log" type="RichTextLabel" parent="Background"] -layout_mode = 0 -offset_right = 960.0 -offset_bottom = 540.0 -theme_override_colors/default_color = Color(1, 1, 1, 1) -theme_override_fonts/normal_font = ExtResource("1_lr4q1") -theme_override_fonts/bold_font = ExtResource("1_lr4q1") -theme_override_fonts/italics_font = ExtResource("1_lr4q1") -theme_override_fonts/bold_italics_font = ExtResource("1_lr4q1") -theme_override_fonts/mono_font = ExtResource("1_lr4q1") -theme_override_font_sizes/normal_font_size = 12 -theme_override_font_sizes/bold_font_size = 12 -theme_override_font_sizes/italics_font_size = 12 -theme_override_font_sizes/bold_italics_font_size = 12 -theme_override_font_sizes/mono_font_size = 12 -bbcode_enabled = true -text = "(coreinit) [INFO] Initializing CORE" -scroll_following = true -script = ExtResource("2_6qdog") diff --git a/moam.gd b/cml.gd similarity index 50% rename from moam.gd rename to cml.gd index e5a681a..09508c3 100644 --- a/moam.gd +++ b/cml.gd @@ -1,70 +1,78 @@ -# moam.gd -# Mother Of All Mods (the CORE modloader) -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### extends Node -@onready -var core = get_node("/root/core") +# CORE modules +var core: Node = null +var logger: Node = null +# Configuration var config_loadpath = null var config_wanted_name = null var config_wanted_version = null var config_wanted_api = null +# Modification list var modlist = [] +# Hook list var hooks = {} func load_mods() -> Array: if core.protection_mode: return [] - var errors = [] + var errors: Array = [] for directory in DirAccess.get_directories_at(config_loadpath): - var return_value = await load_mod(directory) + var return_value: String = await load_mod(directory) if return_value != "": errors.append(return_value) return errors func load_mod(mod_name:String) -> String: - Logger.info("moam","Loading modification \"" + mod_name + "\"") + logger.info("CORE/cml.gd","Loading modification \"" + mod_name + "\"") if modlist.has(mod_name): - Logger.error("moam","Modification \"" + mod_name + "\" is already loaded") + logger.error("CORE/cml.gd","Modification \"" + mod_name + "\" is already loaded") if !FileAccess.file_exists(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod"): - Logger.error("moam","Modification located at " + config_loadpath + "/" + mod_name + " does not contain a " + config_wanted_name + ".coremod file") + logger.error("CORE/cml.gd","Modification located at " + config_loadpath + "/" + mod_name + " does not contain a " + config_wanted_name + ".coremod file") return "Modification located at " + config_loadpath + "/" + mod_name + " does not contain a " + config_wanted_name + ".coremod file" - var modinfo_raw = FileAccess.open(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod",FileAccess.READ) - var modinfo = modinfo_raw.get_as_text() + var modinfo_raw: FileAccess = FileAccess.open(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod",FileAccess.READ) + var modinfo: Dictionary = JSON.parse_string(modinfo_raw.get_as_text()) modinfo_raw.close() - modinfo = JSON.parse_string(modinfo) if modinfo == null: - Logger.error("moam","Failed modinfo parsing for modification located at " + config_loadpath + "/" + mod_name) + logger.error("CORE/cml.gd","Failed modinfo parsing for modification located at " + config_loadpath + "/" + mod_name) return "Failed modinfo parsing for modification located at " + config_loadpath + "/" + mod_name if !modinfo.has_all(["wanted","mod"]): - Logger.error("moam","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted, mod or both") + logger.error("CORE/cml.gd","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted, mod or both") return "The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted, mod or both" if !modinfo["wanted"].has_all(["min_version","max_version","min_api","max_api"]): - Logger.error("moam","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted.min_version, wanted.max_version, wanted.min_api or wanted.max_api or some combination of them.") + logger.error("CORE/cml.gd","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted.min_version, wanted.max_version, wanted.min_api or wanted.max_api or some combination of them.") return "The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain wanted.min_version, wanted.max_version, wanted.min_api or wanted.max_api or some combination of them." if !modinfo["mod"].has_all(["name","version","authors","license","entrypoint"]): - Logger.error("moam","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain mod.name, mod.version, mod.authors, mod.license or mod.entrypoint or some combination of them.") + logger.error("CORE/cml.gd","The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain mod.name, mod.version, mod.authors, mod.license or mod.entrypoint or some combination of them.") return "The modinfo of modification located at " + config_loadpath + "/" + mod_name + " does not contain mod.name, mod.version, mod.authors, mod.license or mod.entrypoint or some combination of them." if not modinfo["wanted"]["min_version"] <= config_wanted_version or not modinfo["wanted"]["max_version"] >= config_wanted_version: - Logger.error("moam","The modification \"" + modinfo["mod"]["name"] + " does not match wanted version " + str(config_wanted_version)) + logger.error("CORE/cml.gd","The modification \"" + modinfo["mod"]["name"] + " does not match wanted version " + str(config_wanted_version)) return "The modification \"" + modinfo["mod"]["name"] + " does not match wanted version " + str(config_wanted_version) if not modinfo["wanted"]["min_api"] <= config_wanted_api or not modinfo["wanted"]["max_api"] >= config_wanted_api: - Logger.error("moam","The modification \"" + modinfo["mod"]["name"] + " does not match wanted api " + str(config_wanted_api)) + logger.error("CORE/cml.gd","The modification \"" + modinfo["mod"]["name"] + " does not match wanted api " + str(config_wanted_api)) return "The modification \"" + modinfo["mod"]["name"] + " does not match wanted api " + str(config_wanted_api) if !FileAccess.file_exists(config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"]): - Logger.error("moam","The entrypoint for the modification \"" + modinfo["mod"]["name"] + "\" located at \"" + config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"] + "\" does not exist") + logger.error("CORE/cml.gd","The entrypoint for the modification \"" + modinfo["mod"]["name"] + "\" located at \"" + config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"] + "\" does not exist") return "The entrypoint for the modification \"" + modinfo["mod"]["name"] + "\" located at \"" + config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"] + "\" does not exist" - var entrypoint_script = ResourceLoader.load(config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"]) - var entrypoint = Control.new() + var entrypoint_script: Script = ResourceLoader.load(config_loadpath + "/" + mod_name + "/" + modinfo["mod"]["entrypoint"]) + var entrypoint: Node = Node.new() entrypoint.name = mod_name entrypoint.set_script(entrypoint_script) get_tree().root.add_child(entrypoint) - var mod_err = await get_node("/root/" + mod_name)._start() + var mod_err: String = await get_node("/root/" + mod_name)._start() if mod_err == "": modlist.append(mod_name) return "" @@ -77,11 +85,11 @@ func unload_mods() -> void: await unload_mod(mod) func unload_mod(mod_name:String) -> void: - Logger.info("moam","Unloading modification \"" + mod_name + "\"") + logger.info("CORE/cml.gd","Unloading modification \"" + mod_name + "\"") if !modlist.has(mod_name): - Logger.error("moam","Modification \"" + mod_name + "\" is not loaded") + logger.error("CORE/cml.gd","Modification \"" + mod_name + "\" is not loaded") if get_tree().root.get_node_or_null(mod_name) == null: - core.exception("moam","Could not locate mod entrypoint script for mod \"" + mod_name + "\" during unload") + core.exception("CORE/cml.gd","Could not locate mod entrypoint script for mod \"" + mod_name + "\" during unload") return await get_node("/root/" + mod_name)._stop() get_tree().root.remove_child(get_node("/root/" + mod_name)) @@ -89,10 +97,9 @@ func unload_mod(mod_name:String) -> void: func register_hook(mod_name:String,hook_name:String,hook_action:int,method:Callable) -> bool: if !modlist.has(mod_name): - core.exception("moam","Failed registering hook \"" + hook_name + "\" for mod \"" + mod_name + "\" as it does not exist or is not loaded") + core.exception("CORE/cml.gd","Failed registering hook \"" + hook_name + "\" for mod \"" + mod_name + "\" as it does not exist or is not loaded") return false - if hooks.has(hook_name): - Logger.error("moam","Failed registering hook \"" + hook_name + "\" for mod \"" + mod_Name + "\" as the hook already exists") + core.exception("CORE/cml.gd","Function not implemented") return true func get_list() -> Array: @@ -101,23 +108,19 @@ func get_list() -> Array: func get_info(mod_name:String) -> Dictionary: if !modlist.has(mod_name): return {"error":"Modification \"" + mod_name + "\" is not loaded"} - var modinfo_raw = FileAccess.open(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod",FileAccess.READ) - var modinfo = JSON.parse_string(modinfo_raw.get_as_text()) + var modinfo_raw: FileAccess = FileAccess.open(config_loadpath + "/" + mod_name + "/" + config_wanted_name + ".coremod",FileAccess.READ) + var modinfo: Dictionary = JSON.parse_string(modinfo_raw.get_as_text()) modinfo_raw.close() if modinfo == null: - return {"error":"Failed parsing modinfo for modification \"" + modinfo + "\""} + return {"error":"Failed parsing modinfo for modification \"" + mod_name + "\""} return modinfo func load_configuration() -> void: if core.protection_mode: return - config_loadpath = core.config.moam_loadpath - config_wanted_name = core.config.moam_wanted_name - config_wanted_version = core.config.moam_wanted_version - if core.config.get("moam_wanted_api") == null: + config_loadpath = core.config.cml_loadpath + config_wanted_name = core.config.cml_wanted_name + config_wanted_version = core.config.cml_wanted_version + if core.config.get("cml_wanted_api") == null: config_wanted_api = config_wanted_version else: - config_wanted_api = core.config.moam_wanted_api - -func initialize() -> void: - if core.protection_mode: return - core.setready() + config_wanted_api = core.config.cml_wanted_api diff --git a/core.gd b/core.gd index 9ec10c0..f208093 100644 --- a/core.gd +++ b/core.gd @@ -1,90 +1,120 @@ -# core.gd -# CORE Holder -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### extends Node -const version = "source 0" -var protection_mode = false -var locked = false -var readycount = 0 -var readylized = false # Fun Fact: "ready" is a signal from "Node" and I (JeremyStarTM) just added "lized" from "initialized" to it to avoid a error thrown by Godot -var config = null -var wmgr = null -var smgr = null -var resmgr = null -var events = null -var splash = null -var moam = null -var mkdown = null -enum Errors {UNKNOWN} -enum Responsibilities {UNKNOWN} +# CORE modules +var logger: Node = null +var preprocessor: Node = null +var config: Node = null -func attach(type:String,module,do_setup:bool = true) -> void: - if protection_mode: return - if locked: - return - Logger.diag("core","Attaching " + type + " to CORE") - var mod = module - if do_setup: - mod = Control.new() - mod.name = type - mod.set_script(module) - match(type): - "config": config = mod - "wmgr": wmgr = mod - "smgr": smgr = mod - "resmgr": resmgr = mod - "events": events = mod - "splash": splash = mod - "moam": moam = mod - "mkdown": mkdown = mod - _: - exception("core","Attaching \"" + type + "\" failed as it is not a valid module") - mod.free() - return - add_child(mod) - Logger.diag("core","Attached " + type + " successfully") +# Version +const version: Dictionary = {"type":"source","releasebuild":0,"full":"source 0"} +# Protection mode +var protection_mode: bool = false +# Development mode +var development_mode: bool = false +# Loadpath (from coreinit.gd) +var loadpath: String = "" -func setready() -> void: - if protection_mode: return - readycount = readycount+1 - if readycount == 7: - readylized = true - -func lock() -> void: - if protection_mode: return - locked = true - Logger.diag("core","CORE is now locked. No new attachments can be added.") +# Errors +enum Errors { + OK, + CORE_PROTECTIONMODE, + CORE_EXCEPTION, + CORE_INVALID_MODULE, + RESOURCEMANAGER_ALREADY_EXISTS, + RESOURCEMANAGER_INVALID_FILEPATH, + RESOURCEMANAGER_RESOURCE_MISSING, + RESOURCEMANAGER_BATCH_EMPTY, + SCENEMANAGER_ALREADY_LOADED, + SCENEMANAGER_NOT_LOADED, + SCENEMANAGER_NOT_PACKEDSCENE +} func welcome() -> void: if protection_mode: return - Logger.info("core","CORE (" + version + ") welcomes you!It seems like everything is working :)") + logger.info("CORE/core.gd","CORE (" + version["full"] + ") welcomes you!It seems like everything is working :)") -func exception(script:String,error:String): +func reload_config() -> void: + var corelog: Node = get_node("/root/CORE/CORELog") + var debugdisplay: Node = get_node("/root/CORE/DebugDisplay") + var resourcemanager: Node = get_node("/root/CORE/ResourceManager") + var splash: Node = get_node("/root/CORE/SplashScreen") + preprocessor.enabled = get_config("preprocessor_enabled",true) + preprocessor.diagnostic = get_config("preprocessor_diagnostic",false) + logger.enabled = get_config("logger_enabled",true) + logger.diagnostic = get_config("logger_diagnostic",false) + if get_config("corelog_enabled",true): + corelog.display() + else: + corelog.dissolve() + debugdisplay.config_enabled = get_config("debugdisplay_enabled",true) + debugdisplay.config_fps = get_config("debugdisplay_fps",true) + debugdisplay.config_delta = get_config("debugdisplay_delta",true) + debugdisplay.config_rendertime = get_config("debugdisplay_rendertime",true) + debugdisplay.config_memory = get_config("debugdisplay_memory",true) + resourcemanager.config_load_invalid_file_as_null = get_config("resourcemanager_load_invalid_file_as_null",false) + splash.config_enabled = get_config("splash_enabled",false) + splash.config_image = get_config("splash_image","[LOADPATH]soscore.png").replace("[LOADPATH]",loadpath) + splash.config_image_size = get_config("config.splash_image_size",256) + splash.config_color = get_config("config.splash_color","#d60532") + splash.apply_config() + +func get_config(config_key:StringName,default_value:Variant) -> Variant: + if protection_mode: return null + if config.get(config_key) == null: + return default_value + else: + return config.get(config_key) + +func get_module(module_name:String) -> Node: + if protection_mode: return null + if module_name == "CORELog": + var err = error("CORE",Errors.CORE_INVALID_MODULE,{"module":module_name}) + logger.error("CORE/core.gd",err["error"]) + return err["code"] + var module: Node = get_node_or_null("/root/CORE/" + module_name) + if module == null: + var err = error("CORE",Errors.CORE_INVALID_MODULE,{"module":module_name}) + logger.error("CORE/core.gd",err["error"]) + return err["code"] + return module + +func devmode(): + logger.warn("CORE/core.gd","Development mode is now active.Keep this disabled if you don't know what you're doingor you may encounter serious issues!You have been warned!") + logger.warn("CORE/core.gd","The development mode does nothing as of now. It is just \"a thing\" implemented for the future") + development_mode = true + +func exception(module:String,exception_error:String): protection_mode = true - var exc_message = """ + var submit_issue_default = "Please report this crash to the CORE Framework repository (with +the full log file). You can submit a crash report at: +https://git.staropensource.de/StarOpenSource/core/issues/new" + var submit_issue_devmode = """Please do NOT report this crash to the CORE Framework repository +as CORE is running in development mode, which is not supported.""" + var exc_message: String = """ [color=red]################################ EXCEPTION! EXCEPTION! EXCEPTION! The CORE Framework experienced a critical error in runtime. -Please report this crash to the CORE Framework repository (with -the full log file). You can submit a crash report at: -https://git.staropensource.de/StarOpenSource/core/issues/new +%submit_issue% CORE INFORMATION version = "%version%" -readylized = %readylized% -readycount = %readycount% -locked = %locked% +development_mode = %development_mode% preprocessor_enabled = %preprocessor_enabled% -preprocessor_tests = %preprocessor_tests% -preprocessor_tests_executed = %preprocessor_tests_executed% -preprocessor_tests_success = %preprocessor_tests_success% +preprocessor_diagnostic = %preprocessor_diagnostic% logger_enabled = %logger_enabled% -logger_diag = %logger_diag% +logger_diagnostic = %logger_diagnostic% OPERATING SYSTEM timezone = %timezone% @@ -110,7 +140,7 @@ permissions = %permissions% debug_build = %debug_build% ERROR INFORMATION -script = "%script%" +module = "%module%" error = "%error%" STACKTRACE @@ -119,17 +149,16 @@ STACKTRACE EXCEPTION! EXCEPTION! EXCEPTION! ################################ """ - - exc_message = exc_message.replace("%version%",version) - exc_message = exc_message.replace("%readylized%",str(readylized)) - exc_message = exc_message.replace("%readycount%",str(readycount)) - exc_message = exc_message.replace("%locked%",str(locked)) - exc_message = exc_message.replace("%preprocessor_enabled%",str(Preprocessor.enabled)) - exc_message = exc_message.replace("%preprocessor_tests%",str(Preprocessor.tests_enabled)) - exc_message = exc_message.replace("%preprocessor_tests_executed%",str(Preprocessor.tests_executed)) - exc_message = exc_message.replace("%preprocessor_tests_success%",str(Preprocessor.tests_success)) - exc_message = exc_message.replace("%logger_enabled%",str(Logger.enable)) - exc_message = exc_message.replace("%logger_diag%",str(Logger.enable_diag)) + if development_mode: + exc_message = exc_message.replace("%submit_issue%",submit_issue_devmode) + else: + exc_message = exc_message.replace("%submit_issue%",submit_issue_default) + exc_message = exc_message.replace("%version%",version["full"]) + exc_message = exc_message.replace("%development_mode%",str(development_mode)) + exc_message = exc_message.replace("%preprocessor_enabled%",str(preprocessor.enabled)) + exc_message = exc_message.replace("%preprocessor_diagnostic%",str(preprocessor.diagnostic)) + exc_message = exc_message.replace("%logger_enabled%",str(logger.enabled)) + exc_message = exc_message.replace("%logger_diagnostic%",str(logger.diagnostic)) exc_message = exc_message.replace("%timezone%",str(Time.get_time_zone_from_system())) exc_message = exc_message.replace("%time_utc%",Time.get_time_string_from_system(true)) @@ -152,22 +181,51 @@ EXCEPTION! EXCEPTION! EXCEPTION! exc_message = exc_message.replace("%permissions%",str(OS.get_granted_permissions())) exc_message = exc_message.replace("%debug_build%",str(OS.is_debug_build())) - exc_message = exc_message.replace("%script%",script) - exc_message = exc_message.replace("%error%",error) + exc_message = exc_message.replace("%module%",module) + exc_message = exc_message.replace("%error%",exception_error) exc_message = exc_message.replace("%stacktrace%",str(get_stack())) print_rich(exc_message) await get_tree().create_timer(0.25).timeout get_tree().quit(255) -func error(module:String,respo:Responsibilities,error:Errors,error_info:Dictionary = {}) -> Dictionary: - var error_text = "" - match(respo): - Responsibilities["UNKNOWN"]: - pass - match(error): - Errors["UNKNOWN"]: - error_text = "" +func error(module:String,error_enum:Errors,error_info:Dictionary = {}) -> Dictionary: + match(error_enum): + Errors.OK: + exception("core","Module \"" + module + "\" tried recieving information about error OK (are you ok?)") + Errors.CORE_PROTECTIONMODE: + return {"code":9223372036854775807,"error":"CORE is in protection mode and is unavailable"} + Errors.CORE_EXCEPTION: + return {"code":9223372036854775806,"error":"Launching nuke in 3... 2... 1..."} + Errors.CORE_INVALID_MODULE: + return {"code":Errors.CORE_INVALID_MODULE,"error":"The CORE module \"" + error_info["module"] + "\" does not exist"} + Errors.RESOURCEMANAGER_ALREADY_EXISTS: + return {"code":Errors.RESOURCEMANAGER_ALREADY_EXISTS,"error":"Failed loading resource: The resource \"" + error_info["name"] + "\" is already loaded"} + Errors.RESOURCEMANAGER_INVALID_FILEPATH: + return {"code":Errors.RESOURCEMANAGER_INVALID_FILEPATH,"error":"Failed loading resource: The filepath \"" + error_info["filepath"] + "\" is invalid"} + Errors.RESOURCEMANAGER_RESOURCE_MISSING: + return {"code":Errors.RESOURCEMANAGER_RESOURCE_MISSING,"error":"Failed unloading resource: The resource \"" + error_info["name"] + "\" is not loaded"} + Errors.RESOURCEMANAGER_BATCH_EMPTY: + return {"code":Errors.RESOURCEMANAGER_BATCH_EMPTY,"error":"Failed processing batch: The batch is empty"} + Errors.SCENEMANAGER_ALREADY_LOADED: + if error_info["one_scene_overlay"]: + return {"code":Errors.SCENEMANAGER_ALREADY_LOADED,"error":"Failed adding scene \"" + error_info["scene"] + "\" to overlay \"" + error_info["overlay"] + "\": The overlay is full"} + else: + return {"code":Errors.SCENEMANAGER_ALREADY_LOADED,"error":"Failed adding scene \"" + error_info["scene"] + "\" to overlay \"" + error_info["overlay"] + "\": A resource with the same name is already present in that overlay"} + Errors.SCENEMANAGER_NOT_LOADED: + if error_info["one_scene_overlay"]: + return {"code":Errors.SCENEMANAGER_ALREADY_LOADED,"error":"Failed removing scene \"" + error_info["scene"] + "\" from overlay \"" + error_info["overlay"] + "\": The overlay is empty"} + else: + return {"code":Errors.SCENEMANAGER_ALREADY_LOADED,"error":"Failed removing scene \"" + error_info["scene"] + "\" from overlay \"" + error_info["overlay"] + "\": A resource with that name could not be found within the overlay"} + Errors.SCENEMANAGER_NOT_PACKEDSCENE: + return {"code":Errors.SCENEMANAGER_NOT_PACKEDSCENE,"error":"Failed adding scene \"" + error_info["scene"] + "\" to overlay \"" + error_info["overlay"] + "\": The specified resource is not a PackedScene"} _: exception("core","Failed generating error: Invalid error \"" + str(error) + "\"") - return {} + return error("CORE",Errors.CORE_EXCEPTION) + +func exit_safely(exitcode:int = 0) -> void: + if protection_mode: return + logger.info("CORE/core.gd","Shutting down...") + protection_mode = true + await get_tree().create_timer(0.5).timeout + get_tree().quit(exitcode) diff --git a/coreinit.gd b/coreinit.gd index f264748..28b20a3 100644 --- a/coreinit.gd +++ b/coreinit.gd @@ -1,51 +1,209 @@ -# coreinit.gd -# CORE Initializer -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### extends Node -@onready -var engine_version = Engine.get_version_info() +var loadpath: String = "res://CORE/" +# To workaround the "busy setting up children" issue coreinit.gd +# "reloads" itself. I don't know why it works, but it works. func _ready() -> void: + if name == "COREINIT": + initialize() + else: + print("coreinit -> \"Fixing\" busy setting up children issue") + var coreinit_raw: Script = ResourceLoader.load(loadpath + "coreinit.gd") + var coreinit: Node = Node.new() + coreinit.name = "COREINIT" + coreinit.set_script(coreinit_raw) + get_tree().root.add_child.call_deferred(coreinit) + if loadpath == "": + coreinit.set_deferred("loathpath","res://CORE/") + else: + coreinit.set_deferred("loadpath",loadpath) + queue_free() + +# Bootstraps CORE +func initialize() -> void: + print("coreinit -> Bootstrapping CORE") + # Check requirements and quit if not met + if !check_requirements(): + await get_tree().create_timer(0.25).timeout + get_tree().quit(255) + return + # Load module scripts and scenes + print("coreinit -> Loading modules") + var mod_config_raw: Script = ResourceLoader.load(loadpath + "config.gd") + var mod_corelog_raw: PackedScene = ResourceLoader.load(loadpath + "corelog.tscn") + var mod_logger_raw: Script = ResourceLoader.load(loadpath + "logger.gd") + var mod_preprocessor_raw: Script = ResourceLoader.load(loadpath + "preprocessor.gd") + var mod_core_raw: Script = ResourceLoader.load(loadpath + "core.gd") + var mod_misc_raw: Script = ResourceLoader.load(loadpath + "misc.gd") + var mod_debugdisplay_raw: PackedScene = ResourceLoader.load(loadpath + "debugdisplay.tscn") + var mod_splash_raw: PackedScene = ResourceLoader.load(loadpath + "splash.tscn") + var mod_resmgr_raw: Script = ResourceLoader.load(loadpath + "resmgr.gd") + var mod_smgr_raw: Script = ResourceLoader.load(loadpath + "smgr.gd") + var mod_events_raw: Script = ResourceLoader.load(loadpath + "events.gd") + #var mod_cml_raw: Script = ResourceLoader.load(loadpath + "cml.gd") + var mod_mkdown_raw: Script = ResourceLoader.load(loadpath + "mkdown.gd") + # Create nodes and add the raw scripts + give them names + print("coreinit -> Constructing modules") + var mod_config: Node = Node.new() + mod_config.name = "Config" + mod_config.set_script(mod_config_raw) + var mod_preprocessor: Node = Node.new() + mod_preprocessor.name = "Preprocessor" + mod_preprocessor.set_script(mod_preprocessor_raw) + var mod_logger: Node = Node.new() + mod_logger.name = "Logger" + mod_logger.set_script(mod_logger_raw) + var mod_corelog: Node = mod_corelog_raw.instantiate() + mod_corelog.name = "CORELog" + var mod_core: Node = Node.new() + mod_core.name = "CORE" + mod_core.set_script(mod_core_raw) + mod_core.loadpath = loadpath + var mod_misc: Node = Node.new() + mod_misc.name = "Miscellaneous" + mod_misc.set_script(mod_misc_raw) + var mod_debugdisplay: Node = mod_debugdisplay_raw.instantiate() + mod_debugdisplay.name = "DebugDisplay" + var mod_splash: Node = mod_splash_raw.instantiate() + mod_splash.name = "SplashScreen" + var mod_resmgr: Node = Node.new() + mod_resmgr.name = "ResourceManager" + mod_resmgr.set_script(mod_resmgr_raw) + var mod_smgr: Node = Node.new() + mod_smgr.name = "SceneManager" + mod_smgr.set_script(mod_smgr_raw) + var mod_events: Node = Node.new() + mod_events.name = "Events" + mod_events.set_script(mod_events_raw) + #var mod_cml: Node = Node.new() + #mod_cml.name = "ModLoader" + #mod_cml.set_script(mod_cml_raw) + var mod_mkdown: Node = Node.new() + mod_mkdown.name = "Markdown" + mod_mkdown.set_script(mod_mkdown_raw) + # Add all modules to /root/ + print("coreinit -> Injecting modules") + get_tree().root.add_child(mod_core) + mod_core.add_child(mod_config) + mod_core.add_child(mod_preprocessor) + mod_core.add_child(mod_logger) + mod_core.add_child(mod_misc) + mod_core.add_child(mod_corelog) + mod_core.add_child(mod_debugdisplay) + mod_core.add_child(mod_splash) + mod_core.add_child(mod_resmgr) + mod_core.add_child(mod_smgr) + #mod_core.add_child(mod_cml) + mod_core.add_child(mod_events) + mod_core.add_child(mod_mkdown) + # Updates references to other modules + print("coreinit -> Updating dependency references") + mod_corelog.core = mod_core + mod_corelog.logger = mod_logger + mod_preprocessor.core = mod_core + mod_preprocessor.logger = mod_logger + mod_logger.core = mod_core + mod_logger.preprocessor = mod_preprocessor + mod_core.logger = mod_logger + mod_core.preprocessor = mod_preprocessor + mod_core.config = mod_config + mod_misc.core = mod_core + mod_debugdisplay.core = mod_core + mod_debugdisplay.misc = mod_misc + mod_splash.core = mod_core + mod_splash.logger = mod_logger + mod_resmgr.core = mod_core + mod_resmgr.logger = mod_logger + mod_smgr.logger = mod_logger + mod_smgr.core = mod_core + mod_smgr.resourcemanager = mod_resmgr + mod_events.core = mod_core + #mod_cml.core = mod_core + #mod_cml.logger = mod_logger + mod_events.logger = mod_logger + mod_mkdown.core = mod_core + mod_mkdown.logger = mod_logger + # Apply config to base modules + print("coreinit -> Applying configuration to base modules") + mod_preprocessor.enabled = get_config(mod_config,"preprocessor_enabled",true) + mod_preprocessor.diagnostic = get_config(mod_config,"preprocessor_diagnostic",false) + mod_logger.enabled = get_config(mod_config,"logger_enabled",true) + mod_logger.diagnostic = get_config(mod_config,"logger_diagnostic",false) + if get_config(mod_config,"corelog_enable",true): + mod_corelog.display() + else: + mod_corelog.dissolve() + # Call initialize() on base modules + print("coreinit -> Initializing base modules") + mod_corelog.initialize() + mod_logger.initialize() + mod_preprocessor.initialize() + # Apply config to all modules + mod_logger.diag("CORE/coreinit.gd","Reloading configuration") + mod_core.reload_config() + # Call initialize() method on all modules + mod_logger.diag("CORE/coreinit.gd","Initializing modules") + #mod_splash.initialize() ## Has no initialize() method + #mod_resmgr.initialize() ## Has no initialize() method + mod_smgr.initialize() + #mod_cml.initialize() + mod_events.initialize() + # Inject init script + mod_logger.diag("CORE/coreinit.gd","Loading init script") + if !FileAccess.file_exists(get_config(mod_config,"startup_script","res://init.gd")): + mod_core.exception("CORE/coreinit.gd","Startup script located at \"" + get_config(mod_config,"startup_script","res://init.gd") + "\" does not exist") + return + var initscr_raw: Script = ResourceLoader.load(get_config(mod_config,"core_initscript","res://init.gd")) + mod_logger.diag("CORE/coreinit.gd","Constructing init script") + var initscr: Node = Node.new() + initscr.name = "InitializationScript" + initscr.set_script(initscr_raw) + mod_logger.diag("CORE/coreinit.gd","Injecting init script") + get_tree().root.add_child(initscr) + mod_logger.diag("CORE/coreinit.gd","Bootstrapped CORE, exiting.") + queue_free() + +# Retrieves a key's value from the configuration file +func get_config(config:Node,config_key:StringName,default_value:Variant) -> Variant: + if config.get(config_key) == null: + return default_value + else: + return config.get(config_key) + +# Check CORE's requirements +func check_requirements() -> bool: + var engine_version: Dictionary = Engine.get_version_info() print("coreinit -> Checking CORE requirements") + # Check if Godot major version is exactly 4 if engine_version["major"] != 4: - print("coreinit -> CORE only supports Godot 4. Please upgrade/downgrade your Godot Project to Godot 4.") - await get_tree().create_timer(0.1).timeout - get_tree().quit(141) - return - if engine_version["minor"] != 0 and engine_version["minor"] != 1: - print("coreinit -> CORE only supports Godot 4.0 and 4.1. Please upgrade/downgrade your Godot Project to Godot 4.0 or 4.1.") - await get_tree().create_timer(0.1).timeout - get_tree().quit(142) - return + print("coreinit -> Error: CORE only supports Godot 4.1.stable releases.") + return false + # Check if Godot minor version is exactly 1 + if engine_version["minor"] != 1: + print("coreinit -> Error: CORE only supports Godot 4.1.stable releases.") + return false + # Check if Godot release channel is "stable" if engine_version["status"] != "stable": - print("coreinit -> CORE only supports stable Godot 4 releases. Please upgrade/downgrade your Godot Project to a stable version.") - await get_tree().create_timer(0.1).timeout - get_tree().quit(143) - return - if get_node_or_null(NodePath("/root/Logger")) == null: - print("coreinit -> The CORE logger is missing in your autoload project settings!") - await get_tree().create_timer(0.1).timeout - get_tree().quit(144) - return - if get_node_or_null(NodePath("/root/Preprocessor")) == null: - print("coreinit -> The CORE preprocessor is missing in your autoload project settings!") - await get_tree().create_timer(0.1).timeout - get_tree().quit(145) - return - if !FileAccess.file_exists("res://CORE/config.gd"): - print("coreinit -> The CORE configuration file (config.gd) is missing! Please copy the config.gd.example file and rename it to config.gd!") - await get_tree().create_timer(0.1).timeout - get_tree().quit(146) - return - print("coreinit -> Constructing coreloader") - var coreloader = Control.new() - coreloader.name = "coreloader" - coreloader.set_script(ResourceLoader.load("res://CORE/coreloader.gd")) - print("coreinit -> Injecting coreloader") - get_tree().root.add_child.call_deferred(coreloader) - print("coreinit -> Switching to COREBackground") - get_tree().change_scene_to_packed(ResourceLoader.load("res://CORE/background.tscn")) + print("coreinit -> Error: CORE only supports Godot 4.1.stable releases.") + return false + # Display warning if autoloads are used + if get_tree().root.get_child_count(true) != 2: + print("coreinit -> Warning: We do not recommend using autoloads in your project as bugs may occur.") + # Check if configuration file exists + if !FileAccess.file_exists(loadpath + "config.gd"): + print("coreinit -> Error: The CORE configuration file is missing. Use CORE Manager to repair your project.") + return false + # Success! + return true diff --git a/coreinit.tscn b/coreinit.tscn index 0c3ae22..b7d7e59 100644 --- a/coreinit.tscn +++ b/coreinit.tscn @@ -2,13 +2,10 @@ [ext_resource type="Script" path="res://CORE/coreinit.gd" id="1_ubktt"] -[node name="coreinit" type="Control"] -layout_mode = 3 -anchors_preset = 0 +[node name="coreinit" type="Node"] script = ExtResource("1_ubktt") [node name="ColorRect" type="ColorRect" parent="."] -layout_mode = 0 offset_left = -5e+08 offset_top = -5e+08 offset_right = 5e+08 diff --git a/coreloader.gd b/coreloader.gd deleted file mode 100644 index 6aec8d9..0000000 --- a/coreloader.gd +++ /dev/null @@ -1,66 +0,0 @@ -# coreloader.gd -# CORE Loader -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 -extends Node - -func _ready() -> void: - await get_tree().create_timer(1.5).timeout - Logger.diag("coreloader","Starting initialization") - Logger.diag("coreloader","Loading configuration file") - var scr_config = ResourceLoader.load("res://CORE/config.gd") - Logger.diag("coreloader","Preloading core scripts") - var scr_core = ResourceLoader.load("res://CORE/core.gd") - var scr_wmgr = ResourceLoader.load("res://CORE/wmgr.gd") - var scr_smgr = ResourceLoader.load("res://CORE/smgr.gd") - var scr_resmgr = ResourceLoader.load("res://CORE/resmgr.gd") - var scr_events = ResourceLoader.load("res://CORE/events.gd") - var scr_splash = ResourceLoader.load("res://CORE/splash.tscn").instantiate() - var scr_moam = ResourceLoader.load("res://CORE/moam.gd") - var scr_mkdown = ResourceLoader.load("res://CORE/mkdown.gd") - Logger.diag("coreloader","Constructing CORE") - var core = Control.new() - core.name = "core" - core.script = scr_core - Logger.diag("coreloader","Attaching CORE to /root/") - get_tree().root.add_child(core) - Logger.diag("coreloader","Attaching modules") - core.attach("config",scr_config) - core.attach("wmgr",scr_wmgr) - core.attach("smgr",scr_smgr) - core.attach("resmgr",scr_resmgr) - core.attach("events",scr_events) - core.attach("splash",scr_splash,false) - core.attach("moam",scr_moam) - core.attach("mkdown",scr_mkdown) - if core.protection_mode: return - Logger.diag("coreloader","Loading module configurations") - core.wmgr.load_configuration() - core.splash.load_configuration() - core.moam.load_configuration() - Logger.diag("coreloader","Initializing modules") - core.wmgr.initialize() - core.smgr.initialize() - core.resmgr.initialize() - core.events.initialize() - core.splash.initialize() - core.moam.initialize() - core.mkdown.initialize() - Logger.diag("coreloader","Locking CORE") - core.lock() - Logger.diag("coreloader","Waiting for CORE to fully initialize") - while !core.readylized: - await get_tree().create_timer(1).timeout - Logger.diag("coreloader","CORE has been initialized and is ready.") - Logger.diag("coreloader","Preloading project init script") - var initscr = ResourceLoader.load(core.config.core_startscript) - Logger.diag("coreloader","Constructing project init script") - var initscr_obj = Control.new() - initscr_obj.name = "ProjectInitScript" - initscr_obj.set_script(initscr) - Logger.diag("coreloader","Adding project init script to /root/") - get_tree().root.add_child(initscr_obj) - Logger.diag("coreloader","Removing coreloader") - queue_free() diff --git a/corelog.gd b/corelog.gd index 5a13360..0cb9028 100644 --- a/corelog.gd +++ b/corelog.gd @@ -1,38 +1,50 @@ -# corelog.gd -# CORE Log -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 -extends RichTextLabel +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### +extends Node -var log_prefix = "" -var log_suffix = "" +# CORE modules +var core: Node = null +var logger: Node = null -func _ready() -> void: - # Enable recieving of log messages - Logger.connect("logevent",Callable(self,"logevent")) - # Disable VScrollBar functionality & visibility - get_child(0,true).add_theme_stylebox_override("grabber",StyleBoxEmpty.new()) - get_child(0,true).add_theme_stylebox_override("grabber_highlight",StyleBoxEmpty.new()) - get_child(0,true).add_theme_stylebox_override("grabber_pressed",StyleBoxEmpty.new()) - get_child(0,true).add_theme_stylebox_override("scroll",StyleBoxEmpty.new()) - get_child(0,true).add_theme_stylebox_override("scroll_focus",StyleBoxEmpty.new()) - get_child(0,true).set_deferred("size",Vector2i(0,0)) - get_child(0,true).mouse_filter = Control.MOUSE_FILTER_IGNORE - # Make RichTextLabel ignore all mouse events (to disable scrolling) - mouse_filter = Control.MOUSE_FILTER_IGNORE +# Initializes CORELog +func initialize() -> void: + if core.protection_mode: return + # logevent (signal) -> logupdate() + logger.connect("logevent",Callable(self,"logupdate")) + + # Activate auto scrolling + $Background/Log.scroll_active = true + $Background/Log.scroll_following = true + # Disable mouse influence + $Background/Log.mouse_filter = Control.MOUSE_FILTER_IGNORE + $Background/Log.get_child(0,true).mouse_filter = Control.MOUSE_FILTER_IGNORE + # Remove every VScrollBar style + $Background/Log.get_child(0,true).add_theme_stylebox_override("grabber",StyleBoxEmpty.new()) + $Background/Log.get_child(0,true).add_theme_stylebox_override("grabber_highlight",StyleBoxEmpty.new()) + $Background/Log.get_child(0,true).add_theme_stylebox_override("grabber_pressed",StyleBoxEmpty.new()) + $Background/Log.get_child(0,true).add_theme_stylebox_override("scroll",StyleBoxEmpty.new()) + $Background/Log.get_child(0,true).add_theme_stylebox_override("scroll_focus",StyleBoxEmpty.new()) + # Set VScollBar size to zero + $Background/Log.get_child(0,true).set_deferred("size",Vector2i(0,0)) -func _process(_delta) -> void: - var windowsize = DisplayServer.window_get_size() - $".".size = windowsize - get_parent().size = windowsize - get_parent().get_parent().size = windowsize +# Updates log text +func logupdate(_type:String,_script:String,_method:String,logmessage:String) -> void: + $Background/Log.text = $Background/Log.text + "\n" + logmessage -func logevent(_type:String,_script:String,_message:String,logcomp:String) -> void: - # Appends log to RichTextLabel - text = text + "\n" + log_prefix + logcomp + log_suffix +# These two functions are very self explanitory +func display() -> void: + if core.protection_mode: return + $Background.visible = true -func rmconnect() -> void: - # Disables recieving of log messages - Logger.disconnect("logevent",Callable(self,"logevent")) +func dissolve() -> void: + if core.protection_mode: return + $Background.visible = false diff --git a/corelog.tscn b/corelog.tscn new file mode 100644 index 0000000..ef9a7ee --- /dev/null +++ b/corelog.tscn @@ -0,0 +1,52 @@ +[gd_scene load_steps=5 format=3] + +[ext_resource type="Script" path="res://CORE/corelog.gd" id="1_8l1qi"] +[ext_resource type="FontFile" path="res://CORE/hack.ttf" id="1_m5led"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_adeh8"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_koe3t"] + +[node name="CORELog" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_8l1qi") + +[node name="Background" type="ColorRect" parent="."] +layout_mode = 0 +offset_right = 960.0 +offset_bottom = 540.0 +color = Color(0, 0, 0, 1) + +[node name="Log" type="RichTextLabel" parent="Background"] +layout_mode = 0 +offset_right = 960.0 +offset_bottom = 540.0 +theme_override_colors/default_color = Color(1, 1, 1, 1) +theme_override_fonts/normal_font = ExtResource("1_m5led") +theme_override_fonts/bold_font = ExtResource("1_m5led") +theme_override_fonts/italics_font = ExtResource("1_m5led") +theme_override_fonts/bold_italics_font = ExtResource("1_m5led") +theme_override_fonts/mono_font = ExtResource("1_m5led") +theme_override_font_sizes/normal_font_size = 12 +theme_override_font_sizes/bold_font_size = 12 +theme_override_font_sizes/italics_font_size = 12 +theme_override_font_sizes/bold_italics_font_size = 12 +theme_override_font_sizes/mono_font_size = 12 +theme_override_styles/focus = SubResource("StyleBoxEmpty_adeh8") +theme_override_styles/normal = SubResource("StyleBoxEmpty_koe3t") +bbcode_enabled = true +text = "coreinit -> \"Fixing\" busy setting up children issue +coreinit -> Bootstrapping CORE +coreinit -> Checking CORE requirements +coreinit -> Loading modules +coreinit -> Constructing modules +coreinit -> Injecting modules +coreinit -> Updating dependency references +coreinit -> Applying configuration to base modules +coreinit -> Initializing base modules" +scroll_following = true diff --git a/count_characters.sh b/count_characters.sh index dac6967..84d001b 100755 --- a/count_characters.sh +++ b/count_characters.sh @@ -1,11 +1,27 @@ #!/bin/bash +if [ "$1" == "--help" ]; then + echo "Environment variables: VERBOSE (false)" + echo " FILEEXTENSION (*)" + echo " IGNORE_SCRIPT (false)" + echo " IGNORE_DOCUMENTATION (false)" + echo " NUMBER_ONLY (false)" + exit 0 +fi function dircount() { if [ "$VERBOSE" == "true" ]; then echo ":: Checking directory \"$*\"..."; fi cd "$*" || exit 54 for file in $FILEEXTENSION; do export "file_full=$*/$file" if [ -d "$file" ]; then - dircount "$file_full" + if [ "$file" == "devprj" ]; then + if [ "$VERBOSE" == "true" ]; then echo ":: Skipping directory \"devprj\"";fi + else + if [ "$IGNORE_DOCUMENTATION" == "true" ] && [ "$file" == "docs" ]; then + if [ "$VERBOSE" == "true" ]; then echo ":: Skipping directory \"docs\"";fi + else + dircount "$file_full" + fi + fi elif [ -f "$file" ]; then if [ "$IGNORE_SCRIPT" == "true" ] && [ "$file" == "count_characters.sh" ]; then if [ "$VERBOSE" == "true" ]; then echo ":: Skipping this script"; fi diff --git a/debugdisplay.gd b/debugdisplay.gd new file mode 100644 index 0000000..4e4bbed --- /dev/null +++ b/debugdisplay.gd @@ -0,0 +1,71 @@ +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### +extends Node + +# CORE modules +var core: Node = null +var misc: Node = null + +# Important nodes +@onready +var display: RichTextLabel = get_node("Display") + +# Config +var config_enabled: bool = false +var config_fps: bool = false +var config_delta: bool = false +var config_rendertime: bool = false +var config_memory: bool = false + +# Check if enabled +func _process(_delta) -> void: + if config_enabled: + update_display() + display.visible = true + else: + display.visible = false + +# Updates the display with useful information +func update_display(): + var displaytext: String = "" + var displaysize: int = 17 + # Get memory information + var info_memory: Dictionary = OS.get_memory_info() + if config_memory: + info_memory.merge({"peak":OS.get_static_memory_peak_usage(),"percent":float(OS.get_static_memory_usage())/info_memory["physical"]*100,"used":OS.get_static_memory_usage()}) + + # If fps is enabled, add the fps counter + if config_fps: + displaysize = displaysize+17*1 + displaytext = displaytext + "\nFPS: " + str(snappedf(misc.get_fps(false),0.01)) + # If delta is enabled, add the delta counter + if config_delta: + displaysize = displaysize+17*1 + displaytext = displaytext + "\nDelta: " + str(misc.get_delta()) + # If rendertime is enabled, add the rendertime counter + if config_rendertime: + displaysize = displaysize+17*1 + displaytext = displaytext + "\nRendertime: " + str(misc.get_rendertime()) + # If memory is enabled, display memory information + if config_memory: + displaysize = displaysize+17*2 + displaytext = displaytext + "\nMemory (Available|Used|Stack): " + str(misc.byte_to_mib(info_memory["available"],true)) + " MiB|" + str(misc.byte_to_mib(info_memory["used"],true)) + " MiB|" + str(misc.byte_to_mib(info_memory["stack"],true)) + " MiB" + displaytext = displaytext + "\nMemory (Physical|Peak|%): " + str(misc.byte_to_mib(info_memory["physical"],true)) + " MiB|" + str(misc.byte_to_mib(info_memory["peak"],true)) + " MiB|" + str(snappedf(info_memory["percent"],0.001)) + "%" + + # Add CORE version and (if enabled) a dev mode notice + if core.development_mode: + displaytext = "CORE " + core.version["full"] + " [color=yellow](development mode)[/color]" + displaytext + else: + displaytext = "CORE " + core.version["full"] + displaytext + # Update display + display.text = displaytext + display.size = Vector2i(540,displaysize) diff --git a/debugdisplay.tscn b/debugdisplay.tscn new file mode 100644 index 0000000..2fa3c4a --- /dev/null +++ b/debugdisplay.tscn @@ -0,0 +1,34 @@ +[gd_scene load_steps=5 format=3] + +[ext_resource type="Script" path="res://CORE/debugdisplay.gd" id="1_hcfi0"] +[ext_resource type="FontFile" path="res://CORE/hack.ttf" id="1_nhdg1"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_3c08d"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5ghow"] +bg_color = Color(0.839216, 0.0196078, 0.196078, 0.862745) +corner_radius_bottom_right = 16 +shadow_color = Color(0, 0, 0, 0) + +[node name="DebugDisplay" type="Node"] +script = ExtResource("1_hcfi0") + +[node name="Display" type="RichTextLabel" parent="."] +offset_right = 540.0 +offset_bottom = 102.0 +theme_override_colors/default_color = Color(1, 1, 1, 1) +theme_override_fonts/normal_font = ExtResource("1_nhdg1") +theme_override_font_sizes/normal_font_size = 14 +theme_override_font_sizes/bold_font_size = 14 +theme_override_font_sizes/italics_font_size = 14 +theme_override_font_sizes/bold_italics_font_size = 14 +theme_override_font_sizes/mono_font_size = 14 +theme_override_styles/focus = SubResource("StyleBoxEmpty_3c08d") +theme_override_styles/normal = SubResource("StyleBoxFlat_5ghow") +bbcode_enabled = true +text = "CORE source-N (development mode) (THIS IS A PLACEHOLDER!) +FPS: +Delta: +Rendertime: +Memory (1): +Memory (2):" diff --git a/docs/breaking-commits.md b/docs/breaking-commits.md new file mode 100644 index 0000000..7adb7be --- /dev/null +++ b/docs/breaking-commits.md @@ -0,0 +1,9 @@ +--- +hide: + - navigation +--- +# Breaking commits +We sometimes push a commit that may break something for some project. Here's where we list critical changes. + +## 404 Documentation not found +There are no breaking commits as of now. diff --git a/docs/index.md b/docs/index.md index 2ae1a70..9e565ce 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,16 +6,16 @@ hide: Welcome to the StarOpenSource documentation! Look below for more information about CORE and code references. ## What, why, wtf? -The **StarOpenSource CORE Framework** (also known as **CORE** or **SOSCORE**) is a framework that makes the development of games and applications written in **Godot 4.0 and 4.1** easier. CORE implements useful & common functions *(such as calculating the current FPS)* and provides a logging system that even supports formatting, a scene manager and so much more. +The **StarOpenSource CORE Framework** (also known as **CORE** or **SOSCORE**) is a framework that makes the development of games and applications written in **Godot 4.1** easier. CORE implements useful & common functions *(such as calculating the current FPS)* and provides a logging system that even supports formatting, a scene manager and so much more. ## Can I use CORE in my existing project? -In theory, yes. But if you don't want to refactor a large part of your codebase, don't install CORE. +Yes, unless you want to refactor your entire project. Remember: CORE is a framework, NOT a library and NOT a regular addon! ## Can I use CORE in my project freely? [Click this text to learn more about licensing.](/licensing/) ## I have a problem with CORE! -First of all, read the [Troubleshooting guide](/troubleshooting/). If you can't find your error or it's some incompatibility with CORE and project x, [create a issue](https://git.staropensource.de/StarOpenSource/core/issues/new). +First of all, read the [Troubleshooting guide](/troubleshooting/). If you can't find your error in there or CORE has a compatibility issue with some addon, look at [the issue tracker](https://git.staropensource.de/StarOpenSource/issues) for more information. ## How to install/update CORE? If you want to install CORE, follow [this guide](/install/). If you want to update CORE to the latest version instead, follow [this guide](/update/) instead. diff --git a/docs/install.md b/docs/install.md index 70a0ca4..ddd9578 100644 --- a/docs/install.md +++ b/docs/install.md @@ -3,66 +3,131 @@ hide: - navigation --- # Installing CORE -## Step 1: Downloading the *CORE Manager* +## The safe route +### Step 1: Downloading the *CORE Manager* Before we install CORE, we first have to download the **CORE Manager**. It is responsible for installing CORE and downloading updates.
-#### Windows: [CORE-Manager.exe](https://git.staropensource.de/staropensource/core-manager/releases/download/b0/CORE-Manager.exe) -#### Linux: [CORE-Manager.elf](https://git.staropensource.de/staropensource/core-manager/releases/download/b0/CORE-Manager.elf) +#### Windows: [CORE-Manager.exe](https://git.staropensource.de/staropensource/core-manager/releases/download/b1/CORE-Manager.exe) +#### Linux: [CORE-Manager.elf](https://git.staropensource.de/staropensource/core-manager/releases/download/b1/CORE-Manager.elf) #### macOS: Use `wine` to run `CORE-Manager.exe` -## Step 2: Using the *CORE Manager* +### Step 2: Using the *CORE Manager* Launch `CORE-Manager.exe` or `CORE-Manager.elf` and type in the path to your Godot project ***(replace backslashes with regular slashes on Windows)***. Click on `Install` and wait until it's finished. **Note: If you are updating CORE, click on `Update` instead.** -## Step 3: Configuring your project +### Step 3: Configuring your project Launch your project in the Godot Editor and go to your project settings. You now need to set your startup scene to `res://CORE/coreinit.tscn`. -## Step 4: Configuring CORE -Edit the `res://CORE/config.gd` file and set the `core_startscript` variable to a GDScript file. That GDScript file will act as your init script and can be used to load your game. You can find the `config.gd` reference [here](/references/config.gd/). - -## Step 5: Write your init script -Create a new GDScript file and write this into it: -``` gdscript +### Step 4: Write your init script +Create a new GDScript file at `res://init.gd` (can be anything else, but you need to change the `core_initscript` variable accordingly!) and write this into it: +```gdscript extends Node @onready -var core = get_node("/root/core") #(1)! +var core = get_node("/root/CORE") #(1)! +@onready +var logger = core.get_module("Logger") #(2)! func _ready() -> void: - core.welcome() #(2)! - Logger.enable_diag = true #(3)! - Logger.diag("","This is a diagnostic message. I can only be seen with Logger.enable_diag being true.") - Logger.info("","This is a informational message.") - Logger.warn("","This is a warning message.") - Logger.error("","This is a error message.") - await get_tree().create_timer(0.1).timeout #(4)! - get_tree().quit(0) + core.welcome() #(3)! + config.logger_diagnostic = true #(4)! + core.reload_config() #(5)! + logger.diag("","This is a diagnostic message. I can only be seen if diagnostic log messages are enabled.") + logger.info("","This is a informational message.") + logger.warn("","This is a warning message.") + logger.error("","This is a error message.") + core.exit_safely() #(6)! ``` -1. Imports the CORE Holder aka. /root/core -2. Makes CORE say hello :) -3. Enables diagnostic log output -4. Waits 100 milliseconds for the log messages to be printed before exiting +1. Imports the CORE "module" aka. /root/CORE +2. Imports the CORE's logger implementation +3. Makes CORE say hello :) +4. Overwrites the logger_diagnostic setting temporarily (in memory) +5. Applies all modified settings +6. Tells CORE to shutdown your application safely. Has to do with CORE's logger and Godot. -Now replace `` with the filename of your script (without `.gd`) and save it under the path you specified in the `core_startscript` variable. +Now replace `` with the file path of your script (preferably with `.gd` and without `res://`) and save it under the path you specified in the `core_initscript` variable. -## Step 6: Start your project -Start your project and wait until CORE initialized itself. You should see this output in your Godot console (replace `` in your head with the filename of the init script without `.gd`): -``` text -logger -> Initializing Logger -preprocessor -> Initializing Preprocessor -preprocessor -> Delaying initialization by 0.75s +### Step 5: Start your project +Start your project and wait at least 500ms. You should see this output in your Godot console (with a few variations, of course): +```text +coreinit -> "Fixing" busy setting up children issue #(1)! +coreinit -> Bootstrapping CORE coreinit -> Checking CORE requirements -coreinit -> Constructing coreloader -coreinit -> Injecting coreloader -coreinit -> Switching to COREBackground -(core) [INFO] CORE git-develop welcomes you! - It seems like everything is working :) -() [DIAG] This is a diagnostic message. I can only be seen with Logger.enable_diag being true. -() [INFO] This is a informational message. -() [WARN] This is a warning message. -() [ERROR] This is a error message. -(coreloader) [DIAG] Removing coreloader +coreinit -> Loading modules +coreinit -> Constructing modules +coreinit -> Injecting modules +coreinit -> Updating dependency references +coreinit -> Applying configuration to base modules +coreinit -> Initializing base modules +(CORE/core.gd) [INFO] CORE (source 0) welcomes you! #(2)! + It seems like everything is working :) +(init.gd) [DIAG] This is a diagnostic message. I can only be seen if diagnostic log messages are enabled. +(init.gd) [INFO] This is a informational message. +(init.gd) [WARN] This is a warning message. +(init.gd) [ERR!] This is a error message. +(CORE/coreinit.gd) [DIAG] Bootstrapped CORE, exiting. #(3)! ``` -If your project returns about the same output (a few lines omitted) then CORE has been successfully installed. If not, look for your error [here](/troubleshooting/). If you need a example `init.gd` script, [look here](/references/init.gd/). +1. These messages are printed anyway as CORE's logger implementation is not loaded at that point in time +2. That log messages comes from your init.gd! +3. tldr we enabled diagnostic messages "too fast". if we delayed the config reload by half a second, we wouldn't have seen that message. + +If your project returns about the same output then CORE has been successfully installed. If not, look for your error [here](/troubleshooting/). For a quick start guide, [click here](/quickstartguide/) + +## YOLOing the install +Do you want to play with fire? Do you like to live at the edge of what's possible? Or are you just a Arch Linux or Gentoo user? If yes, here's a guide on how to manually install and update CORE. + +### Note +This install method is **only recommended for devs experienced with CORE, Godot 4 and Git**. We are not responsible if you mess up something and break your project! + +### Installing CORE +1. Create your Godot Project and open the project folder in a terminal +2. Execute `git clone https://git.staropensource.de/StarOpenSource/core.git CORE` (even if you're planning/using a git repository already! Do NOT use git submodules!) +3. `cd` into the CORE folder and copy `config.gd.example` and rename it to `config.gd`. You may edit it to your liking now. +4. Create your init script at `[project root]/init.gd` (or some other path, update it in `config.gd` accordingly) and write this into it: +```gdscript +extends Node + +@onready +var core = get_node("/root/CORE") +@onready +var logger = core.get_module("Logger") + +func _ready() -> void: + logger.info("init.gd","init.gd loaded.") + core.welcome() + core.exit_safely() +``` +5. Go back to Godot and set your startup scene to `res://CORE/coreinit.tscn` +6. Launch your project, you should see something like this in your console: +```text +coreinit -> "Fixing" busy setting up children issue +coreinit -> Bootstrapping CORE +coreinit -> Checking CORE requirements +coreinit -> Loading modules +coreinit -> Constructing modules +coreinit -> Injecting modules +coreinit -> Updating dependency references +coreinit -> Applying configuration to base modules +coreinit -> Initializing base modules +(init.gd) [INFO] init.gd loaded. +(CORE/core.gd) [INFO] CORE (source 0) welcomes you! + It seems like everything is working :) +(CORE/coreinit.gd) [DIAG] Bootstrapped CORE, exiting. +``` +7. Congrats, you're not a idiot. + +### Updating CORE +1. Open your Godot project folder in a terminal +2. `cd` into the CORE folder and create a backup of your `config.gd` file +3. Run `git pull` +4. Check the [breaking commits](/breaking-commits/) documentation page for breaking changes and update your code accordingly +5. Launch your project and look for any issues. If any arise re-check your code for any [breaking commits](/breaking-commits/) or contact us. + +### Reverting a update +#### Reverting an update is unsupported and should **only** be used in special cases. +1. Open your Godot project folder in a terminal +2. `cd` into the CORE folder and create a backup of your `config.gd` file +3. Run `git fetch && git checkout ` (replace `` with whatever commit you want to revert to) +4. Revert all changes made in all commits after. Checking the [breaking commits](/breaking-commits/) page might be useful. diff --git a/docs/licensing.md b/docs/licensing.md index 5a5712c..49e3811 100644 --- a/docs/licensing.md +++ b/docs/licensing.md @@ -7,7 +7,7 @@ hide: This documentation page only covers the most important licensing question. If you want to read more about the GNU General Public License Version 3, [read this](https://www.gnu.org/licenses/gpl-faq.html). ## Note -Under **modified CORE copy** we understand a CORE installation that has been modified in any way (**config.gd** is excluded). If you modified anything else than the **config.gd** file in the **res://CORE/** folder, you have a modified CORE copy. +Under a **modified CORE copy** we understand a CORE installation that has been modified in any way. The configuration file `config.gd` is excluded. ## What happens when the license is violated against? We'll contact the person/organisation doing that. If they won't take it down or can't be contacted, we'll send a cease and desist letter or contact a lawyer. diff --git a/docs/quickstartguide.md b/docs/quickstartguide.md new file mode 100644 index 0000000..7a11c4c --- /dev/null +++ b/docs/quickstartguide.md @@ -0,0 +1,57 @@ +--- +hide: + - navigation +--- +# Quick Start Guide +Welcome to the CORE quick start guide! Here you'll learn how to use CORE efficently and how to start your journey with CORE. + +## Note +Please do **NOT** continue if CORE is not installed or not working for you. You can install CORE by [visiting this guide](/install/) + +## WARNING +**This quick start guide is work in progress and will heavily change over time. The information at this point in time is accurate but incomplete.** + +## Introduction I: The configuration file +The configuration file can be used to configure CORE to your liking and tweak it's behaviour. You can edit the configuration **permanently** in `res://CORE/config.gd` or **overwrite** the config **temporarily** ***in memory*** using this example: +```gdscript +extends Node + +@onready +var core: Node = get_node("/root/CORE") +@onready +var config: Node = core.get_module("Config") #(1)! + +func _ready() -> void: + logger.diag("init.gd","This diagnostic message will be hidden unless enabled permanently.") #(2)! + config.logger_diagnostic = true #(3)! + core.reload_config() #(4)! + logger.diag("init.gd","This diagnostic message will be displayed even if disabled permanently as we overwrote the setting in memory.") #(5)! +``` + +1. Imports the config module for configuration access +2. Will be hidden unless logger_diagnostic is set to true permanently +3. Overwrites the configuration setting "logger_diagnostic" in memory +4. Tells CORE to apply config changes +5. Will be displayed even if logger_diagnostic is set to false permanently as we overwrote the value in memory and set it to true +``` + +## Introduction II: The init script +The initialization script (you specified in the configuration file) is injected into the SceneTree after CORE completed it's startup procedure. Your init script is responsible for loading and displaying your application. Here's a basic example of `res://init.gd` loading a scene located at `res://testscene.tscn` and freeing itself. +```gdscript +extends Node + +@onready +var core: Node = get_node("/root/CORE") +@onready +var resourcemanager: Node = core.get_module("ResourceManager") +@onready +var scenemanager: Node = core.get_module("SceneManager") + +func _ready() -> void: + logger.info("init.gd","Loading testscene") + resourcemanager.load("testscene","res://testscene.tscn") + logger.info("init.gd","Injecting testscene into SceneTree under the action overlay.") + scenemanager.add_game("testscene") + logger.info("init.gd","Removing init script") + queue_free() +``` diff --git a/docs/references/CORE.md b/docs/references/CORE.md new file mode 100644 index 0000000..6394eee --- /dev/null +++ b/docs/references/CORE.md @@ -0,0 +1,57 @@ +--- +hide: + - navigation +--- +# CORE (/root/CORE) +The main "module" + +## Constants +### version +- type `Dictionary` +- description `The CORE version. "type" is the release type, "releasebuild" the number of the latest release and "full" the full version string.` +- keys `type` (`String`, either `source`, `release` or `prerelease`), `releasebuild` (`int`) and `full` (`String`) + +## Enums +### Errors +- description `Contains all possible errors CORE can throw at you.` +- keys `OK`, `CORE_PROTECTIONMODE`, `CORE_EXCEPTION`, `CORE_INVALID_MODULE`, `RESOURCEMANAGER_ALREADY_EXISTS`, `RESOURCEMANAGER_RESOURCE_MISSING`, `RESOURCEMANAGER_BATCH_EMPTY`, `SCENEMANAGER_ALREADY_LOADED`, `SCENEMANAGER_NOT_LOADED` and `SCENEMANAGER_NOT_PACKEDSCENE` + +## Methods +### welcome() +- returns `void` +- description `Prints a welcome message and the CORE version.` +### reload_config() +- returns `void` +- description `Reloads the configuration file and applies any changes (made in memory).` +### get_module() +- returns `Node` +- description `Returns a CORE module. A alternative to get_node("/root/CORE/")` + - argument `module_name` + - type `StringName` + - mandatory `yes` + - description `The CORE module that should be returned` + - possible values `Config`, `Preprocessor`, `Logger`, `Miscellaneous`, `DebugDisplay`, `SplashScreen`, `ResourceManager`, `SceneManager` and `Events` +- example +```gdscript +extends Node + +@onready +var core = get_node("/root/CORE") +@onready +var logger = core.get_module("Logger") + +func _ready() -> void: + logger.info("test.gd","Hi there!") +``` +### devmode() +- returns `void` +- description `Enables the development mode` +- note `Do not call this function unless you're working on CORE. It disables limits and many more things.` +### exit_safely() +- returns `void` +- description `Exists CORE safely. Is recommended over get_tree().quit() as log messages may be stuck in processing and would get lost otherwise.` + - argument `exitcode` + - type `int` + - description `Oh, you don't know what an exitcode is? Learn cmd.exe or bash you fool!` + - mandatory `no, default value is 0` +- trivia `The only thing this method does is to enable CORE's protection mode, wait 500ms (0.5s) and then quit.` diff --git a/docs/references/Configuration_File.md b/docs/references/Configuration_File.md new file mode 100644 index 0000000..fef508b --- /dev/null +++ b/docs/references/Configuration_File.md @@ -0,0 +1,142 @@ +--- +hide: + - navigation +--- +# Configuration File (/root/CORE/Config) +The CORE configuration file is located at `res://CORE/config.gd` and is used for configuring CORE behaviour. A full example configuration can be found [here](#example-configuration). + +## Placeholders +### [LOADPATH] +- type `String` +- description `Will be replaced by CORE's loadpath` +- example `res://CORE/` +- can be used in `splash_image` + +## CORE +### core_initscript +- type `String` +- description `The path to your init script` +- default value `"res://init.gd"` + +## Preprocessor +### preprocessor_enabled +- type `bool` +- description `Enables the preprocessor if true` +- default value `true` +### preprocessor_diagnostic +- type `bool` +- description `Makes the preprocessor super-verbose` +- default value `false` +- note `Please leave this option disabled as your log will get massively bloated by the preprocessor.` + +## Logger +### logger_enabled +- type `bool` +- description `Enables CORE's logger implementation if true` +- default value `true` +### logger_diagnostic +- type `bool` +- description `Displays diagnostic messages including messages by CORE if enabled. +- default value `false` + +## CORELog +### corelog_enabled +- type `bool` +- description `If CORELog should be displayed or not` +- default value `true` + +## Debug Display +### debugdisplay_enabled +- type `bool` +- description `If the debug display should be enabled or not` +- default value `false` +### debugdisplay_fps +- type `bool` +- description `Displays the framerate counter if true` +- default value `true` +### debugdisplay_delta +- type `bool` +- description `Renders the delta value if true` +- default value `true` +### debugdisplay_rendertime +- type `bool` +- description `Displays the rendertime if true` +- default value `true` +### debugdisplay_memory +- type `bool` +- description `Displays information about the memory usage if true` +- default value `true` + +## Resource Manager +## resourcemanager_load_invalid_file_as_null +- type `bool` +- description `Affects the Resource Manager's loadres() function if it encounters a invalid filepath. If true, loadres() will "save" the resource as null, but will do nothing if false.` +- default value `false` + +## Splash Screen +### splash_enabled +- type `bool` +- description `Enables or disables the splash screen at startup` +- default value `false` +- note `You can still call display() and dissolve() manually, this option just affects the startup process.` +### splash_image +- type `String` +- description `The path to your splash image (square-sized)` +- default value `[LOADPATH]soscore.png` +### splash_image_size +- type `int` +- description `The width and height of your square-sized image` +- default value `256` +### splash_color +- type `String` +- description `The splash screen's background color in hex (without the "#" at the beginning!)` + +## Example configuration +This is the full example configuration that you can find as `config.gd.example` +```gdscript +############################## +# THE CORE FRAMEWORK # +# EXAMPLE CONFIGURATION FILE # +# # +# THIS DOCUMENT IS PUBLICLY # +# AVAILABLE UNDER THE PUBLIC # +# DOMAIN AND IS NOT LICENSED # +############################## +extends Node + +# Hello there, fellow developer! +# This is a example configuration file +# for the CORE Framework (source 0). +# +# Most settings in this config should be +# self explanitory. If not, visit the documentation: +# https://core.staropensource.de/references/Configuration_File/ +# +# Thank you for using the CORE Framework! +# - The StarOpenSource Project & Contributers + +var core_initscript: String ? "res://init.gd" + +var preprocessor_enabled: bool = true +var preprocessor_diagnostic: bool = false + +var logger_enabled: bool = true +var logger_diagnostic: bool = false + +var corelog_enabled: bool = true + +var debugdisplay_enabled: bool = false +var debugdisplay_fps: bool = true +var debugdisplay_delta: bool = true +var debugdisplay_rendertime: bool = true +var debugdisplay_memory: bool = true + +var resourcemanager_load_invalid_file_as_null: bool = false + +var splash_enabled: bool = false +var splash_image: String = "res://CORE/soscore.png" +var splash_image_size: int = 256 +var splash_color: String = "000000" + +# EOF <- Yes, this is the end of the example configuration! Pretty short, isn't it? +``` diff --git a/docs/references/DebugDisplay.md b/docs/references/DebugDisplay.md new file mode 100644 index 0000000..b122ce4 --- /dev/null +++ b/docs/references/DebugDisplay.md @@ -0,0 +1,9 @@ +--- +hide: + - navigation +--- +# Debug Display (/root/CORE/DebugDisplay) +Displays useful information in the top-left corner + +## 404 Documentation not found +The `Debug Display` module does not have any variables or methods that are relevant to a developer as you can change everything through the configuration file. diff --git a/docs/references/Events.md b/docs/references/Events.md new file mode 100644 index 0000000..eeda9d6 --- /dev/null +++ b/docs/references/Events.md @@ -0,0 +1,43 @@ +--- +hide: + - navigation +--- +# Events (/root/CORE/Events) +Just connect a signal to a function and get updates when something happens + +## Signals +### window_title +- emitted on `window title change` +- argument `window_title` (type `String`) +- argument `previous_window_title` (type `String`) +### window_size +- emitted on `window size change` +- argument `update_coordinate` (type `String`, can be `X`, `Y` or `BOTH`) +- argument `window_size` (type `Vector2i`) +- argument `previous_window_size` (type `Vector2i`) +### window_pos +- emitted on `window position change` +- argument `update_coordinate` (type `String`, can be `X`, `Y` or `BOTH`) +- argument `window_pos` (type `Vector2i`) +- argument `previous_window_pos` (type `Vector2i`) +### logger_all +- emitted on `log output` +- argument `type` (type `String`, can be `"DIAG"`, `"INFO"`, `"WARN"` or `"ERROR"`) +- argument `script` (type `String`) +- argument `message` (type `String`) +### logger_diag +- emitted on `diagnostic log output` +- argument `script` (type `String`) +- argument `message` (type `String`) +### logger_info +- emitted on `informational log output` +- argument `script` (type `String`) +- argument `message` (type `String`) +### logger_warn +- emitted on `warning log output` +- argument `script` (type `String`) +- argument `message` (type `String`) +### logger_error +- emitted on `error log output` +- argument `script` (type `String`) +- argument `message` (type `String`) diff --git a/docs/references/Logger.md b/docs/references/Logger.md new file mode 100644 index 0000000..d29eb29 --- /dev/null +++ b/docs/references/Logger.md @@ -0,0 +1,76 @@ +--- +hide: + - navigation +--- +# Logger (/root/CORE/Logger) +The CORE logger implementation (with formatting support!) + +## Signals +### logevent +- emitted on `log message` +- argument `type` (type `String`, can be `DIAG`, `INFO`, `WARN` or `ERR!`) +- argument `script` (type `String`) +- argument `message` (type `String`) +- argument `logmessage` (type `String`, description `The full log message as printed in console`) + +## Methods +### diag() +- returns `void` +- description `Prints a diagnostic message` + - argument `script` + - type `String` + - mandatory `yes` + - description `The script where the log message is coming from` + - argument `message` + - type `String` + - mandatory `yes` + - description `Your log message` + - argument `preproc` + - type `bool` + - mandatory `no, default value is true` + - description `If the log message should be run through the preprocessor. If false formatting will be disabled for that log message.` +### info() +- returns `void` +- description `Prints a informational message` + - argument `script` + - type `String` + - mandatory `yes` + - description `The script where the log message is coming from` + - argument `message` + - type `String` + - mandatory `yes` + - description `Your log message` + - argument `preproc` + - type `bool` + - mandatory `no, default value is true` + - description `If the log message should be run through the preprocessor. If false formatting will be disabled for that log message.` +### warn() +- returns `void` +- description `Prints a warning message` + - argument `script` + - type `String` + - mandatory `yes` + - description `The script where the log message is coming from` + - argument `message` + - type `String` + - mandatory `yes` + - description `Your log message` + - argument `preproc` + - type `bool` + - mandatory `no, default value is true` + - description `If the log message should be run through the preprocessor. If false formatting will be disabled for that log message.` +### error() +- returns `void` +- description `Prints a error message` + - argument `script` + - type `String` + - mandatory `yes` + - description `The script where the log message is coming from` + - argument `message` + - type `String` + - mandatory `yes` + - description `Your log message` + - argument `preproc` + - type `bool` + - mandatory `no, default value is true` + - description `If the log message should be run through the preprocessor. If false formatting will be disabled for that log message.` diff --git a/docs/references/Miscellaneous.md b/docs/references/Miscellaneous.md new file mode 100644 index 0000000..71ac55e --- /dev/null +++ b/docs/references/Miscellaneous.md @@ -0,0 +1,51 @@ +--- +hide: + - navigation +--- +# Miscellaneous (/root/CORE/Miscellaneous) +Contains small methods that do not deserve their own module. + +## Methods +### get_title() +- returns `String` +- description `Returns the main window title.` +- note `This method simply returns the value of get_tree().root.title and is included here as DisplayServer.window_get_title() does not exist.` +### get_fps() +- returns `float` +- description `Returns the current framerate aka. FPS aka. Frames Per Second` +- note `If the delta value (which is used in the calculation) is zero, INF (infinity) will be returned.` + - argument `flatten` + - type `bool` + - mandatory `no, default value is false` + - description `The decimal numbers will be removed if true` +### get_rendertime() +- returns `float` +- description `Returns the time in milliseconds it took for Godot to render a frame` +### get_delta() +- returns `float` +- description `Returns the delta value you normally see as a argument in _process()` +### byte_to_mib() +- returns `float` +- description `Converts a number of bytes to a number of Mebibytes.` + - argument `bytes` + - type `int` + - mandatory `yes` + - description `The number of bytes` + - argument `flatten` + - type `bool` + - mandatory `no, default value is true` + - description `The decimal numbers will be removed if true` +## flat_float() +- returns `float` +- description `Removes all decimal numbers from a floating point number.` + - argument `number` + - type `float` + - mandatory `yes` + - description `The floating point number` +## flat_float_int() +- returns `int` +- description `Removes all decimal numbers from a floating point number. Returns a integer instead of a float` + - argument `number` + - type `float` + - mandatory `yes` + - description `The floating point number` diff --git a/docs/references/Preprocessor.md b/docs/references/Preprocessor.md new file mode 100644 index 0000000..59baee4 --- /dev/null +++ b/docs/references/Preprocessor.md @@ -0,0 +1,96 @@ +--- +hide: + - navigation +--- +# Preprocessor (/root/CORE/Preprocessor) +The **Preprocessor** parses tags and is responsible for formatting text. + +## Tags *(these can be used in log messages too!)* +All tags can be escaped by adding `esc_` before the tag name, if you want to do that. Example: +```text +Raw: +Output: +``` +### No process `` +- end tag `no` +- description `Disables preprocessing completely. Doesn't even display the prefix.` +- example: +``` text +Raw: This is atest MESSage. +Output: This is atest MESSage. +``` +### Newline `` +- end tag `no` +- description `Makes a newline while respecting the prefix. Is much recommended over "\n".` +- example (with prefix `prefix_`): +``` text +Raw: Very nice message!Here's another message :) +Output: +prefix_Very nice message! + Here's another message :) +``` +### Lowercase `` +- end tag `yes` +- description `Makes your text lowercase.` +- example: +``` text +Raw: Did you FiNd THAT funny? +Output: Did you find thaT funny? +``` +### Uppercase `` +- end tag `yes` +- description `Makes your text uppercase.` +- example: +``` text +Raw: ThiS TeXT should be UPPercaSED +Output: ThiS TeXT SHOULD BE UPPERcaSED +``` +### Camelcase `` +- end tag `yes` +- description `Makes your text camelcase.` +- example: +``` text +Raw: This text should be CamelCased. +Output: This textShouldBeCamelCased. +``` +### Pascalcase `` +- end tag `yes` +- description `Makes your text pascalcase.` +- example: +``` text +Raw: This text should be PascelCased. +Output: This TextShouldBePascelCased. +``` +### Snakecase `` +- end tag `yes` +- description `Makes your text snakecase.` +- example: +``` text +Raw: This text should be SnakeCased. +Output: This text_should_be_snake_cased. +``` + +## Methods +### process() +- returns `String` +- description `Formats a message` + - argument `msg` + - type `String` + - mandatory `yes` + - description `The message used for processing` + - argument `prefix` + - type `String` + - mandatory `yes` + - description `The prefix used for newlines` + - argument `pre_msg` + - type `String` + - mandatory `no, default value is ""` + - description `Inserted before the message` + - argument `post_msg` + - type `String` + - mandatory `no, default value is ""` + - description `Inserted after the message` + - argument `exclusion_filter` + - type `Array` + - mandatory `no, default value is []` + - description `Removes specific Strings from the prefix (used in calculating spaces when using )` diff --git a/docs/references/resmgr.gd.md b/docs/references/ResourceManager.md similarity index 81% rename from docs/references/resmgr.gd.md rename to docs/references/ResourceManager.md index 3368f9e..c558a3a 100644 --- a/docs/references/resmgr.gd.md +++ b/docs/references/ResourceManager.md @@ -2,7 +2,7 @@ hide: - navigation --- -# Resource Manager (core.resmgr) +# Resource Manager (/root/CORE/ResourceManager) Responsible for loading and unloading resources, even in batches. ## Methods @@ -54,17 +54,3 @@ Responsible for loading and unloading resources, even in batches. - type `String` - mandatory `yes` - description `The resource name.` - -## Internal variables -Do not touch or you will cause breakage. -### resources -- type `Directory` -- default value `{}` -- description `All loaded resources` -- format `{"resource_name":loaded_resource} - -## Internal methods -Do not execute or you will cause breakage. -### _ready() -- returns `void` -- description `Executes core.setready(). That's all.` diff --git a/docs/references/SceneManager.md b/docs/references/SceneManager.md new file mode 100644 index 0000000..0cf64ba --- /dev/null +++ b/docs/references/SceneManager.md @@ -0,0 +1,79 @@ +--- +hide: + - navigation +--- +# Scene Manager (/root/CORE/SceneManager) +Responsible for displaying scenes using overlays. + +## Overlays +The scene manager uses something called **overlays**. A overlay can either hold one scene or multiple scenes and are used to keep scenes in order. +### Overlay #1 - `debug` +- description `The overlay with the highest priority and is displayed over all other overlays. Should contain debug scenes.` +- more than one scene `yes` +- adding a scene **[add_debug()](#add_debug)** +- removing a scene **[remove_debug()](#remove_debug)** +### Overlay #2 - `cutscene` +- description `Has the second highest priority and is displayed over all overlays except debug. Should contain... well cutscenes.` +- more than one scene `no` +- adding a scene **[add_cutscene()](#add_cutscene)** +- removing a scene **[remove_cutscene()](#remove_cutscene)** +### Overlay #3 - `menu` +- description `The overlay with the second lowest priority. Should contain menus.` +- more than one scene `yes` +- adding a scene **[add_menu()](#add_menu)** +- removing a scene **[remove_menu()](#remove_menu)** +### Overlay #4 - `action` +- description `Has the lowest priority. This overlay should contain your main menu, your program's main interface or your level.` +- more than one scene `no` +- adding a scene **[add_action()](#add_action)** +- removing a scene **[remove_action()](#remove_action)** + +## Methods +### add_debug() +- returns `bool` +- description `Adds a PackedScene to the debug overlay.` + - argument `resource_name` + - type `String` + - mandatory `yes` + - description `Used for loading the scene and the loaded scene name.` +### remove_debug() +- returns `bool` +- description `Removes a menu scene from the debug overlay.` + - argument `scene_name` + - type `String` + - mandatory `yes` + - description `Should be the same as the "resource_name" argument used previously in add_debug().` +### add_cutscene() +- returns `bool` +- description `Adds a PackedScene to the cutscene overlay.` + - argument `resource_name` + - type `String` + - mandatory `yes` + - description `Used for loading the scene and the loaded scene name.` +### remove_cutscene() +- returns `bool` +- description `Removes the game scene from the cutscene overlay.` +### add_menu() +- returns `bool` +- description `Adds a PackedScene to the menu overlay.` + - argument `resource_name` + - type `String` + - mandatory `yes` + - description `Used for loading the scene and the loaded scene name.` +### remove_menu() +- returns `bool` +- description `Removes a menu scene from the menu overlay.` + - argument `scene_name` + - type `String` + - mandatory `yes` + - description `Should be the same as the "resource_name" argument used previously in add_menu().` +### add_action() +- returns `bool` +- description `Adds a PackedScene to the action overlay.` + - argument `resource_name` + - type `String` + - mandatory `yes` + - description `Used for loading the scene and the loaded scene name.` +### remove_action() +- returns `bool` +- description `Removes the game scene from the action overlay.` diff --git a/docs/references/SplashScreen.md b/docs/references/SplashScreen.md new file mode 100644 index 0000000..f276fb6 --- /dev/null +++ b/docs/references/SplashScreen.md @@ -0,0 +1,14 @@ +--- +hide: + - navigation +--- +# Splash Screen (/root/CORE/SplashScreen) +Allows you to display a nice loading screen. + +## Methods +### display() +- returns `void` +- description `Makes the splash screen visible.` +### dissolve() +- returns `void` +- description `Makes the splash screen invisible.` diff --git a/docs/references/config.gd.md b/docs/references/config.gd.md deleted file mode 100644 index 36bb2ea..0000000 --- a/docs/references/config.gd.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -hide: - - navigation ---- -# CORE configuration file (core.config) -The CORE configuration file is located at `res://CORE/config.gd` and is used for configuring CORE behaviour. A full example configuration can be found [here](#example-configuration). - -## CORE -### core_startscript -- type `String` -- default value `res://init.gd` -- description `The initialization script. It is responsible for loading your application and for example displaying a main menu.` - -## Window manager (wmgr) -### wmgr_size_x -- type `int` -- default value `960` -- description `The window size set at startup (x coordinate).` -### wmgr_size_y -- type `int` -- default value `540` -- description `The window size set at startup (y coordinate).` -### wmgr_title -- type `String` -- default value `"Application/Game using CORE"` -- description `The window title set at startup.` -### wmgr_mode -- type `String` -- default value `0` -- description `The window mode set at startup.` -- format `0` = `WINDOWED`, `1` = `MINIMIZED`, `2` = `MAXIMIZED`, `3` = `FULLSCREEN` or `4` = `EXCLUSIVE_FULLSCREEN` - -## Splash screen (splash) -### splash_enabled -- type `bool` -- default value `false` -- description `Displays or hides the splash screen at startup time.` -- format `true` = `displayed` or `false` = `hidden` -### splash_image -- type `String` -- default value `"res://CORE/soscore.png"` -- description `The path to a image, displayed in the center of the splash screen.` -### splash_image_size -- type `float` -- default value `256` -- description `The size of your image. Used for both the x and y coordinates.` -### splash_color -- type `String` -- default value `000000` -- description `The background color.` -- format `AARRGGBB` or `RRGGBB` (`AA` = `alpha`, `RR` = `red`, `GG` = `green` and `BB` = `blue`) - -## Example configuration -This configuration can be found at `res://CORE/config.gd.example`. -``` gdscript -# core.gd.example -# CORE example configuration file -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Available in the public domain. -extends Node - -# Hello fellow dev! This is the CORE configuration file. -# This file can be used to customize CORE to your liking. -# You do not need to modify any CORE script as some things -# might break (everything depends on each other). -# Thank you for using CORE :) - - -# CORE -## core_startscript -## Type: String -## Default value: "res://" -## Enter the path to the game/application -## start script. It will be responsible -## for loading your game or application. -var core_startscript = "res://" - -# wmgr (Window Manager) -## wmgr_size_x -## Type: int -## Default value: 960 -## Defines the default window size (x axis) -var wmgr_size_x = 960 -## wmgr_size_y -## Type: Int -## Default value: 540 -## Defines the default window size (y axis) -var wmgr_size_y = 540 -## wmgr_title -## Type: String -## Default value: "Application/Game using CORE" -var wmgr_title = "Application/Game using CORE" -## wmgr_mode -## Type:int -## Default value: 0 -## ID | Mode -## 0 | Windowed -## 1 | Minimized -## 2 | Maximized -## 3 | Fullscreen -## 4 | Exclusive fullscreen -var wmgr_mode = 0 - -# Splash -## splash_enabled -## Type: bool -## Default value: false -## Enables or disables the splash screen at startup. -## Can be manually enabled with core.splash.display() -var splash_enabled = true -## splash_image -## Type: String -## Default value: "res://CORE/soscore.png" -## The path to your image that will be displayed -## in the center of the splash screen. -var splash_image = "res://CORE/soscore.png" -## splash_image_size -## Type: float -## Default value: 256 -## The size of your splash image. Used for both x and y. -var splash_image_size = 256 -## splash_color -## Type: String -## Default value: "000000" -## The splash screen's background color. Do not include -## a "#" at the start. -var splash_color = "000000" -``` diff --git a/docs/references/core.gd.md b/docs/references/core.gd.md deleted file mode 100644 index 27cfeda..0000000 --- a/docs/references/core.gd.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -hide: - - navigation ---- -# CORE Holder (core) -The **CORE Holder** is responsible for... well holding the components. - -## Constants -### version -- type `string` -- description `The CORE version.` -- format ` ` (`` can be either `release`, `prerelease` or `source`. `` is the latest version number) - -## Methods -### welcome() -- returns `void` -- description `Prints a welcome message and the CORE version.` - -## Internal Variables -Do not touch or you will cause breakage. -### locked -- type `bool` -- default value `false` -- description `If true, attach() will reject new components.` -### readycount -- type `int` -- default value `0` -- description `How many components have been fully initialized.` -### readylized -- type `bool` -- default value `false` -- description `If all components have been fully initialized. Is set to true if readycount is equal to the number of components.` - -## Internal functions -Do not call or you will cause breakage. -### attach() -- returns `void` -- description `Attaches a component to the CORE holder` - - argument `type` - - type `String` - - mandatory `yes` - - description `The component type. Can be "config", "wmgr", "smgr", "resmgr", "events" or "splash".` - - argument `component` - - type `none (intended types are "PackedScene" or "Script")` - - mandatory `yes` - - description `The component attach() should add to the SceneTree.` - - argument `do_setup` - - type `bool` - - mandatory `no, default value is true` - - description `If true, creates a new Control and sets the component as a script. Used for Scripts like "smgr.gd" but not for PackedScene's like "splash.tscn".` -### lock() -- returns `void` -- description `Sets the "locked" variable to true.` -### setready() -- returns `void` -- description `Increases "readycount" variable by 1 and checks if "readycount" is equal to the number of components.` - -# Trivia -- The variable [readylized](#readylized) was named like that because a signal called `ready` already exists in `Node` and can therefore not be used as a name. [JeremyStarâ„¢](https://git.staropensource.de/JeremyStarTM) then simply appended `lized` from `initialized` to `ready` and `readylized` was born. diff --git a/docs/references/events.gd.md b/docs/references/events.gd.md deleted file mode 100644 index 42c710e..0000000 --- a/docs/references/events.gd.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -hide: - - navigation ---- -# Events (core.events) -The **Events** component makes tracking changes in your application/game easier. - -## Signals -### window_title -- emitted on `window title change` -- argument `window_title` (type `String`) -- argument `previous_window_title` (type `String`) -### window_size -- emitted on `window size change` -- argument `update_coordinate` (type `String`, can be `X`, `Y` or `BOTH`) -- argument `window_size` (type `Vector2i`) -- argument `previous_window_size` (type `Vector2i`) -### window_pos -- emitted on `window position change` -- argument `update_coordinate` (type `String`, can be `X`, `Y` or `BOTH`) -- argument `window_pos` (type `Vector2i`) -- argument `previous_window_pos` (type `Vector2i`) -### logger_all -- emitted on `log output` -- argument `type` (type `String`, can be `"DIAG"`, `"INFO"`, `"WARN"` or `"ERROR"`) -- argument `script` (type `String`) -- argument `message` (type `String`) -### logger_diag -- emitted on `diagnostic log output` -- argument `script` (type `String`) -- argument `message` (type `String`) -### logger_info -- emitted on `informational log output` -- argument `script` (type `String`) -- argument `message` (type `String`) -### logger_warn -- emitted on `warning log output` -- argument `script` (type `String`) -- argument `message` (type `String`) -### logger_error -- emitted on `error log output` -- argument `script` (type `String`) -- argument `message` (type `String`) - -## Internal variables -### window_title_prev -- type `String` -- default value `""` -- description `The previous title.` -### window_size_x_prev -- type `int` -- default value `0` -- description `The previous window size (x coordinate)` -### window_size_y_prev -- type `int` -- default value `0` -- description `The previous window size (y coordinate)` -### window_pos_x_prev -- type `int` -- default value `0` -- description `The previous window position (x coordinate)` -### window_pos_y_prev -- type `int` -- default value `0` -- description `The previous window position (y coordinate)` - -## Internal functions -### _ready() -- returns `void` -- description `connects the logger's "logevent" signal with the "logger_update()" function` -### _process() -- returns `void` -- description `checks for window title, size and position changes and emits a signal if one changes` - - argument `_delta` - - type `float` - - mandatory `yes` - - description `The delta value passed by the engine` -### logger_update() -- returns `void` -- description `emits "logger_all" signal and checks against type and sends the corresponding "logger_" signal` - - argument `type` - - type `String` - - mandatory `yes` - - description `The log type` - - argument `script` - - type `String` - - mandatory `yes` - - description `The script responsible for the log output` - - argument `message` - - type `String` - - mandatory `yes` - - description `The log message` - - argument `_logmessage` - - type `String` - - mandatory `yes` - - description `The printed (processed) log message` diff --git a/docs/references/index.md b/docs/references/index.md index 898ff06..f3a0edf 100644 --- a/docs/references/index.md +++ b/docs/references/index.md @@ -3,15 +3,15 @@ hide: - navigation --- # References index -Here you can find all code references.
-**Index syntax**: *Human-friendly name (callable_gdscript.name)* +Welcome to the reference documentation! Here you can find everything you need to develop your game or application with CORE. -## [CORE configuration file (core.config)](/references/config.gd/) -## [CORE Holder (core)](/references/core.gd/) -## [Events (core.events)](/references/events.gd/) -## [Preprocessor (Preprocessor)](/references/preprocessor.gd/) -## [Resource Manager (core.resmgr)](/references/resmgr.gd/) -## [Scene Manager (core.smgr)](/references/smgr.gd/) -## [Splash Screen (core.splash)](/references/splash.gd/) -## [Window Manager (core.wmgr)](/references/wmgr.gd/) -## [Mother Of All Mods [Mod loader] (core.moam)](/references/moam.gd/) +## [The CORE configuration file](/references/Configuration_File/) +## [CORE](/references/CORE/) +## [Logger](/references/Logger/) +## [Preprocessor](/references/Preprocessor/) +## [Resource Manager](/references/ResourceManager/) +## [Scene Manager](/references/SceneManager/) +## [Splash Screen](/references/SplashScreen/) +## [Debug Display](/references/DebugDisplay/) +## [Miscellaneous](/references/Miscellaneous/) +## [Events](/references/Events/) diff --git a/docs/references/moam.gd.md b/docs/references/moam.gd.md deleted file mode 100644 index 58ff4fe..0000000 --- a/docs/references/moam.gd.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -hide: - - navigation ---- -# Mother Of All Mods [Modloader] (core.moam) -Loads and executes modifications. - -## Methods -### load_mods() -- returns `Array` -- description `Loads all modifications and returns all encountered errors as a a collection of strings` -### load_mod() -- returns `String` (if **not** `""` some error occured) -- description `Loads and executes a modification` - - argument `mod_name` - - type `String` - - mandatory `yes` - - description `The modification name to use` -### unload_mods() -- returns `void` -- description `Unloads all loaded modifications` -### unload_mod() -- returns `void` -- description `Unloads a modification` - - argument `mod_name` - - type `String` - - mandatory `yes` - - description `The modification name to use` -### get_list() -- returns `Array` -- description `Returns a list of all loaded modification names` -### get_info() -- returns `Dictionary` (if a error occured the dict will contain a `error` key) -- description `Returns information about a modification` - - argument `mod_name` - - type `String` - - mandatory `yes` - - description `The modification name to use` - -## Internal variables -Do not touch or you will cause breakage. -### modlist -- type `Array` -- default value `[]` -- description `All loaded modification (names)` -### config_loadpath -- type `String` -- default value `null` -- description `The mods directory all modifications are loaded from` -### config_wanted_name -- type `String` -- default value `null` -- description `Used for the modinfo filename. If set to "testapp" it will search for "testapp.coremod" files` -### config_wanted_version -- type `String` -- default value `null` -- description `The application or game version. Modifications will not load if they don't support the specified version` -### config_wanted_api -- type `String` -- default value `null` -- description `The application or game api version. Modifications will not load if they don't support the specified api version.` diff --git a/docs/references/preprocessor.gd.md b/docs/references/preprocessor.gd.md deleted file mode 100644 index f765e0c..0000000 --- a/docs/references/preprocessor.gd.md +++ /dev/null @@ -1,219 +0,0 @@ ---- -hide: - - navigation ---- -# Preprocessor (Preprocessor) -The **Preprocessor** can format text. -## Tags *(these can be used in log messages too!)* -All tags can be escaped by adding `esc_` before the tag name. Example: -```text -Raw: -Output: -``` -### No process `` -- end tag `no` -- description `Disables preprocessing completely. Doesn't even display the prefix.` -- example: -``` text -Raw: This is atest MESSage. -Output: This is atest MESSage. -``` -### Newline `` -- end tag `no` -- description `Makes a newline while respecting the prefix. Is much recommended over "\n".` -- example (with prefix `prefix_`): -``` text -Raw: Very nice message!Here's another message :) -Output: -prefix_Very nice message! - Here's another message :) -``` -### Lowercase `` -- end tag `yes` -- description `Makes your text lowercase.` -- example: -``` text -Raw: Did you FiNd THAT funny? -Output: Did you find thaT funny? -``` -### Uppercase `` -- end tag `yes` -- description `Makes your text uppercase.` -- example: -``` text -Raw: ThiS TeXT should be UPPercaSED -Output: ThiS TeXT SHOULD BE UPPERcaSED -``` -### Camelcase `` -- end tag `yes` -- description `Makes your text camelcase.` -- example: -``` text -Raw: This text should be CamelCased. -Output: This textShouldBeCamelCased. -``` -### Pascalcase `` -- end tag `yes` -- description `Makes your text pascalcase.` -- example: -``` text -Raw: This text should be PascelCased. -Output: This TextShouldBePascelCased. -``` -### Snakecase `` -- end tag `yes` -- description `Makes your text snakecase.` -- example: -``` text -Raw: This text should be SnakeCased. -Output: This text_should_be_snake_cased. -``` -## Variables -### enabled -- type `bool` -- default value `true` -- description `Enables or disables the preprocessor.` -### verbose_logging -- type `bool` -- default value `false` -- description `Makes the log unreadable. Adds about twenty lines to every process() call.` -### tests_enabled -- type `bool` -- default value `true` -- description `Enables or disables preprocessor testing. Recommended to leave enabled as it disables the preprocessor if it's malfunctioning (somehow). Better to have unformatted text than broken text.` -### tests_level -- type `int` -- default value `1` -- description `Controls when test results are displayed. 0 = Never, 1 = On failure, 2 = Always` - -## Methods -### do_tests() -- returns `void` -- description `Performs tests on all preprocessor functions. Very useful for catching bugs while debugging and/or modifying the preprocessor.` - - argument `ignore_flag` - - type `bool` - - mandatory `no, default value is false` - - description `ignores the "tests_enabled" variable if set to true` -### process() -- returns `String` -- description `Formats a message` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for processing` - - argument `prefix` - - type `String` - - mandatory `yes` - - description `The prefix used for newlines` - - argument `pre_msg` - - type `String` - - mandatory `no, default value is ""` - - description `Inserted before the message` - - argument `post_msg` - - type `String` - - mandatory `no, default value is ""` - - description `Inserted after the message` - - argument `exclusion_filter` - - type `Array` - - mandatory `no, default value is []` - - description `Removes specific Strings from the prefix (used in calculating spaces in _newline())` - -## Internal variables -Do not touch these or you will cause breakage. -### tests_executed -- type `bool` -- default value `false` -- description `If tests have been executed already or not.` -### tests_log -- type `String` -- default value `""` -- description `The latest preprocessor testing log.` -### tests_success -- type `int` -- default value `0` -- description `The testing success count. If the value is 12, testing succeeded. If not, something is broken.` - -## Internal Methods -Do not execute these or you will cause breakage. -### _ready() -- returns `void` -- description `Executes do_tests() and imports logger.` -### _newline() -- returns `String` -- description `Processes the tag` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for processing the tag` - - argument `prefix` - - type `String` - - mandatory `yes` - - description `The prefix used for newlines` - - argument `pre_msg` - - type `String` - - mandatory `yes` - - description `Inserted before the message` - - argument `post_msg` - - type `String` - - mandatory `yes` - - description `Inserted after the message` - - argument `exclusion_filter` - - type `Array` - - mandatory `yes` - - description `Removes specific Strings from the prefix (used in calculating spaces)` -### _case_lower() -- returns `String` -- description `Processes the tags` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for processing the tags` -### _case_upper() -- returns `String` -- description `Processes the tags` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for processing the tags` -### _case_camelcase() -- returns `String` -- description `Processes the tags` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for processing the tags` -### _case_pascalcase() -- returns `String` -- description `Processes the tags` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for processing the tags` -### _case_snakecase() -- returns `String` -- description `Processes the tags` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for processing the tags` -### _case() -- returns `String` -- description `Executes all _case_* functions` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The messages passed to all other _case_* functions` -### _escapes() -- returns `String` -- description `It escapes tags` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for processing the tags` -### _noprocess() -- returns `bool` -- description `Checks if the "msg" variable contains ""` - - argument `msg` - - type `String` - - mandatory `yes` - - description `The message used for searching ""` diff --git a/docs/references/smgr.gd.md b/docs/references/smgr.gd.md deleted file mode 100644 index 1d2984f..0000000 --- a/docs/references/smgr.gd.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -hide: - - navigation ---- -# Scene Manager (core.smgr) -Responsible for displaying scenes in order. - -## Overlays -The scene manager uses something called **overlays**. They hold scenes while keeping order. You can think of them like organized collections of scenes *(because they are exactly that)*. There are four **configurable** and one **unconfigurable** overlay. -### Overlay #1 - `debug` -- description `The debug overlay should contain things like a FPS counter, debug menu, etc..` -- configurable `yes` -- more than one scene `yes` -- adding a scene **[add_debug()](#add_debug)** -- removing a scene **[remove_debug()](#remove_debug)** -### Overlay #2 - `cutscene` -- description `The cutscene should contain... well a cutscene.` -- configurable `yes` -- more than one scene `no` -- adding a scene **[add_cutscene()](#add_cutscene)** -- removing a scene **[remove_cutscene()](#remove_cutscene)** -### Overlay #3 - `menu` -- description `The menu overlay should contain multiple menu scenes.` -- configurable `yes` -- more than one scene `yes` -- adding a scene **[add_menu()](#add_menu)** -- removing a scene **[remove_menu()](#remove_menu)** -### Overlay #4 - `game` -- description `The game overlay should contain a game scene. We recommend displaying main menus under the game instead of the menu overlay.` -- configurable `yes` -- more than one scene `no` -- adding a scene **[add_game()](#add_game)** -- removing a scene **[remove_game()](#remove_game)** -### Overlay #5 - `COREBackground` -- description `COREBackground is a unconfigurable overlay responsible for displaying the log and serves as a background if nothing is displayed.` -- configurable `no` -- more than one scene `no` - -## Methods -### add_debug() -- returns `bool` -- description `Adds a PackedScene to the debug overlay.` - - argument `resource_name` - - type `String` - - mandatory `yes` - - description `Used for loading the scene and the loaded scene name.` -### remove_debug() -- returns `bool` -- description `Removes a menu scene from the debug overlay.` - - argument `scene_name` - - type `String` - - mandatory `yes` - - description `Should be the same as the "resource_name" argument used previously in add_debug().` -### add_cutscene() -- returns `bool` -- description `Adds a PackedScene to the cutscene overlay.` - - argument `resource_name` - - type `String` - - mandatory `yes` - - description `Used for loading the scene and the loaded scene name.` -### remove_cutscene() -- returns `bool` -- description `Removes the game scene from the cutscene overlay.` -### add_menu() -- returns `bool` -- description `Adds a PackedScene to the menu overlay.` - - argument `resource_name` - - type `String` - - mandatory `yes` - - description `Used for loading the scene and the loaded scene name.` -### remove_menu() -- returns `bool` -- description `Removes a menu scene from the menu overlay.` - - argument `scene_name` - - type `String` - - mandatory `yes` - - description `Should be the same as the "resource_name" argument used previously in add_menu().` -### add_game() -- returns `bool` -- description `Adds a PackedScene to the game overlay.` - - argument `resource_name` - - type `String` - - mandatory `yes` - - description `Used for loading the scene and the loaded scene name.` -### remove_game() -- returns `bool` -- description `Removes the game scene from the game overlay.` - -## Internal Variables -Do not touch or you will cause breakage. -### ccr -- type `Control` -- default value `null` -- description `The CORE Scene Root.` -### ccr_debug -- type `Control` -- default value `null` -- description `The debug overlay.` -### ccr_debug_names -- type `Array` -- default value `[]` -- description `A collection of all resource names loaded in the debug overlay.` -- Format `["resource_name"]` -### ccr_cutscene -- type `Control` -- default value `null` -- description `The cutscene overlay.` -### ccr_cutscene_inuse -- type `bool` -- default value `null` -- description `Used for checking if a cutscene scene has been loaded already.` -### ccr_menu -- type `Control` -- default value `null` -- description `The menu overlay.` -### ccr_menu_names -- type `Array` -- default value `[]` -- description `A collection of all resource names loaded in the menu overlay.` -- Format `["resource_name"]` -### ccr_game -- type `Control` -- default value `null` -- description `The game overlay.` -### ccr_game_inuse -- type `bool` -- default value `null` -- description `Used for checking if a game scene has been loaded already.` - -## Internal methods -Do not execute these or you will cause breakage. -### _ready() -- returns `void` -- description `Adds the CORE Scene Root, migrates it and executes add_overlays()` -### add_overlays() -- returns `void` -- description `Adds all configurable overlays.` diff --git a/docs/references/splash.gd.md b/docs/references/splash.gd.md deleted file mode 100644 index 9e29f12..0000000 --- a/docs/references/splash.gd.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -hide: - - navigation ---- -# Splash Screen (core.splash) -The splash screen component allows you to display a "loading screen" whilst hiding log output (COREBackground). - -## Variables -### image -- type `String` -- default value `` -- description `Path to a image, displayed in the center of the splash screen.` -### image_size -- type `float` -- default value `` -- description `The size of your image. Used for both the x and y coordinates.` -### color -- type `String` -- default value `` -- description `The background color.` -- format `AARRGGBB` or `RRGGBB` (`AA` = `alpha`, `RR` = `red`, `GG` = `green` and `BB` = `blue`) - -## Methods -### apply_config() -- returns `void` -- description `Applies the variables "image", "image_size" and "color" to the scene.` -### display() -- returns `void` -- description `Makes the splash screen visible.` -### dissolve() -- returns `void` -- description `Makes the splash screen invisible.` - -## Internal variables -Do not touch or you will cause breakage. -### enabled -- type `bool` -- default value ` -- description `If the splash screen module should be displayed at CORE startup or not.` - -## Internal methods -Do not execute or you will cause breakage. -### _ready() -- returns `void` -- description `Executes apply_config() and executes display() if "enabled" is true.` diff --git a/docs/references/wmgr.gd.md b/docs/references/wmgr.gd.md deleted file mode 100644 index a537db2..0000000 --- a/docs/references/wmgr.gd.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -hide: - - navigation ---- -# Window manager (core.wmgr) -Responsible for managing the main window. - -## Modes -The window can be in one of five different modes. Those are: -### `WINDOWED` -A floating window. -### `MINIMIZED` -Minimizes the window to the taskbar/application list/etc.. -### `MAXIMIZED` -Maximizes the window. -### `FULLSCREEN` -Hides all decorations and sets the window size to the screen size. Has multi-window support. -### `EXCLUSIVE_FULLSCREEN` -Same as the `FULLSCREEN` mode but has way less overhead at the cost of loosing multi-window support. Has different effects on different platforms:
-**Windows**: *Depending on the video driver, the screen might black out for a few seconds.*
-**macOS**: *Prevents the dock and menu from showing up when hovering over the edge of the screen.*
-**Linux/BSD**: *Disables compositing (transparency effects, window close animation, etc.)* - -## Methods -### set_size() -- returns `void` -- description `Updates the window size.` - - argument `x` - - type `int` - - mandatory `yes` - - description `The new window size (x coordinate).` - - argument `y` - - type `int` - - mandatory `yes` - - description `The new window size (y coordinate).` -### get_size() -- returns `Vector2i` -- description `Returns the window size.` -### set_position() -- returns `void` -- description `Updates the window position.` - - argument `x` - - type `int` - - mandatory `yes` - - description `The new window position (x coordinate).` - - argument `y` - - type `int` - - mandatory `yes` - - description `The new window position (y coordinate).` -### get_position() -- returns `Vector2i` -- description `Returns the window position.` -### set_title() -- returns `void` -- description `Updates the window title.` - - argument `title` - - type `String` - - mandatory `yes` - - description `The new window title.` -### get_title() -- returns `String` -- description `Returns the window title.` -### set_mode() -- returns `void` -- description `Updates the window mode.` - - argument `mode` - - type `String` - - mandatory `yes` - - description `The new window mode.` - - format follows `wmgr modes` -### get_mode() -- returns `String` -- description `Returns the window mode.` -### get_fps() -- returns `float` -- description `Returns the current framerate, also known as FPS or frames per second.` -- format `NUMBER.NUMBER` (if argument `flat` is `false`), `NUMBER` (if argument `flat` is `true`) or `INF` if the frame rate is infinite (can be caused if the physics fps is set too high, "should" never occur) - - argument `flat` - - type `bool` - - mandatory `no, default value is false` - - description `If decimal numbers should be returned or not.` - - format `If "true" decimal numbers will be removed, if "false" not.` -### get_rendertime() -- returns `float` -- description `Returns how long the last frame took to render (render time).` -### get_delta() -- returns `float` -- description `Returns the latest delta value.` - -## Internal variables -Do not touch or you will cause breakage. -### window_size_x -- type `int` -- default value `` -- description `The window size (x coordinate). Used at startup only.` -### window_size_y -- type `int` -- default value `` -- description `The window size (y coordinate). Used at startup only.` -### window_title -- type `String` -- default value `` -- description `The window title. Used at startup only.` -### window_mode -- type `String` -- default value `` -- description `The window mode. Used at startup only.` -- format follows `wmgr modes` -### delta -- type `float` -- default value `0` -- description `The latest delta value passed by the engine.` - -## Internal methods -Do not execute or you will cause breakage. -### _ready() -- returns `void` -- description `Applies config variables.` -### _process() -- returns `void` -- description `Updates the "delta" variable.` - - argument `delta` - - type `float` - - mandatory `yes` - - description `You know what it is.` diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index ebbb698..f8c3903 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -5,42 +5,5 @@ hide: # Troubleshooting CORE **Warning:** This is a very messy document. Use the table of contents to get to your specified error. If you can't find your problem here, [create a issue](https://git.staropensource.de/staropensource/core/issues/new). -## Invalid argument issues -### (wmgr) [ERROR] Invalid window mode "``". -[wmgr's set_mode() function](/references/wmgr/#set_mode) recieved a invalid window mode. Only possible options are `"WINDOWED"`, `"MINIMIZED"`, `"MAXIMIZED"`, `"FULLSCREEN"` and `"EXCLUSIVE_FULLSCREEN"`. -### (smgr) [ERROR] Resource is not type of PackedScene -You tried loading something that's not a scene into the SceneTree. Check against what you are loading first! - -## Common errors -### (smgr) [ERROR] Failed adding `` scene: Only one `` scene is allowed -Only one scene can be loaded into the `game` and `cutscene` overlays. Perform a check against the overlay first! [Click here for the smgr reference page](/references/smgr/) -### (smgr) [ERROR] Failed removing `` scene: No `` scene is active -You tried removing a scene in the `game` or `cutscene` overlay, but no scene is loaded in that overlay. Perform a check against the overlay first! [Click here for the smgr reference page](/references/smgr/) -### (smgr) [ERROR] Failed adding `` scene: `` scene with name "``" already exists -You tried loading a scene into the `menu` or `debug` overlay, but another scene with the same name already exists in that overlay. Perform a check against the overlay first! [Click here for the smgr reference page](/references/smgr/) -### (resmgr) [ERROR] Loading "``" failed: Resource is loaded already -You tried loading a resource with the resource manager, but a resource with the same name is loaded already. Perform a check against the resmgr first! [Click here for the resmgr reference page](/references/resmgr/) -### (resmgr) [ERROR] Unloading "``" failed: Resource is not present -You tried unloading a resource that is not loaded. Perform a check against the resmgr first! [Click for the resmgr reference page](/references/resmgr/) -### (resmgr) [ERROR] `` a batch failed: Batch is empty -The resource manager can't process a empty batch. Fill it with some information. [Click for the resmgr reference page](/references/resmgr/) - - -## Startup issues -### coreinit -> CORE only supports Godot ``. Please upgrade/downgrade your Godot Project to ``. -Update or downgrade your Godot version to one that CORE supports. See the [requirements page](/requirements/) for more information. -### coreinit -> The CORE logger is missing in your autoload project settings! -The CORE logger (found at `res://CORE/logger.gd`) is missing from your autoload list. Just add it under the name `Logger` and make sure to check `Global variable`. -### coreinit -> The CORE preprocessor is missing in your autoload project settings! -The CORE preprocessor (found at `res://CORE/preprocessor.gd`) is missing from your autoload list. Just add it under the name `Preprocessor` and make sure to check `Global variable`. -### coreinit -> The CORE configuration file (config.gd) is missing! Please copy the config.gd.example file and rename it to config.gd! -The CORE configuration file is missing. Just copy `config.gd.example` and rename it to `config.gd`. Make sure to update it to your likings. -### coreloader.gd:46 @ _ready(): Resource file not found: res://. -The variable `core_startupscript` in CORE's `config.gd` file is empty or points to a missing script. Either set the variable or create a new initialization script. - -## Impossible errors -**If you somehow encounter one of these errors, [report them immediately please](https://git.staropensource.de/staropensource/core/issues/new).** -### Failed attaching `` to CORE: Invalid component -Failed attaching a CORE component (for example `resmgr`) to the CORE holder (`core.gd`). -### Failed to get window mode: The window mode id "`" is not known to CORE. -Godot reported a window mode that CORE can't handle. Can be caused if the version check is removed and a higher Godot version is used than CORE supports. +## Work In Progress +This page will be documented soon. Just shoot [a mail](mailto:support@staropensource.de) or [a private message](https://net.staropensource.de/@soscore) at us for now. diff --git a/docs/update.md b/docs/update.md index 2077f11..3fb1f85 100644 --- a/docs/update.md +++ b/docs/update.md @@ -6,5 +6,3 @@ hide: Updating CORE is the same process as installing it. Just click on `Update` instead of `Install` in the **CORE Manager**. ### [Click to visit the installation page](/install/) - -Note for contributers: If the update process changes in the future we just need to update the documentation page instead of the whole documentation. diff --git a/events.gd b/events.gd index 93d411e..00bc2e7 100644 --- a/events.gd +++ b/events.gd @@ -1,19 +1,28 @@ -# events.gd -# Events -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### extends Node -@onready -var core = get_node(NodePath("/root/core")) -var window_title_prev = "" -var window_size_x_prev = 0 -var window_size_y_prev = 0 -var window_pos_x_prev = 0 -var window_pos_y_prev = 0 +# CORE modules +var core: Node = null +var logger: Node = null +# Used for checking if any values have changed +var prev_window_title: String = "" +var prev_window_size_x: int = 0 +var prev_window_size_y: int = 0 +var prev_window_pos_x: int = 0 +var prev_window_pos_y: int = 0 + +# Event signals signal window_title signal window_size signal window_pos @@ -23,52 +32,64 @@ signal logger_info signal logger_warn signal logger_error +# Set up connection between logger's logevent and logger_update() func initialize() -> void: if core.protection_mode: return - Logger.connect("logevent",Callable(self,"logger_update")) - core.setready() - -func _process(_delta:float) -> void: - if core.protection_mode: return - var window_title_var = core.wmgr.get_title() - var window_size_x = core.wmgr.get_size().x - var window_size_y = core.wmgr.get_size().y - var window_pos_x = core.wmgr.get_position().x - var window_pos_y = core.wmgr.get_position().y - if window_title_prev != window_title_var: - emit_signal("window_title",window_title_var,window_title_prev) - window_title_prev = window_title_var - if window_size_x != window_size_x_prev and window_size_y != window_size_y_prev: - emit_signal("window_size","BOTH",Vector2i(window_size_x,window_size_y),Vector2i(window_size_x_prev,window_size_y_prev)) - window_size_x_prev = window_size_x - window_size_y_prev = window_size_y - elif window_size_x != window_size_x_prev: - emit_signal("window_size","X",Vector2i(window_size_x,window_size_y),Vector2i(window_size_x_prev,window_size_y_prev)) - window_size_x_prev = window_size_x - elif window_size_y != window_size_y_prev: - emit_signal("window_size","Y",Vector2i(window_size_x,window_size_y),Vector2i(window_size_x_prev,window_size_y_prev)) - window_size_y_prev = window_size_y - if window_pos_x != window_pos_x_prev and window_pos_y != window_pos_y_prev: - emit_signal("window_pos","BOTH",Vector2i(window_pos_x,window_pos_y),Vector2i(window_pos_x_prev,window_pos_y_prev)) - window_pos_x_prev = window_pos_x - window_pos_y_prev = window_pos_y - elif window_pos_x != window_pos_x_prev: - emit_signal("window_pos","X",Vector2i(window_pos_x,window_pos_y),Vector2i(window_pos_x_prev,window_pos_y_prev)) - window_pos_x_prev = window_pos_x - elif window_pos_y != window_pos_y_prev: - emit_signal("window_pos","Y",Vector2i(window_pos_x,window_pos_y),Vector2i(window_pos_x_prev,window_pos_y_prev)) - window_pos_y_prev = window_pos_y + # logevent (signal) -> logger_update() + logger.connect("logevent",Callable(self,"logger_update")) func logger_update(type:String,script:String,message:String,_logmessage:String) -> void: if core.protection_mode: return + # Emit signal logger_all for all log messages emit_signal("logger_all",type,script,message) + # Check for log type and emit the right signal if type == "DIAG": emit_signal("logger_diag",script,message) elif type == "INFO": emit_signal("logger_info",script,message) elif type == "WARN": emit_signal("logger_warn",script,message) - elif type == "ERROR": + elif type == "ERR!": emit_signal("logger_error",script,message) else: core.exception("events","The log type \"" + type + "\" is not known to events.gd") + +# Check various variables and emit signals if they changed +func _process(_delta:float) -> void: + process_window_title() + process_window_size() + process_window_pos() + +func process_window_title() -> void: + var new_window_title: String = get_tree().root.title + if prev_window_title != new_window_title: + emit_signal("window_title",new_window_title,prev_window_title) + prev_window_title = new_window_title + +func process_window_size() -> void: + var new_window_size_x: int = DisplayServer.window_get_size().x + var new_window_size_y: int = DisplayServer.window_get_size().y + if new_window_size_x != prev_window_size_x and new_window_size_y != prev_window_size_y: + emit_signal("window_size","BOTH",Vector2i(new_window_size_x,new_window_size_y),Vector2i(prev_window_size_x,prev_window_size_y)) + prev_window_size_x = new_window_size_x + prev_window_size_y = new_window_size_y + elif new_window_size_x != prev_window_size_x: + emit_signal("window_size","X",Vector2i(new_window_size_x,new_window_size_y),Vector2i(prev_window_size_x,prev_window_size_y)) + prev_window_size_x = new_window_size_x + elif new_window_size_y != prev_window_size_y: + emit_signal("window_size","Y",Vector2i(new_window_size_x,new_window_size_y),Vector2i(prev_window_size_x,prev_window_size_y)) + prev_window_size_y = new_window_size_y + +func process_window_pos() -> void: + var new_window_pos_x: int = DisplayServer.window_get_position().x + var new_window_pos_y: int = DisplayServer.window_get_position().y + if new_window_pos_x != prev_window_pos_x and new_window_pos_y != prev_window_pos_y: + emit_signal("window_pos","BOTH",Vector2i(new_window_pos_x,new_window_pos_y),Vector2i(prev_window_pos_x,prev_window_pos_y)) + prev_window_pos_x = new_window_pos_x + prev_window_pos_y = new_window_pos_y + elif new_window_pos_x != prev_window_pos_x: + emit_signal("window_pos","X",Vector2i(new_window_pos_x,new_window_pos_y),Vector2i(prev_window_pos_x,prev_window_pos_y)) + prev_window_pos_x = new_window_pos_x + elif new_window_pos_y != prev_window_pos_y: + emit_signal("window_pos","Y",Vector2i(new_window_pos_x,new_window_pos_y),Vector2i(prev_window_pos_x,prev_window_pos_y)) + prev_window_pos_y = new_window_pos_y diff --git a/logger.gd b/logger.gd index b45d6af..f468855 100644 --- a/logger.gd +++ b/logger.gd @@ -1,73 +1,118 @@ -# logger.gd -# CORE Logger -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 -extends Control +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### +extends Node +# CORE modules +var core: Node = null +var preprocessor: Node = null + +# Enables/disables the logger +var enabled: bool = true +# Enables/disables diagnostic log messages +var diagnostic: bool = false + +# Signals signal logevent -@onready -var preprocessor = get_node(NodePath("/root/Preprocessor")) -@export -@export_category("Configuration") -# Enables/disables logging -var enable = true -@export -@export_category("Configuration") -# Enables/disables diagnostic/verbose logging -var enable_diag = false +func initialize() -> void: + if core.protection_mode: return + if preprocessor == null: + return + diag("CORE/logger.gd","Logger is ready.") -# Initializes the -func _ready() -> void: - print("logger -> Initializing Logger") - if get_node_or_null(NodePath("/root/Preprocessor")) == null: - print("logger -> Preprocessor is not loaded. Shutting application down...") - get_tree().quit(1) - await get_tree().create_timer(1).timeout - diag("Logger","Logger is ready.") - -func diag(script:String,message:String,preproc:bool = false) -> void: - if enable and enable_diag: - if preproc and Preprocessor.enabled: - var logmsg = preprocessor.process(message,"[color=gray](" + script + ") [DIAG] [/color]","[color=gray][b]","[/b][/color]",["[color=gray]","[/color]"]) +func diag(script:String,message:String,preproc:bool = true) -> void: + if core.protection_mode: return + # Check if both the logger and diagnostic log messages are enabled + if enabled and diagnostic: + # Check if preprocessing is allowed for this message and if the preprocessor is enabled + if preproc and preprocessor.enabled: + # Run the message through the preprocessor if enabled/allowed + var logmsg: String = preprocessor.process(message,"[color=gray](" + script + ") [DIAG] [/color]","[color=gray][b]","[/b][/color]",["[color=gray]","[/color]"]) + # Print the message print_rich(logmsg) + # Emit logevent signal emit_signal("logevent","DIAG",script,message,logmsg) else: - var logmsg = "[color=gray](" + script + ") [DIAG] [b]" + message + "[/b][/color]" - print_rich(logmsg) + # Construct a log message normally if preprocessor is disabled/disallowed + # Note: We do not include bold and color tags in here because they can mess + # up the log messages in some cases + var logmsg: String = "(" + script + ") [DIAG] " + message + # Print the message + print(logmsg) + # Emit logevent signal emit_signal("logevent","DIAG",script,message,logmsg) func info(script:String,message:String,preproc:bool = true) -> void: - if enable: - if preproc and Preprocessor.enabled: - var logmsg = preprocessor.process(message,"[color=white](" + script + ") [INFO] [/color]","[color=white][b]","[/b][/color]",["[color=white]","[/color]"]) + if core.protection_mode: return + # Check if the logger is enabled + if enabled: + # Check if preprocessing is allowed for this message and if the preprocessor is enabled + if preproc and preprocessor.enabled: + # Run the message through the preprocessor if enabled/allowed + var logmsg: String = preprocessor.process(message,"[color=white](" + script + ") [INFO] [/color]","[color=white][b]","[/b][/color]",["[color=white]","[/color]"]) + # Print the message print_rich(logmsg) + # Emit logevent signal emit_signal("logevent","INFO",script,message,logmsg) else: - var logmsg = "(" + script + ") [INFO] [b]" + message + "[/b]" - print_rich(logmsg) + # Construct a log message normally if preprocessor is disabled/disallowed + # Note: We do not include bold and color tags in here because they can mess + # up the log messages in some cases + var logmsg: String = "(" + script + ") [INFO] " + message + # Print the message + print(logmsg) + # Emit logevent signal emit_signal("logevent","INFO",script,message,logmsg) func warn(script:String,message:String,preproc:bool = true) -> void: - if enable: - if preproc and Preprocessor.enabled: - var logmsg = preprocessor.process(message,"[color=orange](" + script + ") [WARN] [/color]","[color=orange][b]","[/b][/color]",["[color=orange]","[/color]"]) + if core.protection_mode: return + # Check if the logger is enabled + if enabled: + # Check if preprocessing is allowed for this message and if the preprocessor is enabled + if preproc and preprocessor.enabled: + # Run the message through the preprocessor if enabled/allowed + var logmsg: String = preprocessor.process(message,"[color=orange](" + script + ") [WARN] [/color]","[color=orange][b]","[/b][/color]",["[color=orange]","[/color]"]) + # Print the message print_rich(logmsg) + # Emit logevent signal emit_signal("logevent","WARN",script,message,logmsg) else: - var logmsg = "[color=orange](" + script + ") [WARN] [b]" + message + "[/b][/color]" - print_rich(logmsg) + # Construct a log message normally if preprocessor is disabled/disallowed + # Note: We do not include bold and color tags in here because they can mess + # up the log messages in some cases + var logmsg: String = "(" + script + ") [WARN] " + message + # Print the message + print(logmsg) + # Emit logevent signal emit_signal("logevent","WARN",script,message,logmsg) func error(script:String,message:String,preproc:bool = true) -> void: - if enable: - if preproc and Preprocessor.enabled: - var logmsg = preprocessor.process(message,"[color=red](" + script + ") [ERROR] [/color]","[color=red][b]","[/b][/color]",["[color=red]","[/color]"]) + if core.protection_mode: return + # Check if the logger is enabled + if enabled: + # Check if preprocessing is allowed for this message and if the preprocessor is enabled + if preproc and preprocessor.enabled: + # Run the message through the preprocessor if enabled/allowed + var logmsg: String = preprocessor.process(message,"[color=red](" + script + ") [ERR!] [/color]","[color=red][b]","[/b][/color]",["[color=red]","[/color]"]) + # Print the message print_rich(logmsg) - emit_signal("logevent","ERROR",script,message,logmsg) + # Emit logevent signal + emit_signal("logevent","ERR!",script,message,logmsg) else: - var logmsg = "[color=red](" + script + ") [ERROR] [b]" + message + "[/b][/color]" - print_rich(logmsg) - emit_signal("logevent","ERROR",script,message,logmsg) + # Construct a log message normally if preprocessor is disabled/disallowed + # Note: We do not include bold and color tags in here because they can mess + # up the log messages in some cases + var logmsg: String = "(" + script + ") [ERR!] " + message + # Print the message + print(logmsg) + # Emit logevent signal + emit_signal("logevent","ERR!",script,message,logmsg) diff --git a/misc.gd b/misc.gd new file mode 100644 index 0000000..fd7ca32 --- /dev/null +++ b/misc.gd @@ -0,0 +1,68 @@ +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### +extends Node + +# CORE modules +var core: Node = null + +# Delta value, used for get_fps() and get_delta() +var delta: float = 0.0 + +# Updates delta variable +func _process(delta_process) -> void: + delta = delta_process + +# Returns the title of the main window +## Included as DisplayServer.window_get_title() (for some +## reason) does not exist and not many know that /root/ +## is a Window node (which does have a "title" variable) +func get_title() -> String: + if core.protection_mode: return "" + return get_tree().root.title + +# Returns the current FPS (Frames Per Second) value +func get_fps(flatten:bool = false) -> float: + if core.protection_mode: return 0.0 + if str(delta) == "0": + # In the rare case where delta is zero, return INF + return INF + else: + if flatten: + # Removes decimal numbers + return float(int(1/delta)) + else: + # Yes, it's weird but 1/delta does return the FPS value. + return 1/delta + +# Returns the time it took Godot to render a frame +func get_rendertime() -> float: + if core.protection_mode: return 0.0 + return Performance.get_monitor(Performance.TIME_PROCESS) + +# Returns the delta time +func get_delta() -> float: + if core.protection_mode: return 0.0 + return delta + +# Converts a number of bytes to a number of mebibytes +func byte_to_mib(bytes:int,flatten:bool = true) -> float: + if flatten: + @warning_ignore("integer_division") + return bytes/1048576 + return bytes/float(1048576) + +# Flattens a floating point number +func flat_float(number:float) -> float: + return float(int(number)) + +func flat_float_int(number:float) -> int: + return int(number) diff --git a/mkdocs.yml b/mkdocs.yml index 1f2da59..4adb6db 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -21,7 +21,8 @@ nav: - Home: index.md - Licensing: licensing.md - Installing: install.md - - Updating: update.md + - Quick Start Guide: quickstartguide.md + - Breaking commits: breaking-commits.md - Troubleshooting: troubleshooting.md - References: references/ - Source code: https://git.staropensource.de/staropensource/core/ diff --git a/mkdown.gd b/mkdown.gd index 1fb4dc6..425d2af 100644 --- a/mkdown.gd +++ b/mkdown.gd @@ -1,13 +1,27 @@ +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### extends Node -@onready -var core = get_node("/root/core") -var fsizes = {"text":"16","h1":"29","h2":"24","h3":"19","h4":"14","h5":"9","h6":"4"} +# CORE modules +var core: Node = null +var logger: Node = null + +# Font sizes +var fsizes: Dictionary = {"text":"16","h1":"29","h2":"24","h3":"19","h4":"14","h5":"9","h6":"4"} func parse(content:String) -> String: - var parse_text = "" + var parse_text: String = "" for line in content.split("\n",false): - var line_mod = line + var line_mod: String = line if line_mod.begins_with("######"): line_mod = line_mod.replace("######","[font_size=" + fsizes["h6"] + "]") + "[/font_size]" elif line_mod.begins_with("#####"): @@ -24,6 +38,3 @@ func parse(content:String) -> String: line_mod = "[font_size=" + fsizes["text"] + "]" + line_mod + "[/font_size]" parse_text = parse_text + line_mod + "\n" return parse_text - -func initialize() -> void: - core.setready() diff --git a/preprocessor.gd b/preprocessor.gd index d1af0df..3f1c2b5 100644 --- a/preprocessor.gd +++ b/preprocessor.gd @@ -1,193 +1,60 @@ -# preprocessor.gd -# CORE Text Preprocessor -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 -# -# list/table: -# Tag | Description -# | Newline (DO NOT USE '\n'!) -# | Text is lowercase until closing tag -# | Text is UPPERCASE until closing tag -# | Text is camelCase until closing tag -# | Text is PascalCase until closing tag -# | Text is snake_case until closing tag -# | Closing tag for -#
| Closing tag for -# | Closing tag for -# | Closing tag for -# | Closing tag for +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### +extends Node -extends Control +## ## # ##### ##### #### +## # # # # # # # +## # # # # # # #### +## # ## # # # # +## # # ##### # #### +## The preprocessor is *very* undocumented at this point +## in time as it is a little bit complicated. We may document +## it in the future, but for now you have to read the source. +## +## - JeremyStarTM -var logger = null -@export_category("Configuration") -# Enables/disables Preprocessor. +# CORE modules +var core: Node = null +var logger: Node = null + +# Enables/disables preprocessor functionality @export var enabled = true -# Enables/disables verbose preprocessing. DO NOT ENABLE. VERBOSE PREPROCESSING ADDS 20 LINES FOR EACH LOGGER CALL WITH PREPROCESSING ENABLED AND MAKES THE LOG UNREADABLE. ONLY ENABLE IF YOU KNOW WHAT YOU ARE DOING. -# Requires Logger.enable -> true -@export var verbose_logging = false -# Enables/disables Preprocessor tests. Please do not disable as testing the preprocessor can help catch bugs early. -# Requires enabled -> true -@export var tests_enabled = true -# Controls how test results are displayed -# 0 = Never show results -# 1 = Only display on failure -# 2 = Always display -@export var tests_level = 1 -var tests_executed = false -var tests_log = "" -var tests_success = 0 +# Do not enable unless you exactly know what you are doing! +# It will spam your log chock full of useless garbage! +@export var diagnostic = false -func _ready() -> void: - print("preprocessor -> Initializing Preprocessor") - print("preprocessor -> Delaying initialization by 0.75s") - await get_tree().create_timer(0.75).timeout - logger = get_node(NodePath("/root/Logger")) - await get_tree().create_timer(0.05).timeout - do_tests(false) - if enabled: - logger.diag("Preprocessor","Preprocessor ready.",false) - else: - logger.diag("Preprocessor","Preprocessor disabled.",false) - -# Performs tests on all Preprocessor features to help catch bugs while debugging. -# Recommended to leave enabled because log output might look weird if the a faulty commit is installed. -# Use tests_executed to check if the tests have been executed, use tests_log for the test log and -# read tests_success if you want the number of successful tests. -func do_tests(ignore_flag:bool = false) -> void: - logger.diag("Preprocessor","Testing preprocessor...",false) - # If tests are disaled and ignore_flag is false return - if !tests_enabled and !ignore_flag: - logger.diag("Preprocessor","Testing failed: Tests are disabled.",false) +# Checks if logger is null +func initialize() -> void: + if core.protection_mode: return + if logger == null: return - # If the Preprocessor is not enabled return - if !enabled: - logger.diag("Preprocessor","Testing failed: Preprocessor is disabled.",false) - return - # Expected test resulsts - var tests_newlines = "test_prefix_Line 1.\n _Line 2.\n _Line 3." - var tests_uppercase = "a THIS TEXT SHOULD BE UPPPERCASED b" - var tests_lowercase = "a this text should be lowercased b" - var tests_camelcase = "a thisShouldBeCamelCasEd b" - var tests_pascalcase = "a ThisShouldBePascalCasEd b" - var tests_snakecase = "a this_should_be_snake_cas_ed b" - var tests_escapes_newlines = "" - var tests_escapes_uppercase = "" - var tests_escapes_lowercase = "" - var tests_escapes_camelcase = "" - var tests_escapes_pascalcase = "" - var tests_escapes_snakecase = "" - # Actual tests performed using pre() - var tests_newlines_result = process("Line 1Line 2Line 3","test_prefix","_",".") - var tests_uppercase_result = process("a ThIs tExT sHoUlD bE uPpPeRcAsEd b") - var tests_lowercase_result = process("a ThIs tExT sHoUlD bE lOwErCaSeD b") - var tests_camelcase_result = process("a thisShould_be_camel_CASEd b") - var tests_pascalcase_result = process("a thisShould_be_pascal_CASEd b") - var tests_snakecase_result = process("a thisShould_be_snake_CASEd b") - var tests_escapes_newlines_result = process("") - var tests_escapes_uppercase_result = process("") - var tests_escapes_lowercase_result = process("") - var tests_escapes_camelcase_result = process("") - var tests_escapes_pascalcase_result = process("") - var tests_escapes_snakecase_result = process("") - # Test success and log - tests_success = 0 - tests_log = "" - # Checks if all tests are equal to their expected results and logs the result. - if tests_newlines_result == tests_newlines: - tests_success = tests_success+1 - tests_log = "Y Test NEWLINES returned:\n" + tests_newlines_result + "\n" - else: - tests_log = "N Test NEWLINES returned:\n" + tests_newlines_result + "\n... instead of:\n" + tests_newlines + "\n" - if tests_uppercase_result == tests_uppercase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test UPPERCASE returned \"" + tests_uppercase_result + "\".\n" - else: - tests_log = tests_log + "N Test UPPERCASE returned \"" + tests_uppercase_result + "\" instead of \"" + tests_uppercase + "\".\n" - if tests_lowercase_result == tests_lowercase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test LOWERCASE returned \"" + tests_lowercase_result + "\".\n" - else: - tests_log = tests_log + "N Test LOWERCASE returned \"" + tests_lowercase_result + "\" instead of \"" + tests_lowercase + "\".\n" - if tests_camelcase_result == tests_camelcase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test CAMELCASE returned \"" + tests_camelcase_result + "\".\n" - else: - tests_log = tests_log + "N Test CAMELCASE returned \"" + tests_camelcase_result + "\" instead of \"" + tests_camelcase + "\".\n" - if tests_pascalcase_result == tests_pascalcase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test PASCALCASE returned \"" + tests_pascalcase_result + "\".\n" - else: - tests_log = tests_log + "N Test PASCALCASE returned \"" + tests_pascalcase_result + "\" instead of \"" + tests_pascalcase + "\".\n" - if tests_snakecase_result == tests_snakecase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test SNAKECASE returned \"" + tests_snakecase_result + "\".\n" - else: - tests_log = tests_log + "N Test SNAKECASE returned \"" + tests_snakecase_result + "\" instead of \"" + tests_snakecase + "\".\n" - if tests_escapes_newlines_result == tests_escapes_newlines: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test ESCAPES_NEWLINES returned \"" + tests_escapes_newlines_result + "\".\n" - else: - tests_log = tests_log + "N Test ESCAPES_NEWLINES returned \"" + tests_escapes_newlines_result + "\" instead of \"" + tests_escapes_newlines + "\".\n" - if tests_escapes_uppercase_result == tests_escapes_uppercase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test ESCAPES_UPPERCASE returned \"" + tests_escapes_uppercase_result + "\".\n" - else: - tests_log = tests_log + "N Test ESCAPES_UPPERCASE returned \"" + tests_escapes_uppercase_result + "\" instead of \"" + tests_escapes_uppercase + "\".\n" - if tests_escapes_lowercase_result == tests_escapes_lowercase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test ESCAPES_LOWERCASE returned \"" + tests_escapes_lowercase_result + "\".\n" - else: - tests_log = tests_log + "N Test ESCAPES_LOWERCASE returned \"" + tests_escapes_lowercase_result + "\" instead of \"" + tests_escapes_lowercase + "\".\n" - if tests_escapes_camelcase_result == tests_escapes_camelcase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test ESCAPES_CAMELCASE returned \"" + tests_escapes_camelcase_result + "\".\n" - else: - tests_log = tests_log + "N Test ESCAPES_CAMELCASE returned \"" + tests_escapes_camelcase_result + "\" instead of \"" + tests_escapes_camelcase + "\".\n" - if tests_escapes_pascalcase_result == tests_escapes_pascalcase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test ESCAPES_PASCALCASE returned \"" + tests_escapes_pascalcase_result + "\".\n" - else: - tests_log = tests_log + "N Test ESCAPES_PASCALCASE returned \"" + tests_escapes_pascalcase_result + "\" instead of \"" + tests_escapes_pascalcase + "\".\n" - if tests_escapes_snakecase_result == tests_escapes_snakecase: - tests_success = tests_success+1 - tests_log = tests_log + "Y Test ESCAPES_SNAKECASE returned \"" + tests_escapes_snakecase_result + "\".\n" - else: - tests_log = tests_log + "N Test ESCAPES_SNAKECASE returned \"" + tests_escapes_snakecase_result + "\" instead of \"." + tests_escapes_snakecase + "\".\n" - tests_log = tests_log.left(tests_log.length()-1) # Removes unnecessary line. - tests_executed = true - # Checks if all tests were successful. If not disable the Preprocessor and print log. - if tests_success == 12: - enabled = true - logger.diag("Preprocessor","Testing complete: All preprocessor features are working as intended.",false) - if tests_level == 2: - logger.diag("Preprocessor","Log:\n" + tests_log) - else: - enabled = false - logger.error("Preprocessor","Testing failed: Preprocessor is malfunctioning and is now disabled.",false) - if tests_level >= 1: - logger.error("Preprocessor","Log:\n" + tests_log) + logger.diag("CORE/preprocessor.gd","Preprocessor is ready.",false) -# Processes tags +# Parses tags func _newline(msg:String,prefix:String,pre_msg:String,post_msg:String,exclusion_filter:Array) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing newlines") + if core.protection_mode: return "" + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing newline tags",false) var prefix_space = prefix for exclusion in exclusion_filter: prefix_space = prefix_space.replace(exclusion,"") prefix_space = " ".repeat(prefix_space.length()) var msg_proc = prefix + pre_msg + msg.replace("",post_msg + "\n" + prefix_space + pre_msg) + post_msg - if verbose_logging: - logger.diag("Preprocessor","Preprocessed newlines") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsed newline tags. Transformed \"" + msg + "\" into \"" + msg_proc + "\"",false) return msg_proc -# Processes and tags -# Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. +# Parses and tags func _case_lower(msg:String) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing lowercasing") + if core.protection_mode: return "" + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing lowercase tags",false) var msg_proc = msg while true: var index_one = msg_proc.find("") @@ -198,20 +65,18 @@ func _case_lower(msg:String) -> String: var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_lower()) else: - logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\" (stage LOWERCASE).",false) + core.exception("Preprocessor","Failed parsing lowercase tags in message \"" + msg + "\" (missing end tag?)") msg_proc = msg break else: break - if verbose_logging: - logger.diag("Preprocessor","Preprocessed lowercasing") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsed lowercase tags. Transformed \"" + msg + "\" into \"" + msg_proc + "\"",false) return msg_proc -# Processes and tags -# Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. +# Parses and tags func _case_upper(msg:String) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing uppercasing") + if core.protection_mode: return "" + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing uppercase tags",false) var msg_proc = msg while true: var index_one = msg_proc.find("") @@ -222,20 +87,18 @@ func _case_upper(msg:String) -> String: var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_upper()) else: - logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\". (stage UPPERCASE).",false) + core.exception("Preprocessor","Failed parsing uppercase tags in message \"" + msg + "\" (missing end tag?)") msg_proc = msg break else: break - if verbose_logging: - logger.diag("Preprocessor","Preprocessed uppercasing") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsed uppercase tags. Transformed \"" + msg + "\" into \"" + msg_proc + "\"",false) return msg_proc -# Processes and tags -# Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. +# Parses and tags func _case_camelcase(msg:String) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing camelcasing") + if core.protection_mode: return "" + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing camelcase tags",false) var msg_proc = msg while true: var index_one = msg_proc.find("") @@ -246,20 +109,18 @@ func _case_camelcase(msg:String) -> String: var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_camel_case()) else: - logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\". (stage CAMELCASE).",false) + core.exception("Preprocessor","Failed parsing camelcase tags in message \"" + msg + "\" (missing end tag?)") msg_proc = msg break else: break - if verbose_logging: - logger.diag("Preprocessor","Preprocessed camelcasing") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsed camelcase tags. Transformed \"" + msg + "\" into \"" + msg_proc + "\"",false) return msg_proc -# Processes and tags -# Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. +# Parses and tags func _case_pascalcase(msg:String) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing pascalcasing") + if core.protection_mode: return "" + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing pascalcase tags",false) var msg_proc = msg while true: var index_one = msg_proc.find("") @@ -270,20 +131,18 @@ func _case_pascalcase(msg:String) -> String: var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_pascal_case()) else: - logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\". (stage PASCALCASE).",false) + core.exception("Preprocessor","Failed parsing pascalcase tags in message \"" + msg + "\" (missing end tag?)") msg_proc = msg break else: break - if verbose_logging: - logger.diag("Preprocessor","Preprocessed pascalcasing") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsed pascalcase tags. Transformed \"" + msg + "\" into \"" + msg_proc + "\"",false) return msg_proc -# Processes and tags -# Warning: Please do NOT modify the while true loop. It was a pain to debug, believe me. +# Parses and tags func _case_snakecase(msg:String) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing snakecasing") + if core.protection_mode: return "" + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing snakecase tags",false) var msg_proc = msg while true: var index_one = msg_proc.find("") @@ -294,32 +153,30 @@ func _case_snakecase(msg:String) -> String: var index_proc = msg_proc.substr(index_one,index_two) msg_proc = msg_proc.replace(index_proc,index_proc.replace("","").replace("","").to_snake_case()) else: - logger.error("Preprocessor","Failed preprocessing message \"" + msg + "\". (stage SNAKECASE).",false) + core.exception("Preprocessor","Failed parsing snakecase tags in message \"" + msg + "\" (missing end tag?)") msg_proc = msg break else: break - if verbose_logging: - logger.diag("Preprocessor","Preprocessed snakecasing") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsed snakecase tags. Transformed \"" + msg + "\" into \"" + msg_proc + "\"",false) return msg_proc -# Functions to call all other functions related to *case +# Function calls to everything *case-related func _case(msg:String) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing casing") + if core.protection_mode: return "" + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing casing tags",false) var msg_proc = _case_lower(msg) msg_proc = _case_upper(msg_proc) msg_proc = _case_camelcase(msg_proc) msg_proc = _case_pascalcase(msg_proc) msg_proc = _case_snakecase(msg_proc) - if verbose_logging: - logger.diag("Preprocessor","Preprocessed casing") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsed casing tags. Transformed \"" + msg + "\" into \"" + msg_proc + "\"",false) return msg_proc # Replaces all escapes func _escapes(msg:String) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing escapes") + if core.protection_mode: return "" + if diagnostic:logger.diag("CORE/preprocessor.gd","Parsing escape tags",false) var msg_proc = msg.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") @@ -332,33 +189,29 @@ func _escapes(msg:String) -> String: msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") msg_proc = msg_proc.replace("","") - if verbose_logging: - logger.diag("Preprocessor","Preprocessed escapes") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsed escape tags. Transformed \"" + msg + "\" into \"" + msg_proc + "\"",false) return msg_proc -# Checks for and if found returns true, otherwise false +# Checks for tag and if found stops processing func _noprocess(msg:String) -> bool: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing noprocess") + if core.protection_mode: return true + if diagnostic: logger.diag("CORE/preprocessor.gd","Checking for noprocess tag", false) if msg.contains(""): return true return false # Executes all preprocessing functions and returns their combined work func process(msg:String,prefix:String = "",pre_msg:String = "",post_msg:String = "",exclusion_filter:Array = []) -> String: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing a message") + if core.protection_mode: return "" + if diagnostic: logger.diag("CORE/preprocessor.gd","Call to process() recieved",false) if !enabled: - if verbose_logging: - logger.diag("Preprocessor","Preprocessing failed: Preprocessor is disabled") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing failed: Preprocessor is disabled",false) return msg if _noprocess(msg): - if verbose_logging: - logger.diag("Preprocessor","Preprocessing cancelled: tag detected") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing stopped: noprocess tag detected", false) return msg var msg_proc = _case(msg) msg_proc = _newline(msg_proc,prefix,pre_msg,post_msg,exclusion_filter) msg_proc = _escapes(msg_proc) - if verbose_logging: - logger.diag("Preprocessor","Preprocessing complete") + if diagnostic: logger.diag("CORE/preprocessor.gd","Parsing complete", false) return msg_proc diff --git a/resmgr.gd b/resmgr.gd index 82eb54a..ede2057 100644 --- a/resmgr.gd +++ b/resmgr.gd @@ -1,53 +1,94 @@ -# resmgr.gd -# Resource Manager -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### extends Node -@onready -var core = get_node(NodePath("/root/core")) -var resources = {} +# CORE modules +var core: Node = null +var logger: Node = null -func initialize() -> void: - if core.protection_mode: return - core.setready() +# Loaded resources list +var resources: Dictionary = {} -func loadres(resname:String,respath:String,replace:bool = false) -> void: - if core.protection_mode: return - if resources.has(resname): +# Config +var config_load_invalid_file_as_null: bool = false + +# Loads a resource +func loadres(resource_name:String,resource_path:String,replace:bool = false) -> int: + if core.protection_mode: return 9223372036854775807 + logger.diag("CORE/resmgr.gd","Loading resource \"" + resource_name + "\" from path \"" + resource_path + "\" (replace=" + str(replace) + ")") + if resources.has(resource_name): if replace: - resources.erase(resname) + # If resource is already loaded and replace is true, remove it first (and then add it) + resources.erase(resource_name) else: - Logger.error("resmgr","Loading \"" + resname + "\" failed: Resource is loaded already") - return - resources.merge({resname:ResourceLoader.load(respath)}) + # If resource is already loaded and replace is false, throw an error + var err = core.error("ResourceManager",core.Errors.RESOURCEMANAGER_ALREADY_EXISTS,{"name":resource_name}) + logger.error("CORE/resmgr.gd",err["error"]) + return err["code"] + # Check if resource exists + if !FileAccess.file_exists(resource_path): + if config_load_invalid_file_as_null: + resources.merge({resource_name:null}) + var err = core.error("ResourceManager",core.Errors.RESOURCEMANAGER_INVALID_FILEPATH,{"filepath":resource_path}) + logger.error("CORE/resmgr.gd",err["error"]) + return err["code"] + # Load the resource + resources.merge({resource_name:ResourceLoader.load(resource_path)}) + return core.Errors.OK -func unloadres(resname:String) -> void: - if core.protection_mode: return - if !resources.has(resname): - Logger.error("resmgr","Unloading \"" + resname + "\" failed: Resource is not present") - return - resources.erase(resname) +# Unloads a resource +func unloadres(resource_name:String) -> int: + if core.protection_mode: return 9223372036854775807 + if !resources.has(resource_name): + # If resource is not loaded, throw an error + var err = core.error("ResourceManager",core.Errors.RESOURCEMANAGER_RESOURCE_MISSING,{"name":resource_name}) + logger.error("CORE/resmgr.gd",err["error"]) + return err["code"] + # Unload the resource + resources.erase(resource_name) + return core.Errors.OK -func loadbatch(batch:Dictionary,replace:bool = false) -> void: - if core.protection_mode: return +# Loads a batch of resources +func loadbatch(batch:Dictionary,replace:bool = false) -> int: + if core.protection_mode: return 9223372036854775807 if batch == {}: - Logger.error("resmgr","Loading a batch failed: Batch is empty") + # If batch is empty, throw an error + var err = core.error("ResourceManager",core.Errors.RESOURCEMANAGER_BATCH_EMPTY) + logger.error("CORE/resmgr.gd",err["error"]) + return err["code"] for i in batch: + # Call loadres() method for every item in batch loadres(i,batch[i],replace) + return core.Errors.OK -func unloadbatch(batch:Array) -> void: - if core.protection_mode: return +# Unloads a batch of resources +func unloadbatch(batch:Array) -> int: + if core.protection_mode: return 9223372036854775807 if batch == []: - Logger.error("resmgr","Unloading a batch failed: Batch is empty") + # If batch is empty, throw an error + var err = core.error("ResourceManager",core.Errors.RESOURCEMANAGER_BATCH_EMPTY) + logger.error("CORE/resmgr.gd",err["error"]) + return err["code"] for i in batch: + # Call unloadres() method for every item in batch unloadres(i) + return core.Errors.OK -# No set return type here as it can return literally everything. -func getres(resname:String): +# Returns a loaded resource +# No return type is set because it can return literally everything. +func getres(resource_name:String): if core.protection_mode: return null - if !resources.has(resname): + if !resources.has(resource_name): + # Return null if resource is not loaded return null - return resources[resname] + # Return the content + return resources[resource_name] diff --git a/smgr.gd b/smgr.gd index 83170c9..0dba9ad 100644 --- a/smgr.gd +++ b/smgr.gd @@ -1,169 +1,153 @@ -# smgr.gd -# Scene Manager -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### extends Node -@onready -var core = get_node(NodePath("/root/core")) -var ccr = null -var ccr_game = null -var ccr_game_inuse = false -var ccr_menu = null -var ccr_menu_names = [] -var ccr_cutscene = null -var ccr_cutscene_inuse = false -var ccr_debug = null -var ccr_debug_names = [] +# CORE modules +var core: Node = null +var logger: Node = null +var resourcemanager: Node = null +# Overlays +## The debug overlay +var debug_overlay: Node = Node.new() +var debug_overlay_scene: Dictionary = {} +## The cutscene overlay +var cutscene_overlay: Node = Node.new() +var cutscene_overlay_scene: String = "" +## The menu overlay +var menu_overlay: Node = Node.new() +var menu_overlay_scene: Dictionary = {} +## The action overlay +var action_overlay: Node = Node.new() +var action_overlay_scene: String = "" + +# Initializes the scene manager func initialize() -> void: if core.protection_mode: return - Logger.diag("smgr","Constructing CORE Scene Root (CCR)") - ccr = Control.new() - ccr.name = "ccr" - Logger.diag("smgr","Adding CCR to /root/") - get_tree().root.add_child(ccr) - Logger.diag("smgr","Migrating COREBackground to CCR") - var corebg = get_tree().current_scene - Logger.diag("smgr","Reconstructing COREBackground to CCR") - var corebg_log = corebg.get_node(NodePath("Background/Log")).text - corebg.get_node(NodePath("Background/Log")).rmconnect() - get_tree().current_scene.queue_free() - var corebg_new = ResourceLoader.load("res://CORE/background.tscn").instantiate() - ccr.add_child(corebg_new) - corebg_new.get_node(NodePath("Background/Log")).text = corebg_log - Logger.diag("smgr","COREBackground migration complete.") - Logger.diag("smgr","Adding overlays") - add_overlays() - core.setready() + logger.diag("CORE/smgr.gd","Constructing overlays") + # Set overlay names + debug_overlay.name = "DebugOverlay" + cutscene_overlay.name = "CutsceneOverlay" + menu_overlay.name = "MenuOverlay" + action_overlay.name = "ActionOverlay" + logger.diag("CORE/smgr.gd","Adding overlays") + # Adds overlays to /root/ + get_tree().root.add_child(debug_overlay) + get_tree().root.add_child(cutscene_overlay) + get_tree().root.add_child(menu_overlay) + get_tree().root.add_child(action_overlay) -func add_game(resname:String) -> bool: - if core.protection_mode: return false - Logger.diag("smgr","Adding game scene") - if ccr_game_inuse: - Logger.error("smgr","Failed adding game scene: Only one game scene is allowed") - return false - var res = core.resmgr.getres(resname) - if res == null or res.get_class() != "PackedScene": - Logger.error("smgr","Resource is not type of PackedScene") - return false - ccr_game.add_child(res.instantiate()) - ccr_game_inuse = true - Logger.diag("smgr","Added game scene") - return true +# Adds a debug scene +func add_debug(resource_name:String) -> int: + if core.protection_mode: return core.Errors.CORE_PROTECTIONMODE + logger.diag("CORE/smgr.gd","Adding debug scene \"" + resource_name + "\"") + # Load resource into memory + var resource: Object = resourcemanager.getres(resource_name) + if resource == null or resource.get_class() != "PackedScene": + # If resource is null (not loaded) or is not a PackedScene, throw an error + var err = core.error("SceneManager",core.Errors.SCENEMANAGER_NOT_PACKEDSCENE,{"scene":resource_name,"overlay":"debug"}) + logger.error("CORE/smgr.gd",err["error"]) + return err["code"] + if debug_overlay_scene.has(resource_name) and debug_overlay.get_children().has(resource): + # If scene already exists, throw an error + var err = core.error("SceneManager",core.Errors.SCENEMANAGER_ALREADY_LOADED,{"scene":resource_name,"overlay":"debug"}) + logger.error("CORE/smgr.gd",err["error"]) + return err["code"] + # In theory unecessary but if something for some reason did something very wrong it would be catched here + if !debug_overlay_scene.has(resource_name) and debug_overlay.get_children().has(resource): + core.exception("SceneManager","debug_overlay_scene does not contain \"" + resource_name + "\" but debug_overlay does") + return core.Errors.CORE_EXCEPTION + if debug_overlay_scene.has(resource_name) and !debug_overlay.get_children().has(resource): + core.exception("SceneManager","debug_overlay does not contain \"" + resource_name + "\" but debug_overlay_scene does") + return core.Errors.CORE_EXCEPTION + # Add scene to debug overlay + debug_overlay.add_child(resource) + debug_overlay_scene.merge({resource_name:resource},true) + return core.Errors.OK -func remove_game() -> bool: - if core.protection_mode: return false - Logger.diag("smgr","Removing game scene") - if !ccr_game_inuse: - Logger.error("smgr","Failed removing game scene: No game scene is active") - return false - ccr_game.remove_child(ccr_game.get_child(0)) - ccr_game_inuse = false - Logger.diag("smgr","Removed game scene") - return true +# Adds a menu scene +func add_menu(resource_name:String) -> int: + if core.protection_mode: return core.Errors.CORE_PROTECTIONMODE + logger.diag("CORE/smgr.gd","Adding menu scene \"" + resource_name + "\"") + # Load resource into memory + var resource: Object = resourcemanager.getres(resource_name) + if resource == null or resource.get_class() != "PackedScene": + # If resource is null (not loaded) or is not a PackedScene, throw an error + var err = core.error("SceneManager",core.Errors.SCENEMANAGER_NOT_PACKEDSCENE,{"scene":resource_name,"overlay":"menu"}) + logger.error("CORE/smgr.gd",err["error"]) + return err["code"] + if menu_overlay_scene.has(resource_name) and menu_overlay.get_children().has(resource): + # If resource is null (not loaded) or is not a PackedScene, throw an error + var err = core.error("SceneManager",core.Errors.SCENEMANAGER_ALREADY_LOADED,{"scene":resource_name,"overlay":"menu"}) + logger.error("CORE/smgr.gd",err["error"]) + return err["code"] + if !menu_overlay_scene.has(resource_name) and menu_overlay.get_children().has(resource): + core.exception("SceneManager","menu_overlay_scene does not contain \"" + resource_name + "\" but menu_overlay does") + return core.Errors.CORE_EXCEPTION + if menu_overlay_scene.has(resource_name) and !menu_overlay.get_children().has(resource): + core.exception("SceneManager","menu_overlay does not contain \"" + resource_name + "\" but menu_overlay_scene does") + return core.Errors.CORE_EXCEPTION + menu_overlay.add_child(resource) + menu_overlay_scene.merge({resource_name:resource},true) + return core.Errors.OK -func add_menu(resname:String) -> bool: - if core.protection_mode: return false - Logger.diag("smgr","Adding menu scene \"" + resname + "\"") - if ccr_menu_names.has(resname): - Logger.error("smgr","Failed adding menu scene: Menu scene with name \"" + resname + "\" already exists") - return false - var res = core.resmgr.getres(resname) - if res == null or res.get_class() != "PackedScene": - Logger.error("smgr","Resource is not type of PackedScene") - return false - ccr_menu.add_child(res.instantiate()) - ccr_menu_names.append(resname) - Logger.diag("smgr","Added menu scene \"" + resname + "\"") - return true +# Adds a cutscene scene +func add_cutscene(resource_name:String) -> int: + if core.protection_mode: return core.Errors.CORE_PROTECTIONMODE + logger.diag("CORE/smgr.gd","Adding cutscene scene \"" + resource_name + "\"") + # Load resource into memory + var resource: Object = resourcemanager.getres(resource_name) + if resource == null or resource.get_class() != "PackedScene": + # If resource is null (not loaded) or is not a PackedScene, throw an error + var err = core.error("SceneManager",core.Errors.SCENEMANAGER_NOT_PACKEDSCENE,{"scene":resource_name,"overlay":"cutscene"}) + logger.error("CORE/smgr.gd",err["error"]) + return err["code"] + if cutscene_overlay_scene == resource_name and cutscene_overlay.get_children().has(resource): + # If resource is null (not loaded) or is not a PackedScene, throw an error + var err = core.error("SceneManager",core.Errors.SCENEMANAGER_ALREADY_LOADED,{"scene":resource_name,"overlay":"cutscene"}) + logger.error("CORE/smgr.gd",err["error"]) + return err["code"] + if cutscene_overlay_scene != resource_name and cutscene_overlay.get_children().has(resource): + core.exception("SceneManager","cutscene_overlay_scene does not contain \"" + resource_name + "\" but cutscene_overlay does") + return core.Errors.CORE_EXCEPTION + if cutscene_overlay_scene == resource_name and !cutscene_overlay.get_children().has(resource): + core.exception("SceneManager","cutscene_overlay does not contain \"" + resource_name + "\" but cutscene_overlay_scene does") + return core.Errors.CORE_EXCEPTION + cutscene_overlay.add_child(resource) + cutscene_overlay_scene = resource_name + return core.Errors.OK -func remove_menu(scene_name:String) -> bool: - if core.protection_mode: return false - Logger.diag("smgr","Removing menu scene \"" + scene_name + "\"") - if !ccr_menu_names.has(scene_name): - Logger.error("smgr","Failed removing menu scene: Menu scene with name \"" + scene_name + "\" does not exist") - return false - for i in ccr_menu.get_children(): - if i.name == scene_name: - ccr_menu.remove_child(i) - break - ccr_menu_names.erase(scene_name) - Logger.diag("smgr","Removed menu scene \"" + scene_name + "\"") - return true - -func add_cutscene(resname:String) -> bool: - if core.protection_mode: return false - Logger.diag("smgr","Adding cutscene scene") - if ccr_cutscene_inuse: - Logger.error("smgr","Failed adding cutscene scene: Only one cutscene scene is allowed") - return false - var res = core.resmgr.getres(resname) - if res == null or res.get_class() != "PackedScene": - Logger.error("smgr","Resource is not type of PackedScene") - return false - ccr_cutscene.add_child(res.instantiate()) - ccr_cutscene_inuse = true - Logger.diag("smgr","Added cutscene scene") - return true - -func remove_cutscene() -> bool: - if core.protection_mode: return false - Logger.diag("smgr","Removing cutscene scene") - if !ccr_cutscene_inuse: - Logger.error("smgr","Failed removing cutscene scene: No cutscene scene is active") - return false - ccr_cutscene.remove_child(ccr_cutscene.get_child(0)) - ccr_cutscene_inuse = false - Logger.diag("smgr","Removed cutscene scene") - return true - -func add_debug(resname:String) -> bool: - if core.protection_mode: return false - Logger.diag("smgr","Adding debug scene \"" + resname + "\"") - if ccr_debug_names.has(resname): - Logger.error("smgr","Failed adding debug scene: Debug scene with name \"" + resname + "\" already exists") - return false - var res = core.resmgr.getres(resname) - if res == null or res.get_class() != "PackedScene": - Logger.error("smgr","Resource is not type of PackedScene") - return false - ccr_debug.add_child(res.instantiate()) - ccr_debug_names.append(resname) - Logger.diag("smgr","Added debug scene \"" + resname + "\"") - return true - -func remove_debug(scene_name:String) -> bool: - if core.protection_mode: return false - Logger.diag("smgr","Removing debug scene \"" + scene_name + "\"") - if !ccr_menu_names.has(scene_name): - Logger.error("smgr","Failed removing debug scene: Debug scene with name \"" + scene_name + "\" does not exist") - return false - for i in ccr_debug.get_children(): - if i.name == scene_name: - ccr_debug.remove_child(i) - break - ccr_debug_names.erase(scene_name) - Logger.diag("smgr","Removed debug scene \"" + scene_name + "\"") - return true - -func add_overlays() -> void: - if core.protection_mode: return - Logger.diag("smgr","Adding game overlay") - ccr_game = Control.new() - ccr_game.name = "GameOverlay" - ccr.add_child(ccr_game) - Logger.diag("smgr","Adding menu overlay") - ccr_menu = Control.new() - ccr_menu.name = "MenuOverlay" - ccr.add_child(ccr_menu) - Logger.diag("smgr","Adding cutscene overlay") - ccr_cutscene = Control.new() - ccr_cutscene.name = "CutsceneOverlay" - ccr.add_child(ccr_cutscene) - Logger.diag("smgr","Adding debug overlay") - ccr_debug = Control.new() - ccr_debug.name = "DebugOverlay" - ccr.add_child(ccr_debug) +# Adds a action scene +func add_action(resource_name:String) -> int: + if core.protection_mode: return core.Errors.CORE_PROTECTIONMODE + logger.diag("CORE/smgr.gd","Adding action scene \"" + resource_name + "\"") + # Load resource into memory + var resource = resourcemanager.getres(resource_name) + if resource == null or typeof(resource) != TYPE_OBJECT or resource.get_class() != "PackedScene": + # If resource is null (not loaded) or is not a PackedScene, throw an error + var err = core.error("SceneManager",core.Errors.SCENEMANAGER_NOT_PACKEDSCENE,{"scene":resource_name,"overlay":"action"}) + logger.error("CORE/smgr.gd",err["error"]) + return err["code"] + if action_overlay_scene == resource_name and action_overlay.get_children().has(resource): + # If resource is null (not loaded) or is not a PackedScene, throw an error + var err = core.error("SceneManager",core.Errors.SCENEMANAGER_ALREADY_LOADED,{"scene":resource_name,"overlay":"action"}) + logger.error("CORE/smgr.gd",err["error"]) + return err["code"] + if action_overlay_scene != resource_name and action_overlay.get_children().has(resource): + core.exception("SceneManager","action_overlay_scene does not contain \"" + resource_name + "\" but action_overlay does") + return core.Errors.CORE_EXCEPTION + if action_overlay_scene == resource_name and !action_overlay.get_children().has(resource): + core.exception("SceneManager","action_overlay does not contain \"" + resource_name + "\" but action_overlay_scene does") + return core.Errors.CORE_EXCEPTION + action_overlay.add_child(resource) + action_overlay_scene = resource_name + return core.Errors.OK diff --git a/splash.gd b/splash.gd index 3c8d66f..5935270 100644 --- a/splash.gd +++ b/splash.gd @@ -1,48 +1,45 @@ -# splash.gd -# Splash screen -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 +###################################### +# THE CORE FRAMEWORK # +# MADE BY THE STAROPENSOURCE PROJECT # +# AND CONTRIBUTERS (THANK YOU!) # +# # +# COPYRIGHT 2023 THE STAROPENSOURCE # +# PROJECT AND CONTRIBUTERS # +# # +# LICENSED UNDER THE GNU GENERAL # +# PUBLIC LICENSE VERSION 3 (ONLY) # +###################################### extends Node -@onready -var core = get_node("/root/core") +# CORE modules +var core = null +var logger = null +# Config var config_enabled = null var config_image = null var config_image_size = null var config_color = null -func load_configuration() -> void: - if core.protection_mode: return - config_enabled = core.config.splash_enabled - config_image = core.config.splash_image - config_image_size = core.config.splash_image_size - config_color = core.config.splash_color - -func initialize() -> void: - if core.protection_mode: return - apply_config() - if config_enabled: - display() - else: - $Background.visible = false - core.setready() - +# Makes the splash screen pretty func apply_config() -> void: if core.protection_mode: return $Background.color = config_color $Background/Image.texture = ResourceLoader.load(config_image) $Background/Image.size = Vector2i(config_image_size,config_image_size) + if config_enabled: + display() + else: + $Background.visible = false +# The next two functions are very self explanitory func display() -> void: if core.protection_mode: return - Logger.info("splash","Displaying splash screen") - get_tree().root.move_child($"/root/ccr",0) + logger.info("CORE/splash.gd","Displaying splash screen") + get_tree().root.move_child($"/root/CORE/",0) $Background.visible = true func dissolve() -> void: if core.protection_mode: return - Logger.info("splash","Dissolving splash screen") + logger.info("CORE/splash.gd","Dissolving splash screen") $Background.visible = false diff --git a/splash.tscn b/splash.tscn index e9966b5..0228bb2 100644 --- a/splash.tscn +++ b/splash.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" path="res://CORE/splash.gd" id="1_n4sar"] [ext_resource type="Texture2D" path="res://CORE/soscore.png" id="2_5krj5"] -[node name="splash" type="Control"] +[node name="SplashScreen" type="Control"] layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 diff --git a/wmgr.gd b/wmgr.gd deleted file mode 100644 index 267469a..0000000 --- a/wmgr.gd +++ /dev/null @@ -1,108 +0,0 @@ -# wmgr.gd -# Window Manager -# -# This file is part of StarOpenSource CORE (SOSCORE) -# Made by the StarOpenSource Project and Contributers -# Licensed under GNU GPLv3 -extends Node - -@onready -var core = get_node(NodePath("/root/core")) - -var config_window_size_x = null -var config_window_size_y = null -var config_window_title = null -var config_window_mode = null - -var delta = 0 - -func load_configuration() -> void: - if core.protection_mode: return - config_window_size_x = core.config.wmgr_size_x - config_window_size_y = core.config.wmgr_size_y - config_window_title = core.config.wmgr_title - config_window_mode = core.config.wmgr_mode - -func initialize() -> void: - if core.protection_mode: return - Logger.diag("wmgr","Configuring window") - DisplayServer.window_set_size(Vector2i(config_window_size_x,config_window_size_y)) - DisplayServer.window_set_min_size(Vector2i(960,540)) - DisplayServer.window_set_title(config_window_title) - DisplayServer.window_set_mode(config_window_mode) - core.setready() - -func _process(deltap) -> void: - delta = deltap - -func set_size(x:int,y:int) -> void: - if core.protection_mode: return - Logger.diag("wmgr","Applying new window size (" + str(x) + "x" + str(y) + ")") - DisplayServer.window_set_size(Vector2i(x,y)) - -func set_position(x:int,y:int) -> void: - if core.protection_mode: return - Logger.diag("wmgr","Applying new window position (X" + str(x) + " Y" + str(y) + ")") - DisplayServer.window_set_position(Vector2i(x,y)) - -func set_title(title:String) -> void: - if core.protection_mode: return - Logger.diag("wmgr","Applying new window title (" + title + ")") - DisplayServer.window_set_title(title) - config_window_title = title - -func set_mode(mode:String) -> bool: - if core.protection_mode: return false - Logger.diag("wmgr","Applying new window mode (" + mode + ")") - match(mode): - "WINDOWED": DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) - "MINIMIZED": DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MINIMIZED) - "MAXIMIZED": DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MAXIMIZED) - "FULLSCREEN": DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) - "EXCLUSIVE_FULLSCREEN": DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN) - _: - Logger.error("wmgr","Invalid window mode \"" + mode + "\".") - return false - return true - -func get_size() -> Vector2i: - if core.protection_mode: return Vector2i(0,0) - return DisplayServer.window_get_size() - -func get_position() -> Vector2i: - if core.protection_mode: return Vector2i(0,0) - return DisplayServer.window_get_position() - -func get_title() -> String: - if core.protection_mode: return "" - return config_window_title - -func get_mode() -> String: - if core.protection_mode: return "" - match(DisplayServer.window_get_mode()): - 0: return "WINDOWED" - 1: return "MINIMIZED" - 2: return "MAXIMIZED" - 3: return "FULLSCREEN" - 4: return "EXCLUSIVE_FULLSCREEN" - _: - core.exception("wmgr","The window mode id \"" + str(DisplayServer.window_get_mode()) + "\" is not known to wmgr.gd") - return "INVALID_MODE" - -func get_fps(flat:bool = false) -> float: - if core.protection_mode: return 0.0 - if str(delta) == "0": - return INF - else: - if flat: - return float(int(1/delta)) - else: - return 1/delta - -func get_rendertime() -> float: - if core.protection_mode: return 0.0 - return Performance.get_monitor(Performance.TIME_PROCESS) - -func get_delta() -> float: - if core.protection_mode: return 0.0 - return delta