diff --git a/addons/splash_screen_wizard/editor_ui.gd b/addons/splash_screen_wizard/editor_ui.gd index b41bdb0..c9cefe1 100644 --- a/addons/splash_screen_wizard/editor_ui.gd +++ b/addons/splash_screen_wizard/editor_ui.gd @@ -1,6 +1,10 @@ extends EditorInspectorPlugin +const BUTTON_NEW_SLIDE: String = "Add new Slide" +const BUTTON_NEW_BACKGROUND_LOADING: String = "Add new Background Loading" + + var icon_add_slide = load("res://addons/splash_screen_wizard/icons/IconAddSlide.svg") @@ -14,22 +18,32 @@ func _can_handle(object): func _parse_category(object, category): if category == "splash_screen.gd": _create_button_new_slide(object) + _create_button_new_background_loading(object) func _create_button_new_slide(object): var button_add_slide = Button.new() - button_add_slide.text = "Add new Slide" + button_add_slide.text = BUTTON_NEW_SLIDE button_add_slide.icon = icon_add_slide + button_add_slide.expand_icon = true button_add_slide.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER button_add_slide.vertical_icon_alignment = VERTICAL_ALIGNMENT_TOP - button_add_slide.expand_icon = true button_add_slide.connect("pressed", _on_button_add_slide_pressed.bind(object)) add_custom_control(button_add_slide) +func _create_button_new_background_loading(object): + var button_background_loading = Button.new() + button_background_loading.text = BUTTON_NEW_BACKGROUND_LOADING + + button_background_loading.connect("pressed", _on_button_add_background_loading_pressed.bind(object)) + + add_custom_control(button_background_loading) + + func _on_button_add_slide_pressed(object: SplashScreen): var new_slide = SplashScreenSlide.new() new_slide.name = "NewSlide" @@ -37,3 +51,11 @@ func _on_button_add_slide_pressed(object: SplashScreen): object.add_child(new_slide) new_slide.set_owner(object.get_tree().edited_scene_root) + + +func _on_button_add_background_loading_pressed(object: SplashScreen): + var new_background_loading = SplashScreenBackgroundLoading.new() + new_background_loading.name = "NewBackgroundLoading" + + object.add_child(new_background_loading) + new_background_loading.set_owner(object.get_tree().edited_scene_root) diff --git a/addons/splash_screen_wizard/splash_screen.gd b/addons/splash_screen_wizard/splash_screen.gd index e7e0ba6..a6d7509 100644 --- a/addons/splash_screen_wizard/splash_screen.gd +++ b/addons/splash_screen_wizard/splash_screen.gd @@ -30,11 +30,14 @@ signal finished ## A list of all slides in the splash screen. This is automatically updated when the splash screen is started. var slides: Array[SplashScreenSlide] = [] +## A list of all background loading nodes in the splash screen. This is automatically updated when the splash screen is started. +var queued_background_loading: Array[SplashScreenBackgroundLoading] = [] ## The current slide that is being displayed. var current_slide: SplashScreenSlide var _delay_timer: Timer +var _finished_background_loading: Array[PackedScene] = [] func _ready() -> void: @@ -59,11 +62,19 @@ func _input(event): ## Starts the splash screen. This will update the slides, start them and clean up afterwards. Called automatically if [member auto_start] is `true`. func start() -> void: _configure_timer() - _update_slides() + _update_children() + await _start_slides() + _cleanup() + + _complete_background_loading() + finished.emit() + if delete_after_finished: + queue_free() + func _configure_timer() -> void: _delay_timer = Timer.new() @@ -71,12 +82,14 @@ func _configure_timer() -> void: add_child(_delay_timer) -func _update_slides() -> void: +func _update_children() -> void: slides.clear() for child in get_children(): if child is SplashScreenSlide: slides.append(child) + elif child is SplashScreenBackgroundLoading: + queued_background_loading.append(child) if slides.size() == 0: push_warning("SplashScreen: No slides found. Add some SplashScreenSlide nodes as children to display them in a sequence.") @@ -97,10 +110,29 @@ func _start_slides() -> void: slide_finished.emit(current_slide) +func _complete_background_loading() -> void: + if queued_background_loading.size() == 0: + return + + var all_loading_finished: bool = false + while not all_loading_finished: + all_loading_finished = true + + for loading: SplashScreenBackgroundLoading in queued_background_loading: + match loading.thread_status: + ResourceLoader.ThreadLoadStatus.THREAD_LOAD_IN_PROGRESS: + all_loading_finished = false + ResourceLoader.ThreadLoadStatus.THREAD_LOAD_LOADED: + _finished_background_loading.append(loading.thread_result) + _: + pass + + for loaded_scene: PackedScene in _finished_background_loading: + var scene_instance: Node = loaded_scene.instantiate() + get_parent().add_child(scene_instance) + func _cleanup() -> void: _delay_timer.queue_free() - if delete_after_finished: - queue_free() func _skip_slide() -> void: diff --git a/addons/splash_screen_wizard/splash_screen_background_loading.gd b/addons/splash_screen_wizard/splash_screen_background_loading.gd new file mode 100644 index 0000000..51dc299 --- /dev/null +++ b/addons/splash_screen_wizard/splash_screen_background_loading.gd @@ -0,0 +1,66 @@ +# TODO: Add custom icon +class_name SplashScreenBackgroundLoading extends Node +## TODO: Add a description of the class here. +## +## TODO: Add a explanation of the class here. +## +## @tutorial: TODO: Link relevant README header here. + +## When enabled, the node will start loading the resource on _ready. When disabled, [method start_loading] must be called manually. +@export var autostart: bool = true +## The file path to the scene file (.tscn) the ResourceLoader will load. +@export_file("*.tscn") var file_path: String + + +## The status of the thread loading the resource. +var thread_status: ResourceLoader.ThreadLoadStatus +## The progress of the thread loading the resource from 0 to 1. +var thread_progress: Array = [] +## The final loaded resource from the thread. +var thread_result: PackedScene = null + + +func _ready() -> void: + if not autostart: + set_process(false) + return + + start_loading() + + + +func _process(_delta) -> void: + _process_thread() + + +func _process_thread() -> void: + thread_status = ResourceLoader.load_threaded_get_status(file_path, thread_progress) + + match thread_status: + ResourceLoader.ThreadLoadStatus.THREAD_LOAD_FAILED : + push_error(self.name + ": Failed to load resource from " + file_path) + set_process(false) + ResourceLoader.ThreadLoadStatus.THREAD_LOAD_INVALID_RESOURCE: + push_error(self.name + ": Invalid resource from " + file_path) + set_process(false) + ResourceLoader.ThreadLoadStatus.THREAD_LOAD_LOADED: + thread_result = ResourceLoader.load_threaded_get(file_path) + set_process(false) + _: + pass + + +## Start loading the resource from the file path. Needs to be called manually if [member autostart] is disabled. +func start_loading() -> void: + if file_path == "": + push_error(self.name + ": file_path is empty") + set_process(false) + return + + if not file_path.ends_with(".tscn"): + push_error(self.name + ": file_path is not a .tscn file") + set_process(false) + return + + ResourceLoader.load_threaded_request(file_path) + set_process(true) diff --git a/demo_splash_screen_wizard/assets/big_background.jpg b/demo_splash_screen_wizard/assets/big_background.jpg new file mode 100644 index 0000000..32717b0 Binary files /dev/null and b/demo_splash_screen_wizard/assets/big_background.jpg differ diff --git a/demo_splash_screen_wizard/assets/big_background.jpg.import b/demo_splash_screen_wizard/assets/big_background.jpg.import new file mode 100644 index 0000000..392bdd0 --- /dev/null +++ b/demo_splash_screen_wizard/assets/big_background.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cohc3p1n6pudt" +path="res://.godot/imported/big_background.jpg-440dc4697a15f69f9d64f774d16d6f40.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://demo_splash_screen_wizard/assets/big_background.jpg" +dest_files=["res://.godot/imported/big_background.jpg-440dc4697a15f69f9d64f774d16d6f40.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/demo_splash_screen_wizard/demo_menu.tscn b/demo_splash_screen_wizard/demo_menu.tscn new file mode 100644 index 0000000..c249167 --- /dev/null +++ b/demo_splash_screen_wizard/demo_menu.tscn @@ -0,0 +1,55 @@ +[gd_scene load_steps=3 format=3 uid="uid://ccfrkrre3q4px"] + +[ext_resource type="Texture2D" uid="uid://cohc3p1n6pudt" path="res://demo_splash_screen_wizard/assets/big_background.jpg" id="1_fhipf"] + +[sub_resource type="LabelSettings" id="LabelSettings_tq001"] +font_size = 56 + +[node name="DemoMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="HighResTexture" type="TextureRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("1_fhipf") +expand_mode = 5 + +[node name="CenterContainer" type="CenterContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="CenterContainer/VBoxContainer"] +custom_minimum_size = Vector2(1000, 0) +layout_mode = 2 +text = "This image is way to big!" +label_settings = SubResource("LabelSettings_tq001") +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="Button" type="Button" parent="CenterContainer/VBoxContainer"] +layout_mode = 2 +text = "New Game" + +[node name="Button2" type="Button" parent="CenterContainer/VBoxContainer"] +layout_mode = 2 +text = "Old Game" + +[node name="Button3" type="Button" parent="CenterContainer/VBoxContainer"] +layout_mode = 2 +text = "This button doesn't work" diff --git a/demo_splash_screen_wizard/demo_splash_screen_wizard.tscn b/demo_splash_screen_wizard/demo_splash_screen_wizard.tscn index 334785c..012933e 100644 --- a/demo_splash_screen_wizard/demo_splash_screen_wizard.tscn +++ b/demo_splash_screen_wizard/demo_splash_screen_wizard.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=5 format=3 uid="uid://bo22hma5o31ig"] +[gd_scene load_steps=6 format=3 uid="uid://bo22hma5o31ig"] [ext_resource type="Script" path="res://addons/splash_screen_wizard/splash_screen.gd" id="1_myy6d"] [ext_resource type="PackedScene" uid="uid://ckqiyl367tw67" path="res://demo_splash_screen_wizard/slides/slide_disclaimer.tscn" id="2_flgjm"] [ext_resource type="PackedScene" uid="uid://cxqpgg8ax8bqv" path="res://demo_splash_screen_wizard/slides/slide_godot.tscn" id="3_phgod"] +[ext_resource type="Script" path="res://addons/splash_screen_wizard/splash_screen_background_loading.gd" id="4_dpwq0"] [sub_resource type="LabelSettings" id="LabelSettings_8xhda"] font_size = 56 @@ -75,9 +76,15 @@ grow_vertical = 2 color = Color(0, 0, 0, 1) [node name="SlideDisclaimer" parent="SplashScreen" instance=ExtResource("2_flgjm")] +visible = false layout_mode = 1 duration = 3.0 +skippable = true [node name="SlideGodot" parent="SplashScreen" instance=ExtResource("3_phgod")] layout_mode = 1 skippable = true + +[node name="SplashScreenBackgroundLoading" type="Node" parent="SplashScreen"] +script = ExtResource("4_dpwq0") +file_path = "res://demo_splash_screen_wizard/demo_menu.tscn"