First commit 🎉

This commit is contained in:
Tony Bark 2025-07-17 01:49:18 -04:00
commit 43ea213f9b
728 changed files with 37080 additions and 0 deletions

View file

@ -0,0 +1,91 @@
@tool
extends AcceptDialog
const POPOCHIU_POPUP_SCENE :=\
"res://addons/popochiu/engine/objects/gui/components/popups/popochiu_popup.tscn"
const POPOCHIU_POPUP_SCRIPT :=\
"res://addons/popochiu/engine/templates/gui/popup_template.gd"
const POPUPS_FOLDER := "res://game/gui/popups/%s/"
var _popup_id := ""
var _scene_path := POPUPS_FOLDER + "%s.tscn"
var _script_path := POPUPS_FOLDER + "%s.gd"
@onready var title_edit: LineEdit = %TitleEdit
@onready var info: RichTextLabel = %Info
@onready var dflt_info := info.text
#region Godot ######################################################################################
func _ready() -> void:
# Connect to own signals
about_to_popup.connect(_on_about_to_popup)
# Connect to children's signals
title_edit.text_changed.connect(_on_title_changed)
get_ok_button().pressed.connect(_create_popup)
info.hide()
hide()
#endregion
#region Private ####################################################################################
func _on_about_to_popup() -> void:
title_edit.clear()
info.text = dflt_info
info.hide()
func _on_title_changed(new_text: String) -> void:
if new_text.is_empty():
info.hide()
return
_popup_id = new_text.to_snake_case()
info.text = dflt_info.replace("%s", _popup_id)
info.show()
func _create_popup() -> void:
# Create the popups directory inside the graphic interface directory ---------------------------
DirAccess.make_dir_recursive_absolute(POPUPS_FOLDER % _popup_id)
var scene_path := _scene_path.replace("%s", _popup_id)
var script_path := _script_path.replace("%s", _popup_id)
var pascal_name := _popup_id.to_pascal_case()
# Create the popup script ----------------------------------------------------------------------
DirAccess.copy_absolute(POPOCHIU_POPUP_SCRIPT, script_path)
# Create the PopochiuPopup scene ---------------------------------------------------------------
var popup_instance: PopochiuPopup = load(POPOCHIU_POPUP_SCENE).instantiate()
popup_instance.set_script(load(script_path))
popup_instance.name = pascal_name + "Popup"
popup_instance.script_name = pascal_name
popup_instance.title = pascal_name.capitalize()
var popup_scene: PackedScene = PackedScene.new()
popup_scene.pack(popup_instance)
if ResourceSaver.save(popup_scene, scene_path) != OK:
PopochiuUtils.print_error("Couldn't create popup: %s" % _popup_id)
# TODO: Show feedback in the popup
return
# Add the popup to the Popups node in the graphic interface scene ------------------------------
var popup_node: PopochiuPopup = load(scene_path).instantiate()
var gui_node := EditorInterface.get_edited_scene_root()
gui_node.get_node("Popups").add_child(popup_node)
popup_node.owner = gui_node
EditorInterface.save_scene()
# Open the scene of the created popup for edition ----------------------------------------------
await PopochiuEditorHelper.filesystem_scanned()
EditorInterface.select_file(scene_path)
EditorInterface.open_scene_from_path(scene_path)
#endregion

View file

@ -0,0 +1 @@
uid://b6dn0qq3c0iep

View file

