class_name StudioStartScreen extends Control ## Studio Start Screen offering starter templates and recent projects browser. signal template_selected(template_name: String) signal project_opened(path: String) const MBWorldProjectIOClass = preload("res://scripts/studio/mbworld_project_io.gd") var _recent_list: ItemList var _templates_container: HBoxContainer var _btn_open_file: Button var _file_dialog: FileDialog func _ready() -> void: _build_ui() _populate_recent_projects() func _build_ui() -> void: set_anchors_preset(Control.PRESET_FULL_RECT) var bg := ColorRect.new() bg.set_anchors_preset(Control.PRESET_FULL_RECT) bg.color = Color(0.12, 0.13, 0.16) add_child(bg) var margin := MarginContainer.new() margin.set_anchors_preset(Control.PRESET_FULL_RECT) margin.add_theme_constant_override("margin_left", 60) margin.add_theme_constant_override("margin_top", 40) margin.add_theme_constant_override("margin_right", 60) margin.add_theme_constant_override("margin_bottom", 40) add_child(margin) var root_vbox := VBoxContainer.new() root_vbox.add_theme_constant_override("separation", 24) margin.add_child(root_vbox) # Header var title_row := HBoxContainer.new() var title := Label.new() title.text = "🦬 ModBison Studio" title.add_theme_font_size_override("font_size", 28) title.add_theme_color_override("font_color", Color(1.0, 0.9, 0.3)) title_row.add_child(title) var spacer := Control.new() spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL title_row.add_child(spacer) _btn_open_file = Button.new() _btn_open_file.text = "📂 Open from Disk..." _btn_open_file.pressed.connect(_on_open_file_pressed) title_row.add_child(_btn_open_file) root_vbox.add_child(title_row) # Starter Templates Section var tmpl_lbl := Label.new() tmpl_lbl.text = "Starter Templates" tmpl_lbl.add_theme_font_size_override("font_size", 16) tmpl_lbl.add_theme_color_override("font_color", Color(0.3, 0.85, 1.0)) root_vbox.add_child(tmpl_lbl) _templates_container = HBoxContainer.new() _templates_container.add_theme_constant_override("separation", 16) root_vbox.add_child(_templates_container) _create_template_card("Baseplate", "Clean empty 32x32 world grid ready for custom building.", "baseplate") _create_template_card("Rolling Hills", "Natural outdoor terrain with pine trees and fauna.", "terrain") _create_template_card("Obby Parkour", "Action platformer obstacle course with moving elevators.", "obby") # Recent Projects Section var rec_lbl := Label.new() rec_lbl.text = "Recent Worlds" rec_lbl.add_theme_font_size_override("font_size", 16) rec_lbl.add_theme_color_override("font_color", Color(0.4, 0.9, 0.5)) root_vbox.add_child(rec_lbl) _recent_list = ItemList.new() _recent_list.size_flags_vertical = Control.SIZE_EXPAND_FILL _recent_list.custom_minimum_size = Vector2(0, 160) _recent_list.item_activated.connect(_on_recent_item_activated) root_vbox.add_child(_recent_list) # File Dialog _file_dialog = FileDialog.new() _file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE _file_dialog.access = FileDialog.ACCESS_FILESYSTEM _file_dialog.filters = PackedStringArray(["*.mbworld ; ModBison World Files"]) _file_dialog.file_selected.connect(_on_file_dialog_selected) add_child(_file_dialog) func _create_template_card(title: String, desc: String, template_id: String) -> void: var panel := PanelContainer.new() panel.custom_minimum_size = Vector2(220, 120) panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL var vbox := VBoxContainer.new() vbox.add_theme_constant_override("separation", 8) panel.add_child(vbox) var t_lbl := Label.new() t_lbl.text = title t_lbl.add_theme_font_size_override("font_size", 14) t_lbl.add_theme_color_override("font_color", Color(1.0, 0.95, 0.4)) vbox.add_child(t_lbl) var d_lbl := Label.new() d_lbl.text = desc d_lbl.add_theme_font_size_override("font_size", 10) d_lbl.add_theme_color_override("font_color", Color(0.7, 0.7, 0.7)) d_lbl.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART d_lbl.size_flags_vertical = Control.SIZE_EXPAND_FILL vbox.add_child(d_lbl) var btn := Button.new() btn.text = "Create World" btn.pressed.connect(func(): template_selected.emit(template_id)) vbox.add_child(btn) _templates_container.add_child(panel) func _populate_recent_projects() -> void: _recent_list.clear() var recents: Array = MBWorldProjectIOClass.get_recent_projects() if recents.is_empty(): _recent_list.add_item("(No recent projects)") _recent_list.set_item_disabled(0, true) else: for path in recents: var fname = str(path).get_file() _recent_list.add_item("📄 %s (%s)" % [fname, path]) func _on_recent_item_activated(index: int) -> void: var recents: Array = MBWorldProjectIOClass.get_recent_projects() if index >= 0 and index < recents.size(): var path: String = str(recents[index]) project_opened.emit(path) func _on_open_file_pressed() -> void: _file_dialog.popup_centered(Vector2i(700, 450)) func _on_file_dialog_selected(path: String) -> void: project_opened.emit(path)