feat(studio,stacking,animations,collections): M16 ModBison Studio, object stacking, model animations, and poly collections for MVP 2
checkpoint / checkpoint (push) Successful in 6m32s

This commit is contained in:
2026-09-22 18:30:57 +00:00
parent 654c1ec6bf
commit 721dbe5ae7
37 changed files with 5202 additions and 17 deletions
+152
View File
@@ -0,0 +1,152 @@
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)