@ -0,0 +1,48 @@
[gd_scene load_steps=2 format=3 uid="uid://bu77q250wow5g"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/tab_gui/create_popup_window/create_popup_window.gd" id="1_4ujlk"]
[node name="CreatePopupWindow" type="AcceptDialog"]
title = "Create Popup"
size = Vector2i(640, 256)
popup_window = true
max_size = Vector2i(1280, 720)
ok_button_text = "Create"
script = ExtResource("1_4ujlk")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
offset_left = 8.0
offset_top = 8.0
offset_right = 632.0
offset_bottom = 207.0
[node name="Label" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "Give a title to your popup."
[node name="TitleEdit" type="LineEdit" parent="VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
expand_to_text_length = true
context_menu_enabled = false
clear_button_enabled = true
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer"]
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/PanelContainer"]
layout_mode = 2
theme_override_constants/margin_left = 4
theme_override_constants/margin_top = 4
theme_override_constants/margin_right = 4
theme_override_constants/margin_bottom = 4
[node name="Info" type="RichTextLabel" parent="VBoxContainer/PanelContainer/MarginContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
bbcode_enabled = true
text = "This will create the following files:
[code]res://popochiu/graphic_interface/popups/%s/%s.tscn
res://popochiu/graphic_interface/popups/%s/%s.gd[/code]"
fit_content = true

View file

@ -0,0 +1,234 @@
@tool
extends VBoxContainer
const COMPONENTS_PATH := "res://addons/popochiu/engine/objects/gui/components/"
var _opened_scene: Control = null
var _components_basedir := []
var _script_path := PopochiuResources.GUI_GAME_SCENE.replace(".tscn", ".gd")
var _commands_path := PopochiuResources.GUI_GAME_SCENE.replace(
"gui.tscn", "gui_commands.gd"
)
var _gui_templates_helper := preload(
"res://addons/popochiu/editor/helpers/popochiu_gui_templates_helper.gd"
)
@onready var template_name: Label = %TemplateName
@onready var btn_script: Button = %BtnScript
@onready var btn_commands: Button = %BtnCommands
#region Godot ######################################################################################
func _ready() -> void:
btn_script.icon = get_theme_icon("Script", "EditorIcons")
btn_commands.icon = get_theme_icon("Script", "EditorIcons")
# Connect to child signals
btn_script.pressed.connect(_on_script_pressed)
btn_commands.pressed.connect(_on_commands_pressed)
%PopupsGroup.create_clicked.connect(_on_create_popup_clicked)
#endregion
#region Public #####################################################################################
## Called when the selected scene in the Editor 2D changes.
## This checks if that scene is a PopochiuGraphicInterface to list its components
## and create the corresponding buttons to add/remove such components.
func on_scene_changed(gui_node: Node) -> void:
if gui_node is PopochiuGraphicInterface:
_opened_scene = gui_node
# FIXME: This override the tab change done by tab_room.gd
get_parent().current_tab = get_index()
_clear_elements()
await get_tree().process_frame
_read_dir(COMPONENTS_PATH)
_create_buttons()
_find_components(gui_node)
_update_groups_titles()
template_name.text = "Template: %s" % (
PopochiuResources.get_data_value("ui", "template", "---") as String
).capitalize()
_opened_scene.child_exiting_tree.connect(_on_child_removed)
var popups := _opened_scene.get_node_or_null("Popups")
if popups:
popups.child_exiting_tree.connect(_on_child_removed)
else:
if is_instance_valid(_opened_scene):
_opened_scene.child_exiting_tree.disconnect(_on_child_removed)
var popups := _opened_scene.get_node_or_null("Popups")
if popups:
popups.child_exiting_tree.disconnect(_on_child_removed)
_opened_scene = null
## Opens the graphic interface scene of the game.
func open_gui_scene() -> void:
if is_instance_valid(_opened_scene) and _opened_scene is PopochiuGraphicInterface:
return
var path := PopochiuResources.GUI_GAME_SCENE
EditorInterface.select_file(path)
EditorInterface.set_main_screen_editor("2D")
EditorInterface.open_scene_from_path(path)
#endregion
#region Private ####################################################################################
func _on_script_pressed() -> void:
EditorInterface.select_file(_script_path)
EditorInterface.set_main_screen_editor("Script")
EditorInterface.edit_script(load(_script_path))
func _on_commands_pressed() -> void:
EditorInterface.select_file(_commands_path)
EditorInterface.set_main_screen_editor("Script")
EditorInterface.edit_script(load(_commands_path))
func _on_create_popup_clicked() -> void:
$CreatePopupWindow.popup_centered()
func _clear_elements() -> void:
_components_basedir.clear()
for container in [%BaseComponentsGroup, %PopupsGroup]:
container.clear_list()
## Reads a directory in the project (addons folder) looking for Popochiu GUI
## components and popups.
func _read_dir(path: String) -> void:
var dir = DirAccess.open(path)
if not dir:
return
dir.list_dir_begin()
var element_name = dir.get_next()
while element_name != "":
if dir.current_is_dir():
if element_name == "popups":
_read_dir(COMPONENTS_PATH + element_name + "/")
else:
_components_basedir.append(path + element_name)
element_name = dir.get_next()
## Create the buttons in the tab for GUI components and popups.
func _create_buttons() -> void:
for component_path in _components_basedir:
var btn := Button.new()
var component_name: String = component_path.split("/")[-1]
btn.name = component_name
btn.text = component_name.capitalize()
btn.set_meta("path", component_path)
btn.pressed.connect(_add_component.bind(btn))
if "popups" in component_path:
%PopupsGroup.add(btn)
else:
%BaseComponentsGroup.add(btn)
set_meta(component_name, btn)
## Looks for GUI components and popups in the children of `node`.
func _find_components(node: Control) -> void:
var components := (
node.get_tree().get_nodes_in_group("popochiu_gui_component") +
node.get_tree().get_nodes_in_group("popochiu_gui_popup")
)
for child: Node in components:
var component_name := child.scene_file_path.get_base_dir().split("/")[-1]
if has_meta(component_name):
(get_meta(component_name) as Button).disabled = true
## Updates the title of the base components and popups PopochiuGroups so they
## show a number representing the amount of elements in the scene.
func _update_groups_titles() -> void:
var disabled_count := 0
for btn in %BaseComponentsGroup.get_elements():
if btn.disabled:
disabled_count += 1
%BaseComponentsGroup.set_title_count(disabled_count, %BaseComponentsGroup.get_elements().size())
disabled_count = 0
for btn in %PopupsGroup.get_elements():
if btn.disabled:
disabled_count += 1
%PopupsGroup.set_title_count(disabled_count, %PopupsGroup.get_elements().size())
## Create a copy of the selected component (scenes, resources, scripts) in the
## game graphic interface folder and adds it to the Graphic Interface scene.
func _add_component(btn: Button) -> void:
btn.disabled = true
var is_popup: bool = "popups" in btn.get_meta("path")
var scene_path := "%s/%s.tscn" % [
btn.get_meta("path"),
btn.name + "_popup" if is_popup else btn.name
]
var target_scene_path := await _gui_templates_helper.copy_component(scene_path)
if target_scene_path.is_empty():
return
var instance: Control = (
load(target_scene_path) as PackedScene
).instantiate(PackedScene.GEN_EDIT_STATE_INSTANCE)
if is_popup:
if not _opened_scene.get_node_or_null("Popups"):
var popups_group := Control.new()
_opened_scene.add_child(popups_group)
popups_group.name = "Popups"
popups_group.owner = _opened_scene
popups_group.layout_mode = 1
popups_group.anchors_preset = PRESET_FULL_RECT
popups_group.mouse_filter = Control.MOUSE_FILTER_IGNORE
_opened_scene.get_node("Popups").add_child(instance)
else:
_opened_scene.add_child(instance)
instance.owner = _opened_scene
var result: int = EditorInterface.save_scene()
if result == OK:
PopochiuEditorHelper.select_node(instance)
else:
btn.disabled = false
func _on_child_removed(node: CanvasItem) -> void:
if not node is Control: return
var basedir := node.scene_file_path.get_base_dir()
if basedir in _components_basedir:
(get_meta(basedir.split("/")[-1]) as Button).disabled = false
#endregion

View file

@ -0,0 +1 @@
uid://clpbfehnalnts

View file

@ -0,0 +1,97 @@
[gd_scene load_steps=8 format=3 uid="uid://4etgd0rwjgct"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/tab_gui/tab_gui.gd" id="1_xmvtx"]
[ext_resource type="PackedScene" uid="uid://b55ialbvpilxv" path="res://addons/popochiu/editor/main_dock/popochiu_group/popochiu_group.tscn" id="2_uc7il"]
[ext_resource type="PackedScene" uid="uid://bu77q250wow5g" path="res://addons/popochiu/editor/main_dock/tab_gui/create_popup_window/create_popup_window.tscn" id="3_3a7ix"]
[sub_resource type="Image" id="Image_j7yy0"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id="ImageTexture_ddg1g"]
image = SubResource("Image_j7yy0")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_73bc0"]
content_margin_left = 8.0
content_margin_right = 8.0
draw_center = false
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.6, 0.6, 0.6, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_674al"]
content_margin_left = 8.0
content_margin_right = 8.0
draw_center = false
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.6, 0.6, 0.6, 1)
[node name="UI" type="VBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_xmvtx")
[node name="Header" type="VBoxContainer" parent="."]
layout_mode = 2
alignment = 1
[node name="TemplateName" type="Label" parent="Header"]
unique_name_in_owner = true
layout_mode = 2
text = "Template: Custom"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="Header"]
layout_mode = 2
size_flags_horizontal = 4
[node name="BtnScript" type="Button" parent="Header/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Script"
icon = SubResource("ImageTexture_ddg1g")
[node name="BtnCommands" type="Button" parent="Header/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Commands"
icon = SubResource("ImageTexture_ddg1g")
[node name="ScrollContainer" type="ScrollContainer" parent="."]
layout_mode = 2
size_flags_vertical = 3
[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="BaseComponentsGroup" parent="ScrollContainer/VBoxContainer" instance=ExtResource("2_uc7il")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_73bc0")
title = "Base components"
can_create = false
custom_title_count = true
[node name="PopupsGroup" parent="ScrollContainer/VBoxContainer" instance=ExtResource("2_uc7il")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_674al")
title = "Popups"
create_text = "Create popup"
custom_title_count = true
[node name="CreatePopupWindow" parent="." instance=ExtResource("3_3a7ix")]