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,117 @@
@tool
extends Panel
signal move_folders_pressed
@onready var tab_container: TabContainer = %TabContainer
@onready var tab_main: VBoxContainer = %Main
@onready var tab_room: VBoxContainer = %Room
@onready var tab_audio: VBoxContainer = %Audio
@onready var tab_gui: VBoxContainer = %GUI
# ---- FOOTER --------------------------------------------------------------------------------------
@onready var version: Label = %Version
@onready var btn_setup: Button = %BtnSetup
@onready var btn_docs: Button = %BtnDocs
#region Godot ######################################################################################
func _ready() -> void:
version.text = "v" + PopochiuResources.get_version()
btn_setup.icon = get_theme_icon("Edit", "EditorIcons")
btn_docs.icon = get_theme_icon("HelpSearch", "EditorIcons")
# Set the Main tab selected by default
tab_container.current_tab = 0
# Hide the GUI tab while we decide how it will work based on devs feedback
tab_container.set_tab_hidden(tab_gui.get_index(), true)
# Connect to children's signals
tab_container.tab_changed.connect(_on_tab_changed)
btn_setup.pressed.connect(open_setup)
btn_docs.pressed.connect(OS.shell_open.bind(PopochiuResources.DOCUMENTATION))
# Connect to parent signals
get_tree().node_added.connect(_check_node)
#endregion
#region Public #####################################################################################
func fill_data() -> void:
tab_main.fill_data()
tab_audio.fill_data()
func scene_changed(scene_root: Node) -> void:
if not is_instance_valid(tab_room): return
tab_room.scene_changed(scene_root)
# TODO: Uncomment these lines when working on the GUI tab again
#if not is_instance_valid(tab_gui): return
#tab_gui.on_scene_changed(scene_root)
if (
not scene_root
or (
not scene_root is PopochiuRoom
# TODO: Uncomment this line when working on the GUI tab again
#and not scene_root.scene_file_path == PopochiuResources.GUI_GAME_SCENE
)
):
# Open the Popochiu Main tab if the opened scene in the Editor2D is not a PopochiuRoom nor
# the GUI scene
tab_container.current_tab = 0
func scene_closed(filepath: String) -> void:
if not is_instance_valid(tab_room): return
tab_room.scene_closed(filepath)
check_open_scenes()
func search_audio_files() -> void:
if not is_instance_valid(tab_audio): return
tab_audio.search_audio_files()
func open_setup() -> void:
PopochiuEditorHelper.show_setup()
## If there are no other opened scenes in the Editor, this function connects to
## [signal EditorSelection.selection_changed] in order to make sure the Popochiu dock behaves as
## expected when the [signal EditorPlugin.scene_changed] signal is not emitted.
func check_open_scenes() -> void:
# Fixes #273: Since Godot is not triggering the EditorPlugin.scene_changed signal when opening a
# scene when no other scenes are opened, listen to the EditorSelection.selection_changed signal
await get_tree().process_frame
if EditorInterface.get_open_scenes().is_empty():
EditorInterface.get_selection().selection_changed.connect(_on_editor_selection_changed)
#endregion
#region Private ####################################################################################
func _on_tab_changed(tab: int) -> void:
if tab == tab_main.get_index():
tab_main.check_data()
if tab == tab_gui.get_index():
tab_gui.open_gui_scene()
func _check_node(node: Node) -> void:
if node is PopochiuCharacter and node.get_parent() is Node2D:
# The node is a PopochiuCharacter in a room
node.set_name.call_deferred("Character%s *" % node.script_name)
func _on_editor_selection_changed() -> void:
if EditorInterface.get_edited_scene_root():
EditorInterface.get_selection().selection_changed.disconnect(_on_editor_selection_changed)
scene_changed(EditorInterface.get_edited_scene_root())
#endregion

View file

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

View file

@ -0,0 +1,100 @@
[gd_scene load_steps=8 format=3 uid="uid://bardo4kb80rvg"]
[ext_resource type="PackedScene" uid="uid://bynwdds8o3tcx" path="res://addons/popochiu/editor/main_dock/tab_main/tab_main.tscn" id="2_oxyje"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_dock.gd" id="7"]
[ext_resource type="PackedScene" uid="uid://4etgd0rwjgct" path="res://addons/popochiu/editor/main_dock/tab_gui/tab_gui.tscn" id="10_82goo"]
[ext_resource type="PackedScene" uid="uid://q1bjkxavt2ay" path="res://addons/popochiu/editor/main_dock/tab_room/tab_room.tscn" id="12"]
[ext_resource type="PackedScene" uid="uid://bpj8jlet25coy" path="res://addons/popochiu/editor/main_dock/tab_audio/tab_audio.tscn" id="13"]
[sub_resource type="Image" id="Image_sgf6r"]
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_32xut"]
image = SubResource("Image_sgf6r")
[node name="Popochiu" type="Panel"]
clip_contents = true
custom_minimum_size = Vector2(340, 0)
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("7")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="TabContainer" type="TabContainer" parent="MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
current_tab = 0
[node name="Main" parent="MarginContainer/VBoxContainer/TabContainer" instance=ExtResource("2_oxyje")]
unique_name_in_owner = true
layout_mode = 2
[node name="Room" parent="MarginContainer/VBoxContainer/TabContainer" instance=ExtResource("12")]
unique_name_in_owner = true
visible = false
layout_mode = 2
focus_mode = 2
metadata/_tab_index = 1
[node name="Audio" parent="MarginContainer/VBoxContainer/TabContainer" instance=ExtResource("13")]
unique_name_in_owner = true
visible = false
layout_mode = 2
focus_mode = 2
metadata/_tab_index = 2
[node name="GUI" parent="MarginContainer/VBoxContainer/TabContainer" instance=ExtResource("10_82goo")]
unique_name_in_owner = true
visible = false
layout_mode = 2
metadata/_tab_index = 3
[node name="FooterPanel" type="PanelContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/FooterPanel"]
layout_mode = 2
size_flags_vertical = 3
alignment = 2
[node name="Version" type="Label" parent="MarginContainer/VBoxContainer/FooterPanel/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "v2.0.1"
[node name="BtnSetup" type="Button" parent="MarginContainer/VBoxContainer/FooterPanel/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Opens wiki in web browser"
text = "Setup"
icon = SubResource("ImageTexture_32xut")
[node name="BtnDocs" type="Button" parent="MarginContainer/VBoxContainer/FooterPanel/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Opens wiki in web browser"
text = "Documentation"
icon = SubResource("ImageTexture_32xut")

View file

@ -0,0 +1,51 @@
@tool
extends LineEdit
var groups := {}: set = set_groups
# ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ GODOT ░░░░
func _ready() -> void:
right_icon = get_theme_icon('Search', 'EditorIcons')
# ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ SET & GET ░░░░
func set_groups(value: Dictionary) -> void:
groups = value
if groups:
text_changed.connect(
_filter_rows.bind(groups),
CONNECT_REFERENCE_COUNTED
)
# ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ PRIVATE ░░░░
# `source` is one of the `_types` dictionaries in PopochiuDock, TabRoom and
# TabAudio
func _filter_rows(new_text: String, source: Dictionary) -> void:
for type_dic in source.values():
type_dic.group.show()
var title_in_filter := false
if type_dic.group.title.findn(new_text) > -1:
title_in_filter = true
var hidden_rows := 0
# type_dic.group is a PopochiuGroup
var rows: Array = type_dic.group.get_elements()
for row in rows:
row.show()
if new_text.is_empty(): continue
if (row as Control).name.findn(new_text) < 0\
and not title_in_filter:
hidden_rows += 1
row.hide()
if hidden_rows == rows.size() and not new_text.is_empty():
type_dic.group.hide()

View file

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

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
<g id="PopochiuGroup" transform="matrix(0.5,0,0,0.5,0,0)">
<rect x="0" y="0" width="32" height="32" style="fill:none;"/>
<g transform="matrix(3.25,0,0,3.25,-32.75,-39.25)">
<path d="M19,13.615C19,13.276 18.724,13 18.385,13L11.615,13C11.276,13 11,13.276 11,13.615L11,20.385C11,20.724 11.276,21 11.615,21L18.385,21C18.724,21 19,20.724 19,20.385L19,13.615Z" style="fill:none;stroke:rgb(112,109,235);stroke-width:1.23px;"/>
</g>
<g transform="matrix(0.673999,0,0,0.570028,13,-2.18068)">
<path d="M0,24L8.902,31.902L-0,39.789" style="fill:none;stroke:rgb(112,109,235);stroke-width:6.41px;"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://uwjkfsrpfx3e"
path="res://.godot/imported/popochiu_group.svg-55d153202c16f767328f8314e84a5c37.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/popochiu/editor/main_dock/popochiu_group/images/popochiu_group.svg"
dest_files=["res://.godot/imported/popochiu_group.svg-55d153202c16f767328f8314e84a5c37.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
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,199 @@
@tool
@icon("res://addons/popochiu/editor/main_dock/popochiu_group/images/popochiu_group.svg")
class_name PopochiuGroup
extends PanelContainer
signal create_clicked
const PopochiuRow := preload("res://addons/popochiu/editor/main_dock/popochiu_row/popochiu_row.gd")
@export var icon: Texture2D : set = set_icon
@export var is_open := true : set = set_is_open
@export var color: Color = Color("999999") : set = set_color
@export var title := "Group" : set = set_title
@export var can_create := true
@export var create_text := ""
@export var target_list: NodePath = ""
@export var custom_title_count := false
var _external_list: VBoxContainer = null
@onready var header: PanelContainer = %Header
@onready var arrow: TextureRect = %Arrow
@onready var trt_icon: TextureRect = %Icon
@onready var lbl_title: Label = %Title
@onready var body: Container = %Body
@onready var btn_create: Button = %BtnCreate
@onready var list: VBoxContainer = %List
#region Godot ######################################################################################
func _ready() -> void:
# Establecer estado inicial
add_theme_stylebox_override("panel", get_theme_stylebox("panel").duplicate())
(get_theme_stylebox("panel") as StyleBoxFlat).border_color = color
if is_instance_valid(icon):
trt_icon.texture = icon
lbl_title.text = title
btn_create.icon = get_theme_icon("Add", "EditorIcons")
btn_create.text = create_text
self.is_open = list.get_child_count() > 0
if not can_create:
btn_create.hide()
header.gui_input.connect(_on_input)
list.resized.connect(_update_child_count)
btn_create.pressed.connect(emit_signal.bind("create_clicked"))
if target_list:
_external_list = get_node(target_list) as VBoxContainer
self.is_open = _external_list.get_child_count() > 0
#endregion
#region Public #####################################################################################
func clear_list() -> void:
for c in list.get_children():
# Fix #216: Delete the row immediately so that it does not interfere with the creation of
# other rows that may have the same name as it
c.free()
func add(node: Node, sort := false) -> void:
if sort:
node.ready.connect(_order_list.bind(node))
list.add_child(node)
btn_create.disabled = false
if not is_open:
self.is_open = true
func clear_favs() -> void:
for popochiu_row: PopochiuRow in list.get_children():
popochiu_row.clear_tag()
func disable_create() -> void:
btn_create.disabled = true
func enable_create() -> void:
btn_create.disabled = false
func get_elements() -> Array:
return list.get_children()
func remove_by_name(node_name: String) -> void:
if list.has_node(node_name):
var node: HBoxContainer = list.get_node(node_name)
list.remove_child(node)
node.free()
func add_header_button(btn: Button) -> void:
btn_create.add_sibling(btn)
func set_title_count(count: int, max_count := 0) -> void:
if max_count > 0:
lbl_title.text = "%s (%d/%d)" % [title, count, max_count]
else:
lbl_title.text = "%s (%d)" % [title, count]
func get_by_name(node_name: String) -> HBoxContainer:
if list.has_node(node_name):
return list.get_node(node_name)
return null
#endregion
#region SetGet #####################################################################################
func set_icon(value: Texture2D) -> void:
icon = value
if is_instance_valid(trt_icon):
trt_icon.texture = value
func set_is_open(value: bool) -> void:
is_open = value
_toggled(value)
func set_color(value: Color) -> void:
color = value
if is_instance_valid(header):
(get_theme_stylebox("panel") as StyleBoxFlat).border_color = value
func set_title(value: String) -> void:
title = value
if is_instance_valid(lbl_title):
lbl_title.text = value
#endregion
#region Private ####################################################################################
func _on_input(event: InputEvent) -> void:
var mouse_event: = event as InputEventMouseButton
if mouse_event and mouse_event.button_index == MOUSE_BUTTON_LEFT \
and mouse_event.pressed:
is_open = !is_open
_toggled(is_open)
func _toggled(button_pressed: bool) -> void:
if is_instance_valid(arrow):
arrow.texture = (
get_theme_icon("GuiTreeArrowDown", "EditorIcons") if button_pressed
else get_theme_icon("GuiTreeArrowRight", "EditorIcons")
)
if is_instance_valid(body):
if button_pressed: body.show()
else: body.hide()
if is_instance_valid(_external_list):
_external_list.visible = button_pressed
func _update_child_count() -> void:
if custom_title_count: return
if is_instance_valid(lbl_title):
var children := list.get_child_count()
lbl_title.text = title + (" (%d)" % children) if children > 1 else title
func _order_list(node: Node) -> void:
node.ready.disconnect(_order_list)
# Place the new row in its place alphabetically
var place_before: Node = null
for row in list.get_children():
if str(node.name) < str(row.name):
place_before = row
break
if not place_before: return
list.move_child(node, place_before.get_index())
#endregion

View file

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

View file

@ -0,0 +1,91 @@
[gd_scene load_steps=6 format=3 uid="uid://b55ialbvpilxv"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_group/popochiu_group.gd" id="1_lumyt"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qhsn2"]
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_t8mu1"]
content_margin_left = 0.0
content_margin_top = 0.0
content_margin_right = 0.0
content_margin_bottom = 0.0
bg_color = Color(0.6, 0.6, 0.6, 0.211765)
draw_center = false
corner_detail = 5
expand_margin_left = 4.0
expand_margin_right = 4.0
[sub_resource type="Image" id="Image_e0ep0"]
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_uhpk4"]
image = SubResource("Image_e0ep0")
[node name="PopochiuGroup" type="PanelContainer"]
offset_right = 320.0
offset_bottom = 24.0
theme_override_styles/panel = SubResource("StyleBoxFlat_qhsn2")
script = ExtResource("1_lumyt")
is_open = false
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 2
[node name="Header" type="PanelContainer" parent="VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_t8mu1")
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/Header"]
layout_mode = 2
[node name="Arrow" type="TextureRect" parent="VBoxContainer/Header/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = SubResource("ImageTexture_uhpk4")
stretch_mode = 4
[node name="Icon" type="TextureRect" parent="VBoxContainer/Header/HBoxContainer"]
unique_name_in_owner = true
texture_filter = 1
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="Title" type="Label" parent="VBoxContainer/Header/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Group"
[node name="Body" type="VBoxContainer" parent="VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
[node name="BtnCreate" type="Button" parent="VBoxContainer/Body"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
icon = SubResource("ImageTexture_uhpk4")
[node name="List" type="VBoxContainer" parent="VBoxContainer/Body"]
unique_name_in_owner = true
layout_mode = 2

View file

@ -0,0 +1,237 @@
@tool
extends "res://addons/popochiu/editor/main_dock/popochiu_row/popochiu_row.gd"
signal group_selected(type: int)
signal deleted(file_path: String)
enum AudioOptions {
DELETE = MenuOptions.DELETE,
ADD_TO_MUSIC,
ADD_TO_SFX,
ADD_TO_VOICE,
ADD_TO_UI
}
const DELETE_AUDIO_CUE_MSG = "This will remove the [b]%s[/b] resource. Calls to this audio in \
scripts will not work anymore. This action cannot be reversed. Continue?"
const DELETE_AUDIO_CUE_ASK = "Delete [b]%s[/b] file too? (cannot be reversed)"
const DELETE_AUDIO_FILE_MSG = "[b]%s[/b] will be deleted in the file system. This action cannot be \
reversed. Continue?"
# Only used by rows that represent an audio file
var file_name: String
var audio_cue: AudioCue
var cue_group: String
var stream_player: AudioStreamPlayer
var audio_tab: VBoxContainer = null
var is_playing := false :
set = set_is_playing
var current_playback_position := 0.0
@onready var play_btn: Button = %Play
@onready var stop_btn: Button = %Stop
#region Godot ######################################################################################
func _ready() -> void:
super()
# Assign icons
play_btn.icon = get_theme_icon("MainPlay", "EditorIcons")
stop_btn.icon = get_theme_icon("Stop", "EditorIcons")
# Connect to children's signals
play_btn.pressed.connect(play)
stop_btn.pressed.connect(stop)
# Remove group options if this is a PopochiuAudioCue
if is_instance_valid(audio_cue):
menu_popup.remove_item(menu_popup.get_item_index(AudioOptions.ADD_TO_MUSIC))
menu_popup.remove_item(menu_popup.get_item_index(AudioOptions.ADD_TO_SFX))
menu_popup.remove_item(menu_popup.get_item_index(AudioOptions.ADD_TO_VOICE))
menu_popup.remove_item(menu_popup.get_item_index(AudioOptions.ADD_TO_UI))
else:
label.text = file_name
#endregion
#region Virtual ####################################################################################
func _remove_object() -> void:
_delete_dialog = PopochiuEditorHelper.DELETE_CONFIRMATION_SCENE.instantiate()
if is_instance_valid(audio_cue):
_delete_dialog.title = "Remove %s cue" % audio_cue.resource_name
_delete_dialog.message = DELETE_AUDIO_CUE_MSG % audio_cue.resource_name
_delete_dialog.ask = DELETE_AUDIO_CUE_ASK % audio_cue.audio.resource_path
_delete_dialog.on_confirmed = _remove_from_popochiu
else:
_delete_dialog.title = "Delete %s" % file_name
_delete_dialog.message = DELETE_AUDIO_FILE_MSG % path
_delete_dialog.on_confirmed = _delete_from_file_system
PopochiuEditorHelper.show_delete_confirmation(_delete_dialog)
#endregion
#region Public #####################################################################################
func select() -> void:
EditorInterface.edit_resource(audio_cue)
super()
func play() -> void:
if is_playing:
# Pause the audio stream
is_playing = false
return
if is_instance_valid(audio_tab.last_played):
# Stop the currently playing row (which is different from this one)
audio_tab.last_played.stop()
if not is_instance_valid(audio_cue):
# If the row does not have a [PopochiuAudioCue] assigned, then it is the row of an audio
# file. Therefore, the [AudioStream] to play will be its own [path]
var stream: AudioStream = load(path)
stream.loop = false
stream_player.stream = stream
else:
# Otherwise, the [AudioStream] to play will be that of the audio file associated with this
# [PopochiuAudioCue.audio]
stream_player.stream = audio_cue.audio
# The values of [AudioStream.pitch_scale] and [AudioStream.volume_db] should be taken from
# the information stored in the [PopochiuAudioCue].
stream_player.pitch_scale = audio_cue.get_pitch_scale()
stream_player.volume_db = audio_cue.volume
is_playing = true
func stop() -> void:
is_playing = false
current_playback_position = 0.0
label.add_theme_color_override("font_color", dflt_font_color)
stream_player.stream = null
audio_tab.last_played = null
#endregion
#region SetGet #####################################################################################
func set_is_playing(value: bool) -> void:
is_playing = value
if is_playing:
if not stream_player.finished.is_connected(stop):
stream_player.finished.connect(stop)
stream_player.play(current_playback_position)
audio_tab.last_played = self
else:
current_playback_position = stream_player.get_playback_position()
if stream_player.playing:
stream_player.stop()
stream_player.finished.disconnect(stop)
play_btn.icon = play_btn.get_theme_icon("Pause" if is_playing else "MainPlay", "EditorIcons")
#endregion
#region Private ####################################################################################
func _get_menu_cfg() -> Array:
return [
{
id = AudioOptions.ADD_TO_MUSIC,
icon = preload("res://addons/popochiu/icons/music.png"),
label = "Add to Music"
},
{
id = AudioOptions.ADD_TO_SFX,
icon = preload("res://addons/popochiu/icons/sfx.png"),
label = "Add to Sound Effects"
},
{
id = AudioOptions.ADD_TO_VOICE,
icon = preload("res://addons/popochiu/icons/voice.png"),
label = "Add to Voices"
},
{
id = AudioOptions.ADD_TO_UI,
icon = preload("res://addons/popochiu/icons/ui.png"),
label = "Add to Graphic Interface"
}
] + super()
func _menu_item_pressed(id: int) -> void:
match id:
AudioOptions.ADD_TO_MUSIC:
group_selected.emit(PopochiuResources.AudioTypes.MUSIC)
AudioOptions.ADD_TO_SFX:
group_selected.emit(PopochiuResources.AudioTypes.SOUND_EFFECT)
AudioOptions.ADD_TO_VOICE:
group_selected.emit(PopochiuResources.AudioTypes.VOICE)
AudioOptions.ADD_TO_UI:
group_selected.emit(PopochiuResources.AudioTypes.UI)
_:
super(id)
func _remove_from_popochiu() -> void:
# Remove the AudioCue from popochiu_data.cfg ---------------------------------------------------
var group_data: Array = PopochiuResources.get_data_value(
"audio", cue_group, []
)
if group_data:
group_data.erase(audio_cue.resource_path)
if group_data.is_empty():
PopochiuResources.erase_data_value("audio", cue_group)
else:
group_data.sort_custom(
func (a: String, b: String) -> bool:
return PopochiuUtils.sort_by_file_name(a, b)
)
PopochiuResources.set_data_value("audio", cue_group, group_data)
# Remove the AudioCue from the A singleton -----------------------------------------------------
PopochiuResources.remove_audio_autoload(cue_group, name, audio_cue.resource_path)
# Delete the file in its corresponding group in Audio tab
deleted.emit(audio_cue.audio.resource_path)
if _delete_dialog.check_box.button_pressed:
_delete_from_file_system()
else:
queue_free()
func _delete_from_file_system() -> void:
# Delete the .tres file from the file system
var err: int = DirAccess.remove_absolute(path)
if err != OK:
PopochiuUtils.print_error("Couldn't delete audio cue %s (err_code: %d)" % [path, err])
return
# Delete the audio file linked to the cue
var audio_file_path := audio_cue.audio.resource_path
err = DirAccess.remove_absolute(audio_file_path)
if err != OK:
PopochiuUtils.print_error(
"Couldn't delete audio file %s (err_code: %d)" % [audio_file_path, err]
)
return
# Do this so Godot removes the .import file of the audio file
EditorInterface.get_resource_filesystem().update_file(audio_file_path)
EditorInterface.get_resource_filesystem().scan()
EditorInterface.get_resource_filesystem().scan_sources()
queue_free()
#endregion

View file

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

View file

@ -0,0 +1,62 @@
[gd_scene load_steps=9 format=3 uid="uid://ds6ojs55q50ud"]
[ext_resource type="PackedScene" uid="uid://dwtwuqw2hpdpe" path="res://addons/popochiu/editor/main_dock/popochiu_row/popochiu_row.tscn" id="1_i2mx0"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_row/audio_row/popochiu_audio_row.gd" id="2_24kri"]
[ext_resource type="Texture2D" uid="uid://d1dnmfkhscb7r" path="res://addons/popochiu/icons/music.png" id="3_hi2e1"]
[ext_resource type="Texture2D" uid="uid://cfh1uxtaff0ks" path="res://addons/popochiu/icons/sfx.png" id="4_1iw68"]
[ext_resource type="Texture2D" uid="uid://6ewpl4v0td2h" path="res://addons/popochiu/icons/voice.png" id="5_ray7p"]
[ext_resource type="Texture2D" uid="uid://528j2rksws2c" path="res://addons/popochiu/icons/ui.png" id="6_1bl3m"]
[sub_resource type="Image" id="Image_dygia"]
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_v80gh"]
image = SubResource("Image_dygia")
[node name="PopochiuAudioRow" instance=ExtResource("1_i2mx0")]
script = ExtResource("2_24kri")
[node name="Label" parent="HBoxContainer" index="0"]
text = ""
[node name="Play" type="Button" parent="Panel/ButtonsContainer" index="0"]
unique_name_in_owner = true
layout_mode = 2
mouse_filter = 1
icon = SubResource("ImageTexture_v80gh")
flat = true
[node name="Stop" type="Button" parent="Panel/ButtonsContainer" index="1"]
unique_name_in_owner = true
layout_mode = 2
mouse_filter = 1
icon = SubResource("ImageTexture_v80gh")
flat = true
[node name="BtnMenu" parent="Panel/ButtonsContainer" index="2"]
icon = SubResource("ImageTexture_v80gh")
item_count = 6
popup/item_0/text = "Add to Music"
popup/item_0/icon = ExtResource("3_hi2e1")
popup/item_0/id = 1
popup/item_1/text = "Add to Sound effects"
popup/item_1/icon = ExtResource("4_1iw68")
popup/item_1/id = 2
popup/item_2/text = "Add to Voices"
popup/item_2/icon = ExtResource("5_ray7p")
popup/item_2/id = 3
popup/item_3/text = "Add to Graphic interface"
popup/item_3/icon = ExtResource("6_1bl3m")
popup/item_3/id = 4
popup/item_4/text = ""
popup/item_4/id = -1
popup/item_4/separator = true
popup/item_5/text = "Remove"
popup/item_5/icon = SubResource("ImageTexture_v80gh")
popup/item_5/id = 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bw3ie8wfwa2i2"
path="res://.godot/imported/add_to_core.png-52def14ca6e499df1e292c93f01c4349.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/popochiu/editor/main_dock/popochiu_row/images/add_to_core.png"
dest_files=["res://.godot/imported/add_to_core.png-52def14ca6e499df1e292c93f01c4349.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bahipxbrrss0o"
path="res://.godot/imported/delete.png-27dd9adc116bbf3fc8b20a99d1331933.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/popochiu/editor/main_dock/popochiu_row/images/delete.png"
dest_files=["res://.godot/imported/delete.png-27dd9adc116bbf3fc8b20a99d1331933.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://wm7qycjntmfr"
path="res://.godot/imported/open.png-eb4e739212f91fcaedbead9efc5f731f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/popochiu/editor/main_dock/popochiu_row/images/open.png"
dest_files=["res://.godot/imported/open.png-eb4e739212f91fcaedbead9efc5f731f.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

View file

@ -0,0 +1,79 @@
@tool
extends "res://addons/popochiu/editor/main_dock/popochiu_row/object_row/popochiu_object_row.gd"
enum CharacterOptions {
DELETE = MenuOptions.DELETE,
ADD_TO_CORE = Options.ADD_TO_CORE,
SET_AS_PC,
}
const TAG_ICON = preload("res://addons/popochiu/icons/player_character.png")
const STATE_TEMPLATE = "res://addons/popochiu/engine/templates/character_state_template.gd"
var is_pc := false : set = set_is_pc
#region Godot ######################################################################################
func _ready() -> void:
super()
# Assign icons
tag.texture = TAG_ICON
#endregion
#region Virtual ####################################################################################
func _get_state_template() -> Script:
return load(STATE_TEMPLATE)
func _clear_tag() -> void:
if is_pc:
is_pc = false
#endregion
#region SetGet #####################################################################################
func set_is_pc(value: bool) -> void:
is_pc = value
if is_pc:
PopochiuEditorHelper.signal_bus.pc_changed.emit(name)
tag.visible = value
menu_popup.set_item_disabled(menu_popup.get_item_index(CharacterOptions.SET_AS_PC), value)
#endregion
#region Private ####################################################################################
func _get_menu_cfg() -> Array:
return [
{
id = CharacterOptions.SET_AS_PC,
icon = TAG_ICON,
label = "Set as Player-controlled Character (PC)",
},
] + super()
func _menu_item_pressed(id: int) -> void:
match id:
CharacterOptions.SET_AS_PC:
self.is_pc = true
_:
super(id)
func _remove_from_core() -> void:
# Delete the object from Popochiu
PopochiuResources.remove_autoload_obj(PopochiuResources.C_SNGL, name)
PopochiuResources.erase_data_value("characters", str(name))
# Continue with the deletion flow
super()
#endregion

View file

@ -0,0 +1,15 @@
@tool
extends "res://addons/popochiu/editor/main_dock/popochiu_row/object_row/popochiu_object_row.gd"
#region Private ####################################################################################
func _remove_from_core() -> void:
# Delete the object from Popochiu
PopochiuResources.remove_autoload_obj(PopochiuResources.D_SNGL, name)
PopochiuResources.erase_data_value("dialogs", str(name))
# Continue with the deletion flow
super()
#endregion

View file

@ -0,0 +1,78 @@
@tool
extends "res://addons/popochiu/editor/main_dock/popochiu_row/object_row/popochiu_object_row.gd"
enum InventoryItemOptions {
DELETE = MenuOptions.DELETE,
ADD_TO_CORE = Options.ADD_TO_CORE,
START_WITH_IT,
}
const TAG_ICON = preload("res://addons/popochiu/icons/inventory_item_start.png")
const STATE_TEMPLATE = "res://addons/popochiu/engine/templates/inventory_item_state_template.gd"
var is_on_start := false : set = set_is_on_start
#region Godot ######################################################################################
func _ready() -> void:
super()
# Assign icons
tag.texture = TAG_ICON
#endregion
#region Virtual ####################################################################################
func _get_state_template() -> Script:
return load(STATE_TEMPLATE)
#endregion
#region SetGet #####################################################################################
func set_is_on_start(value: bool) -> void:
is_on_start = value
tag.visible = value
#endregion
#region Private ####################################################################################
func _get_menu_cfg() -> Array:
return [
{
id = InventoryItemOptions.START_WITH_IT,
icon = TAG_ICON,
label = "Start with it",
},
] + super()
func _menu_item_pressed(id: int) -> void:
match id:
InventoryItemOptions.START_WITH_IT:
var items: Array = PopochiuConfig.get_inventory_items_on_start()
var script_name := str(name)
if script_name in items:
items.erase(script_name)
else:
items.append(script_name)
PopochiuConfig.set_inventory_items_on_start(items)
self.is_on_start = script_name in items
_:
super(id)
func _remove_from_core() -> void:
# Delete the object from Popochiu
PopochiuResources.remove_autoload_obj(PopochiuResources.I_SNGL, name)
PopochiuResources.erase_data_value("inventory_items", str(name))
# Continue with the deletion flow
super()
#endregion

View file

@ -0,0 +1,334 @@
@tool
extends "res://addons/popochiu/editor/main_dock/popochiu_row/popochiu_row.gd"
## Row for the main object types: Room, Character, Inventory item, Dialog
enum Options {
DELETE = MenuOptions.DELETE,
ADD_TO_CORE,
}
const DELETE_MESSAGE = "This will remove the [b]%s[/b] object in [b]%s[/b] scene. Uses of this \
object in scripts will not work anymore. This action cannot be undone. Continue?"
const DELETE_ASK_MESSAGE = "Do you want to delete the [b]%s[/b] folder too?%s (cannot be reversed)"
const ADD_TO_CORE_ICON = preload(
"res://addons/popochiu/editor/main_dock/popochiu_row/images/add_to_core.png"
)
const AUDIO_FILE_TYPES = ["AudioStreamOggVorbis", "AudioStreamMP3", "AudioStreamWAV"]
@onready var btn_open: Button = %BtnOpen
@onready var btn_script: Button = %BtnScript
@onready var btn_state: Button = %BtnState
@onready var btn_state_script: Button = %BtnStateScript
#region Godot ######################################################################################
func _ready() -> void:
# Assign icons
btn_open.icon = get_theme_icon("InstanceOptions", "EditorIcons")
btn_script.icon = get_theme_icon("Script", "EditorIcons")
btn_state.icon = get_theme_icon("Object", "EditorIcons")
btn_state_script.icon = get_theme_icon("GDScript", "EditorIcons")
# Connect to signals and create the options for the menu
super()
# Connect to children's signals
btn_open.pressed.connect(_open)
btn_script.pressed.connect(_open_script)
btn_state.pressed.connect(_edit_state)
btn_state_script.pressed.connect(_open_state_script)
# Disable some options by default
var add_to_core_idx := menu_popup.get_item_index(Options.ADD_TO_CORE)
if add_to_core_idx >= 0:
menu_popup.set_item_disabled(add_to_core_idx, true)
#endregion
#region Virtual ####################################################################################
## Shows a confirmation popup to ask the developer if the Popochiu object should be removed only
## from the core, or from the file system too.
func _remove_object() -> void:
var location := _get_location()
# Look into the Object"s folder for audio files and AudioCues to show the developer that those
# files will be removed too.
var audio_files := _search_audio_files(
EditorInterface.get_resource_filesystem().get_filesystem_path(path.get_base_dir())
)
_delete_dialog = PopochiuEditorHelper.DELETE_CONFIRMATION_SCENE.instantiate()
_delete_dialog.title = "Remove %s from %s" % [name, location]
_delete_dialog.message = DELETE_MESSAGE % [name, location]
_delete_dialog.ask = DELETE_ASK_MESSAGE % [
path.get_base_dir(),
"" if audio_files.is_empty()
else " ([b]%d[/b] audio cues will be deleted)" % audio_files.size()
]
_delete_dialog.on_confirmed = _remove_from_core
PopochiuEditorHelper.show_delete_confirmation(_delete_dialog)
func _get_state_template() -> Script:
return null
func _get_location() -> String:
return "Popochiu"
#endregion
#region Public #####################################################################################
## Called to make the row appear semitransparent to indicate that the object is in the project
## (has a folder with files inside) but is not part of the [code]popochiu_data.cfg[/code] file nor
## its corresponding autoload (e.g., R, C, I, D). This can happen when one removes an object from
## the project without removing its files, or when adding objects from another project.
func show_as_not_in_core() -> void:
label.modulate.a = 0.5
menu_popup.set_item_disabled(menu_popup.get_item_index(Options.ADD_TO_CORE), false)
#endregion
#region Private ####################################################################################
func _get_menu_cfg() -> Array:
return [
{
id = Options.ADD_TO_CORE,
icon = ADD_TO_CORE_ICON,
label = "Add to Popochiu",
types = PopochiuResources.MAIN_TYPES
},
] + super()
func _menu_item_pressed(id: int) -> void:
match id:
Options.ADD_TO_CORE:
_add_object_to_core()
_:
super(id)
## Add this Object (Room, Character, InventoryItem, Dialog) to popochiu_data.cfg so it can be used
## by Popochiu.
func _add_object_to_core() -> void:
var target_array := ""
var resource: Resource
if ".tscn" in path:
resource = load(path.replace(".tscn", ".tres"))
else:
resource = load(path)
match type:
PopochiuResources.Types.ROOM:
target_array = "rooms"
PopochiuResources.Types.CHARACTER:
target_array = "characters"
PopochiuResources.Types.INVENTORY_ITEM:
target_array = "inventory_items"
PopochiuResources.Types.DIALOG:
target_array = "dialogs"
if PopochiuEditorHelper.add_resource_to_popochiu(target_array, resource) != OK:
PopochiuUtils.print_error("Couldn't add Object [b]%s[/b] to Popochiu." % str(name))
return
# Add the object to its corresponding singleton
PopochiuResources.update_autoloads(true)
label.modulate.a = 1.0
menu_popup.set_item_disabled(menu_popup.get_item_index(Options.ADD_TO_CORE), true)
## Selects the main file of the object in the FileSystem and opens it so that it can be edited.
func _open() -> void:
EditorInterface.select_file(path)
if ".tres" in path:
EditorInterface.edit_resource(load(path))
else:
EditorInterface.set_main_screen_editor("2D")
EditorInterface.open_scene_from_path(path)
select()
func _open_script() -> void:
var script_path := path
if ".tscn" in path:
# A room, character, inventory item, or prop
script_path = path.replace(".tscn", ".gd")
elif ".tres" in path:
# A dialog
script_path = path.replace(".tres", ".gd")
elif not ".gd" in path:
return
EditorInterface.select_file(script_path)
EditorInterface.set_main_screen_editor("Script")
EditorInterface.edit_script(load(script_path))
select()
func _edit_state() -> void:
EditorInterface.select_file(path.replace(".tscn", ".tres"))
EditorInterface.edit_resource(load(path.replace(".tscn", ".tres")))
select()
func _open_state_script() -> void:
var state := load(path.replace(".tscn", ".tres"))
EditorInterface.select_file(state.get_script().resource_path)
EditorInterface.set_main_screen_editor("Script")
EditorInterface.edit_resource(state.get_script())
select()
func _search_audio_files(dir: EditorFileSystemDirectory) -> Array:
var files := []
for idx in dir.get_subdir_count():
files.append_array(_search_audio_files(dir.get_subdir(idx)))
for idx in dir.get_file_count():
match dir.get_file_type(idx):
AUDIO_FILE_TYPES:
files.append(dir.get_file_path(idx))
return files
func _remove_from_core() -> void:
# Check if the files should be deleted in the file system
if _delete_dialog.check_box.button_pressed:
_delete_from_file_system()
elif type in PopochiuResources.MAIN_TYPES:
show_as_not_in_core()
var edited_scene: Node = EditorInterface.get_edited_scene_root()
if edited_scene and edited_scene.get("script_name") and edited_scene.script_name == name:
# If the open scene matches the object being deleted, skip saving the scene
queue_free()
return
EditorInterface.save_scene()
queue_free()
## Remove this object's directory (subfolders included) from the file system.
func _delete_from_file_system() -> void:
var object_dir: EditorFileSystemDirectory = \
EditorInterface.get_resource_filesystem().get_filesystem_path(path.get_base_dir())
# Remove files, sub folders and its files.
_recursive_delete(object_dir)
## Remove the `dir` directory from the system. For Godot to be able to delete a directory, it has to
## be empty, so this method first deletes the files from from the directory and each of its
## subdirectories.
func _recursive_delete(dir: EditorFileSystemDirectory) -> void:
if dir.get_file_count() > 0:
assert(
_delete_files(dir) == OK,
"[Popochiu] Error removing files in recursive elimination of %s" % dir.get_path()
)
if dir.get_subdir_count() > 0:
for folder_idx in dir.get_subdir_count():
# Check if there are more folders inside the folder or delete the files inside it before
# deleting the folder itself
_recursive_delete(dir.get_subdir(folder_idx))
assert(
DirAccess.remove_absolute(dir.get_path()) == OK,
"[Popochiu] Error removing folder in recursive elimination of %s" % dir.get_path()
)
EditorInterface.get_resource_filesystem().scan()
## Delete files within [param dir] directory. First, get the paths to each file, then delete them
## one by one calling [method EditorFileSystem.update_file], so that in case it's an imported file,
## its [b].import[/b] is also deleted.
func _delete_files(dir: EditorFileSystemDirectory) -> int:
# Stores the paths of the files to be deleted.
var files_paths := []
# Stores the paths of the audio resources to delete
var deleted_audios := []
for file_idx: int in dir.get_file_count():
match dir.get_file_type(file_idx):
AUDIO_FILE_TYPES:
deleted_audios.append(dir.get_file_path(file_idx))
"Resource":
var resource: Resource = load(dir.get_file_path(file_idx))
if not resource is AudioCue:
# If the resource is not an AudioCue, then it should be ignored for deletion
# in the game data
continue
# Delete the [PopochiuAudioCue] in the project data file and the A singleton
assert(
_delete_audio_cue_in_data(resource) == true,
"[Popochiu] Couldn't remove [b]%s[/b] during deletion of [b]%s[/b]." %
[resource.resource_path, dir.get_path()]
)
deleted_audios.append(resource.audio.resource_path)
files_paths.append(dir.get_file_path(file_idx))
for fp: String in files_paths:
var err: int = DirAccess.remove_absolute(fp)
if err != OK:
PopochiuUtils.print_error("Couldn't delete file %s. err_code:%d" % [err, fp])
return err
EditorInterface.get_resource_filesystem().scan()
# Delete the rows of audio files and the deleted AudioCues in the Audio tab
if not deleted_audios.is_empty():
PopochiuEditorHelper.signal_bus.audio_cues_deleted.emit(deleted_audios)
# Remove extra files (like .import)
for file_name: String in DirAccess.get_files_at(dir.get_path()):
DirAccess.remove_absolute(dir.get_path() + "/" + file_name)
EditorInterface.get_resource_filesystem().scan()
return OK
## Looks to which audio group corresponds [param audio_cue] and deletes it both from
## [code]popochiu_data.cfg[/code] and the [b]A[/b] singleton (which is the one used to allow code
## autocompletion related to [PopochiuAudioCue]s).
func _delete_audio_cue_in_data(audio_cue: AudioCue) -> bool:
# TODO: This could be improved a lot if each PopochiuAudioCue has a variable to store the group
# to which it corresponds to.
# Delete the [PopochiuAudioCue] in the popochiu_data.cfg
for cue_group in ["mx_cues", "sfx_cues", "vo_cues", "ui_cues"]:
var cues: Array = PopochiuResources.get_data_value("audio", cue_group, [])
if not cues.has(audio_cue.resource_path): continue
cues.erase(audio_cue.resource_path)
if PopochiuResources.set_data_value("audio", cue_group, cues) != OK:
return false
# Fix #59 : remove the [PopochiuAudioCue] from the [A] singleton
PopochiuResources.remove_audio_autoload(
cue_group, audio_cue.resource_name, audio_cue.resource_path
)
break
return true
#endregion

View file

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

View file

@ -0,0 +1,58 @@
[gd_scene load_steps=5 format=3 uid="uid://dwbo3pl372ugo"]
[ext_resource type="PackedScene" uid="uid://dwtwuqw2hpdpe" path="res://addons/popochiu/editor/main_dock/popochiu_row/popochiu_row.tscn" id="1_xi41g"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_row/object_row/popochiu_object_row.gd" id="2_g05pm"]
[sub_resource type="Image" id="Image_15l6n"]
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_12sj2"]
image = SubResource("Image_15l6n")
[node name="PopochiuMainObjectRow" instance=ExtResource("1_xi41g")]
script = ExtResource("2_g05pm")
[node name="Label" parent="HBoxContainer" index="0"]
text = "PopochiuMainObjectRow"
[node name="BtnOpen" type="Button" parent="Panel/ButtonsContainer" index="0"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 3
tooltip_text = "Open in Editor"
icon = SubResource("ImageTexture_12sj2")
flat = true
[node name="BtnScript" type="Button" parent="Panel/ButtonsContainer" index="1"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 3
tooltip_text = "Open in Script"
icon = SubResource("ImageTexture_12sj2")
flat = true
[node name="BtnState" type="Button" parent="Panel/ButtonsContainer" index="2"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 3
tooltip_text = "Open state"
icon = SubResource("ImageTexture_12sj2")
flat = true
[node name="BtnStateScript" type="Button" parent="Panel/ButtonsContainer" index="3"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 3
tooltip_text = "Open state Script"
icon = SubResource("ImageTexture_12sj2")
flat = true

View file

@ -0,0 +1,60 @@
@tool
extends "res://addons/popochiu/editor/main_dock/popochiu_row/object_row/popochiu_object_row.gd"
const PROP_TEMPLATE = "res://addons/popochiu/engine/templates/prop_template.gd"
var node_path := ""
#region Godot ######################################################################################
func _ready() -> void:
super()
if not FileAccess.file_exists(path.replace(".tscn", ".gd")):
btn_script.hide()
btn_state.hide()
btn_state_script.hide()
#endregion
#region Virtual ####################################################################################
func _get_location() -> String:
# Structure of path: "res://game/rooms/room_name/props/prop_name/"
# path split: [res:, popochiu, rooms, room_name, props, prop_name]
return "Room%s" % (path.split("/", false)[3]).to_pascal_case()
#endregion
#region Private ####################################################################################
func _remove_from_core() -> void:
var room_child_to_free: Node = null
if EditorInterface.get_edited_scene_root() is PopochiuRoom:
var opened_room: PopochiuRoom = EditorInterface.get_edited_scene_root()
match type:
PopochiuResources.Types.PROP:
room_child_to_free = opened_room.get_prop(str(name))
PopochiuResources.Types.HOTSPOT:
room_child_to_free = opened_room.get_hotspot(str(name))
PopochiuResources.Types.MARKER:
room_child_to_free = opened_room.get_marker(str(name))
PopochiuResources.Types.REGION:
room_child_to_free = opened_room.get_region(str(name))
PopochiuResources.Types.WALKABLE_AREA:
room_child_to_free = opened_room.get_walkable_area(str(name))
# Continue with the deletion flow
super()
# Fix #196: Remove the Node from the Room tree once the folder of the object has been deleted
# from the FileSystem (this applies to Props, Hotspots, Walkable areas and Regions).
if room_child_to_free:
room_child_to_free.queue_free()
EditorInterface.save_scene()
#endregion

View file

@ -0,0 +1,22 @@
[gd_scene load_steps=5 format=3 uid="uid://baei84pjb3fwj"]
[ext_resource type="PackedScene" uid="uid://dwbo3pl372ugo" path="res://addons/popochiu/editor/main_dock/popochiu_row/object_row/popochiu_object_row.tscn" id="1_yvb3l"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_row/object_row/room_object_row/popochiu_room_object_row.gd" id="2_ulg85"]
[sub_resource type="Image" id="Image_8gjpm"]
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_4qvg7"]
image = SubResource("Image_8gjpm")
[node name="PopochiuRoomObjectRow" instance=ExtResource("1_yvb3l")]
script = ExtResource("2_ulg85")
[node name="BtnMenu" parent="Panel/ButtonsContainer" index="4"]
popup/item_1/icon = SubResource("ImageTexture_4qvg7")

View file

@ -0,0 +1,90 @@
@tool
extends "res://addons/popochiu/editor/main_dock/popochiu_row/object_row/popochiu_object_row.gd"
enum RoomOptions {
DELETE = MenuOptions.DELETE,
ADD_TO_CORE = Options.ADD_TO_CORE,
SET_AS_MAIN,
}
const STATE_TEMPLATE = "res://addons/popochiu/engine/templates/room_state_template.gd"
var is_main := false : set = set_is_main
@onready var btn_play: Button = %BtnPlay
#region Godot ######################################################################################
func _ready() -> void:
super()
# Assign icons
tag.texture = get_theme_icon("Heart", "EditorIcons")
btn_play.icon = get_theme_icon("MainPlay", "EditorIcons")
btn_play.pressed.connect(_play)
#endregion
#region Virtual ####################################################################################
func _get_state_template() -> Script:
return load(STATE_TEMPLATE)
func _clear_tag() -> void:
if is_main:
is_main = false
#endregion
#region SetGet #####################################################################################
func set_is_main(value: bool) -> void:
is_main = value
if is_main:
# Call this first since the favs will be cleared
PopochiuEditorHelper.signal_bus.main_scene_changed.emit(path)
tag.visible = value
menu_popup.set_item_disabled(menu_popup.get_item_index(RoomOptions.SET_AS_MAIN), value)
#endregion
#region Private ####################################################################################
func _get_menu_cfg() -> Array:
return [
{
id = RoomOptions.SET_AS_MAIN,
icon = get_theme_icon("Heart", "EditorIcons"),
label = "Set as Main scene",
},
] + super()
func _menu_item_pressed(id: int) -> void:
match id:
RoomOptions.SET_AS_MAIN:
is_main = true
_:
super(id)
## Plays the scene of the clicked row
func _play() -> void:
EditorInterface.select_file(path)
EditorInterface.play_custom_scene(path)
func _remove_from_core() -> void:
# Delete the object from Popochiu
PopochiuResources.remove_autoload_obj(PopochiuResources.R_SNGL, name)
PopochiuResources.erase_data_value("rooms", str(name))
# Continue with the deletion flow
super()
#endregion

View file

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

View file

@ -0,0 +1,60 @@
[gd_scene load_steps=5 format=3 uid="uid://w3oki6lv6l7f"]
[ext_resource type="PackedScene" uid="uid://dwbo3pl372ugo" path="res://addons/popochiu/editor/main_dock/popochiu_row/object_row/popochiu_object_row.tscn" id="1_1hv2c"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_row/object_row/room_row/popochiu_room_row.gd" id="2_s306b"]
[sub_resource type="Image" id="Image_lkrau"]
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_3an75"]
image = SubResource("Image_lkrau")
[node name="PopochiuRoomRow" instance=ExtResource("1_1hv2c")]
script = ExtResource("2_s306b")
[node name="Label" parent="HBoxContainer" index="0"]
text = "PopochiuRoomRow"
[node name="Tag" parent="HBoxContainer" index="1"]
texture = SubResource("ImageTexture_3an75")
[node name="BtnPlay" type="Button" parent="Panel/ButtonsContainer" index="0"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 3
tooltip_text = "Open in Editor"
icon = SubResource("ImageTexture_3an75")
flat = true
[node name="BtnOpen" parent="Panel/ButtonsContainer" index="1"]
icon = SubResource("ImageTexture_3an75")
[node name="BtnScript" parent="Panel/ButtonsContainer" index="2"]
icon = SubResource("ImageTexture_3an75")
[node name="BtnState" parent="Panel/ButtonsContainer" index="3"]
icon = SubResource("ImageTexture_3an75")
[node name="BtnStateScript" parent="Panel/ButtonsContainer" index="4"]
icon = SubResource("ImageTexture_3an75")
[node name="BtnMenu" parent="Panel/ButtonsContainer" index="5"]
icon = SubResource("ImageTexture_3an75")
item_count = 3
popup/item_0/text = "Set as Main scene"
popup/item_0/icon = SubResource("ImageTexture_3an75")
popup/item_0/id = 3
popup/item_1/text = ""
popup/item_1/id = -1
popup/item_1/separator = true
popup/item_2/text = "Remove"
popup/item_2/icon = SubResource("ImageTexture_3an75")
popup/item_2/id = 0
popup/item_2/disabled = true

View file

@ -0,0 +1,125 @@
@tool
extends HBoxContainer
## The row that is created for Rooms, Characters, Inventory items, Dialogs, Props, Hotspots, Regions,
## Walkable areas, and Markers in the dock.
signal clicked(node: HBoxContainer)
enum MenuOptions {
SEPARATOR = -1,
DELETE,
}
const SELECTED_FONT_COLOR = Color("706deb")
const AudioCue = preload("res://addons/popochiu/engine/audio_manager/audio_cue.gd")
var path := ""
var is_menu_hidden := false
var type := -1
var _delete_dialog: PopochiuEditorHelper.DeleteConfirmation = null
@onready var label: Label = %Label
@onready var tag: TextureRect = %Tag
@onready var btn_menu: MenuButton = %BtnMenu
@onready var menu_popup: PopupMenu = btn_menu.get_popup()
@onready var buttons_container: HBoxContainer = %ButtonsContainer
@onready var dflt_font_color: Color = label.get_theme_color("font_color")
#region Godot ######################################################################################
func _ready() -> void:
label.text = str(name)
tooltip_text = path
# Assign icons
btn_menu.icon = get_theme_icon("GuiTabMenuHl", "EditorIcons")
# Create the context menu based checked the type of Object this row represents
_create_menu()
tag.hide()
if is_menu_hidden:
btn_menu.hide()
gui_input.connect(_check_click)
menu_popup.id_pressed.connect(_menu_item_pressed)
#endregion
#region Virtual ####################################################################################
func _remove_object() -> void:
pass
func _clear_tag() -> void:
pass
#endregion
#region Public #####################################################################################
func select() -> void:
label.add_theme_color_override("font_color", SELECTED_FONT_COLOR)
clicked.emit(self)
func deselect() -> void:
label.add_theme_color_override("font_color", dflt_font_color)
func remove_menu_option(opt: int) -> void:
menu_popup.remove_item(menu_popup.get_item_index(opt))
func add_button(btn: Button) -> void:
buttons_container.add_child(btn)
func clear_tag() -> void:
if tag.visible:
tag.visible = false
_clear_tag()
#endregion
#region Private ####################################################################################
func _create_menu() -> void:
menu_popup.clear()
for option in _get_menu_cfg():
if typeof(option) == TYPE_INT and option == MenuOptions.SEPARATOR:
menu_popup.add_separator("", MenuOptions.SEPARATOR)
elif not option.has("types") or (option.has("types") and type in option.types):
menu_popup.add_icon_item(option.icon, option.label, option.id)
if menu_popup.item_count == 2:
menu_popup.remove_item(menu_popup.get_item_index(MenuOptions.SEPARATOR))
func _get_menu_cfg() -> Array:
return [
MenuOptions.SEPARATOR,
{
id = MenuOptions.DELETE,
icon = get_theme_icon("Remove", "EditorIcons"),
label = "Remove"
}
]
func _check_click(event: InputEvent) -> void:
if PopochiuUtils.get_click_or_touch_index(event) == MOUSE_BUTTON_LEFT:
EditorInterface.select_file(path)
select()
func _menu_item_pressed(id: int) -> void:
match id:
MenuOptions.DELETE:
_remove_object()
#endregion

View file

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

View file

@ -0,0 +1,76 @@
[gd_scene load_steps=6 format=3 uid="uid://dwtwuqw2hpdpe"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_row/popochiu_row.gd" id="1_pqknt"]
[sub_resource type="Image" id="Image_87j38"]
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_4qvg7"]
image = SubResource("Image_87j38")
[sub_resource type="Image" id="Image_hcerf"]
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_jcwkb"]
image = SubResource("Image_hcerf")
[node name="PopochiuRow" type="HBoxContainer"]
offset_right = 320.0
offset_bottom = 40.0
script = ExtResource("1_pqknt")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
[node name="Label" type="Label" parent="HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 2.0
text = "PopochiuRow"
[node name="Tag" type="TextureRect" parent="HBoxContainer"]
unique_name_in_owner = true
visible = false
texture_filter = 1
layout_mode = 2
size_flags_horizontal = 10
size_flags_vertical = 4
tooltip_text = "Main scene"
texture = SubResource("ImageTexture_4qvg7")
[node name="Panel" type="Panel" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 1.5
mouse_filter = 1
[node name="ButtonsContainer" type="HBoxContainer" parent="Panel"]
unique_name_in_owner = true
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
alignment = 2
[node name="BtnMenu" type="MenuButton" parent="Panel/ButtonsContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
icon = SubResource("ImageTexture_jcwkb")
switch_on_hover = true
item_count = 1
popup/item_0/text = "Remove"
popup/item_0/icon = SubResource("ImageTexture_jcwkb")

View file

@ -0,0 +1,416 @@
@tool
extends VBoxContainer
## Handles the Audio tab in Popochiu's dock.
const SEARCH_PATH = "res://game/"
const POPOCHIU_AUDIO_ROW_SCENE = preload(
"res://addons/popochiu/editor/main_dock/popochiu_row/audio_row/popochiu_audio_row.tscn"
)
const AUDIO_FILE_EXTENSIONS = ["ogg", "mp3", "wav", "opus"]
const AudioCue = preload("res://addons/popochiu/engine/audio_manager/audio_cue.gd")
const AudioCueSound = preload("res://addons/popochiu/engine/audio_manager/audio_cue_sound.gd")
const AudioCueMusic = preload("res://addons/popochiu/engine/audio_manager/audio_cue_music.gd")
const PopochiuAudioRow = preload(
"res://addons/popochiu/editor/main_dock/popochiu_row/audio_row/popochiu_audio_row.gd"
)
var last_played: Control = null
var last_selected: Control = null
# Uses the path to an audio file as the key, and the PopochiuAudioRow created for the
# PopochiuAudioCue linked to that audio file as the value.
var _audio_files_in_group := {}
# Uses the path to an audio file as the key, and the PopochiuAudioRow created for that file as the
# value.
var _audio_files_to_assign := {}
var _audio_cues_to_create := []
var _created_audio_cues := 0
var _wavs_to_reimport := []
@onready var _asp: AudioStreamPlayer = $AudioStreamPlayer
@onready var _btn_scan_files: Button = %BtnScanAudioFiles
@onready var unassigned_group: PopochiuGroup = %UnassignedGroup
@onready var _groups := {
PopochiuResources.AudioTypes.MUSIC : {
array = "mx_cues",
group = %MusicGroup
},
PopochiuResources.AudioTypes.SOUND_EFFECT : {
array = "sfx_cues",
group = %SFXGroup
},
PopochiuResources.AudioTypes.VOICE : {
array = "vo_cues",
group = %VoiceGroup
},
PopochiuResources.AudioTypes.UI : {
array = "ui_cues",
group = %UIGroup
}
}
#region Godot ######################################################################################
func _ready() -> void:
$PopochiuFilter.groups = _groups
_btn_scan_files.icon = get_theme_icon("Search", "EditorIcons")
# Connect to children's signals
_btn_scan_files.pressed.connect(search_audio_files)
# Connect to helpers' signals
PopochiuEditorHelper.signal_bus.audio_cues_deleted.connect(delete_rows)
#endregion
#region Public #####################################################################################
func fill_data() -> void:
# Connect to Editor signals
EditorInterface.get_resource_filesystem().sources_changed.connect(_on_sources_changed)
# Look for audio files without AudioCue
_put_audio_cues_in_group()
search_audio_files()
func search_audio_files() -> void:
var fs_directory: EditorFileSystemDirectory =\
EditorInterface.get_resource_filesystem().get_filesystem_path(SEARCH_PATH)
if not fs_directory:
return
_read_directory(fs_directory)
if _audio_cues_to_create.is_empty():
return
var progress_dialog := await PopochiuEditorHelper.show_progress()
progress_dialog.label.text = "Creating PopochiuAudioCues..."
progress_dialog.progress_bar.max_value = _audio_cues_to_create.size()
EditorInterface.get_resource_filesystem().sources_changed.disconnect(_on_sources_changed)
_created_audio_cues = 0
for arr in _audio_cues_to_create:
await _create_audio_cue(arr[0], arr[1])
progress_dialog.progress_bar.value = _created_audio_cues
_put_audio_cues_in_group()
_audio_cues_to_create.clear()
EditorInterface.get_resource_filesystem().sources_changed.connect(_on_sources_changed)
progress_dialog.close()
# Reimport WAV files so they can be changed to LOOP without the need to manually reimport them
if not _wavs_to_reimport.is_empty():
await PopochiuEditorHelper.secs_passed(0.1)
_reimport_wavs()
func delete_rows(filepaths: Array) -> void:
for filepath in filepaths:
if filepath in _audio_files_to_assign:
_audio_files_to_assign[filepath].free()
_audio_files_to_assign.erase(filepath)
elif filepath in _audio_files_in_group:
_audio_files_in_group[filepath].free()
_audio_files_in_group.erase(filepath)
#endregion
#region Private ####################################################################################
func _on_sources_changed(exist: bool) -> void:
# Look popochiu_data.cfg for PopochiuAudioCue files that don't exist in the project anymore
await _delete_rows_without_audio_cue()
search_audio_files()
func _delete_rows_without_audio_cue() -> void:
for key: int in _groups:
var group: String = _groups[key].array
var group_data: Array = PopochiuResources.get_data_value("audio", group, [])
if group_data.is_empty():
continue
group_data = group_data.filter(
func (resource_path: String) -> bool:
if FileAccess.file_exists(resource_path):
return true
var audio_cue_name: String = resource_path.get_file().get_basename()
var popochiu_group: PopochiuGroup = _groups[key].group
popochiu_group.remove_by_name(audio_cue_name)
# Fix #59 : remove the AudioCue from the A singleton
PopochiuResources.remove_audio_autoload(group, audio_cue_name, resource_path)
return false
)
if group_data.is_empty():
PopochiuResources.erase_data_value("audio", group)
else:
group_data.sort_custom(
func (a: String, b: String) -> bool:
return PopochiuUtils.sort_by_file_name(a, b)
)
PopochiuResources.set_data_value("audio", group, group_data)
await get_tree().process_frame
# Remove freed objects in _audio_files_in_group
var to_erase := []
for key: String in _audio_files_in_group:
if not _audio_files_in_group[key] or not is_instance_valid(_audio_files_in_group[key]):
to_erase.append(key)
for key in to_erase:
_audio_files_in_group.erase(key)
func _put_audio_cues_in_group() -> void:
# Put already loaded (in popochiu_data.cfg) PopochiuAudioCues into their corresponding
# PopochiuGroup
for key: int in _groups:
var group_dic: Dictionary = _groups[key]
var group_data: Array = PopochiuResources.get_data_value("audio", group_dic.array, [])
if group_data.is_empty(): continue
for resource_path: String in group_data:
var ac: AudioCue = load(resource_path)
if (
ac.audio.resource_path in _audio_files_in_group
and is_instance_valid(_audio_files_in_group[ac.audio.resource_path])
):
# TODO: Check if the resource_path has changed
continue
var ar := _create_audio_cue_row(ac)
ar.cue_group = group_dic.array
(group_dic.group as PopochiuGroup).add(ar, true)
_audio_files_in_group[ac.audio.resource_path] = ar
func _create_audio_cue_row(audio_cue: AudioCue) -> HBoxContainer:
var ar: HBoxContainer = POPOCHIU_AUDIO_ROW_SCENE.instantiate()
ar.name = audio_cue.resource_name
ar.path = audio_cue.resource_path
ar.audio_cue = audio_cue
ar.audio_tab = self
ar.stream_player = _asp
ar.deleted.connect(_audio_cue_deleted)
ar.clicked.connect(_on_row_clicked)
return ar
func _create_audio_file_row(file_path: String) -> void:
var ar: HBoxContainer = POPOCHIU_AUDIO_ROW_SCENE.instantiate()
ar.name = file_path.get_file().get_basename()
ar.path = file_path
ar.file_name = file_path.get_file()
ar.audio_tab = self
ar.stream_player = _asp
ar.group_selected.connect(_create_audio_cue.bind(file_path, ar))
ar.clicked.connect(_on_row_clicked)
unassigned_group.add(ar, true)
_audio_files_to_assign[file_path] = ar
func _read_directory(dir: EditorFileSystemDirectory) -> void:
if not dir: return
if dir.get_subdir_count():
for d in dir.get_subdir_count():
# Look out sub directories
_read_directory(dir.get_subdir(d))
# Look out the directory files
_read_files(dir)
else:
_read_files(dir)
func _read_files(dir: EditorFileSystemDirectory) -> void:
for idx in dir.get_file_count():
var file_name = dir.get_file(idx)
if not file_name.get_extension() in AUDIO_FILE_EXTENSIONS:
continue
if dir.get_file_path(idx) in _audio_files_in_group\
or dir.get_file_path(idx) in _audio_files_to_assign:
# Don't put in the list an audio file already assigned to a PopochiuAudioCue in
# popochiu_data.cfg
continue
# Check if the file prefix matches any of the prefixes defined to automatically assign it to
# a group
var target := PopochiuResources.AudioTypes.NONE
var prefix := file_name.get_slice(PopochiuConfig.get_prefix_character(), 0)
if prefix in PopochiuConfig.get_music_prefixes():
target = PopochiuResources.AudioTypes.MUSIC
elif prefix in PopochiuConfig.get_sound_effect_prefixes():
target = PopochiuResources.AudioTypes.SOUND_EFFECT
elif prefix in PopochiuConfig.get_voice_prefixes():
target = PopochiuResources.AudioTypes.VOICE
elif prefix in PopochiuConfig.get_ui_prefixes():
target = PopochiuResources.AudioTypes.UI
if target != PopochiuResources.AudioTypes.NONE:
_audio_cues_to_create.append([target, dir.get_file_path(idx)])
else:
# Put the file in the Unassigned group so devs can manually choose the group to which
# the audio file should be assigned
_create_audio_file_row(dir.get_file_path(idx))
func _create_audio_cue(type: int, path: String, audio_row: Container = null) -> void:
# Check if the audio file is a WAV file so its LoopMode is set properly
var stream: AudioStream = load(path)
if stream is AudioStreamWAV:
_wavs_to_reimport.append({
stream = stream,
type = type
})
var cue_name := path.get_file().get_basename()
var cue_file_name := cue_name
cue_file_name += ".tres"
# Create the AudioCue and save it in the file system
var ac: AudioCue
match type:
PopochiuResources.AudioTypes.MUSIC:
ac = AudioCueMusic.new()
ac.loop = true
_:
ac = AudioCueSound.new()
ac.audio = stream
ac.resource_name = cue_name.to_lower()
var error: int = ResourceSaver.save(ac, "%s/%s" % [path.get_base_dir(), cue_file_name])
assert(error == OK, "[Popochiu] Couldn't create PopochiuAudioCue: %s" % cue_file_name)
var res: AudioCue = load("%s/%s" % [path.get_base_dir(), cue_file_name])
var target := ""
match type:
PopochiuResources.AudioTypes.MUSIC:
target = "mx_cues"
PopochiuResources.AudioTypes.SOUND_EFFECT:
target = "sfx_cues"
PopochiuResources.AudioTypes.VOICE:
target = "vo_cues"
PopochiuResources.AudioTypes.UI:
target = "ui_cues"
var target_data: Array = PopochiuResources.get_data_value("audio", target, [])
if not target_data.has(res.resource_path):
target_data.append(res.resource_path)
target_data.sort_custom(
func (a: String, b: String) -> bool:
return PopochiuUtils.sort_by_file_name(a, b)
)
PopochiuResources.set_data_value("audio", target, target_data)
else:
await PopochiuEditorHelper.frame_processed()
return
await PopochiuEditorHelper.secs_passed(0.1)
# Add the AudioCue to the A singleton ----------------------------------------------------------
PopochiuResources.update_autoloads(true)
# Check if the AudioCue was created when assigning the audio file from the "Not assigned" group
if is_instance_valid(audio_row):
# Delete the file row
_audio_files_to_assign.erase(path)
audio_row.queue_free()
# Put the row in its corresponding group
_put_audio_cues_in_group()
else:
_created_audio_cues += 1
func _audio_cue_deleted(file_path: String) -> void:
_audio_files_in_group.erase(file_path)
func _on_row_clicked(row: HBoxContainer) -> void:
if is_instance_valid(last_selected):
last_selected.deselect()
last_selected = row
## Reimport WAV files so they can be changed to LOOP without the need to manually reimport them.
func _reimport_wavs() -> void:
var streams_to_reimport := _wavs_to_reimport.filter(
func (stream_dic: Dictionary):
return _change_wav_loop_mode(stream_dic.stream)
)
EditorInterface.get_resource_filesystem().reimport_files(PackedStringArray(
streams_to_reimport.map(
func (stream_dic: Dictionary) -> String:
return stream_dic.stream.resource_path
)))
await PopochiuEditorHelper.filesystem_scanned()
for stream_dic: Dictionary in streams_to_reimport:
var stream: AudioStreamWAV = stream_dic.stream
var type: PopochiuResources.AudioTypes = stream_dic.type
stream.loop_mode = (
AudioStreamWAV.LOOP_FORWARD if type == PopochiuResources.AudioTypes.MUSIC
else AudioStreamWAV.LOOP_DISABLED
)
_wavs_to_reimport.clear()
func _change_wav_loop_mode(audio_stream: AudioStreamWAV) -> bool:
var import_path := audio_stream.resource_path + ".import"
if not FileAccess.file_exists(import_path):
PopochiuUtils.print_warning(
"[b]%s[/b]" % audio_stream.resource_name \
+ " does not have the correct metadata to loop, please reimport the file" \
+ " by setting its Loop Mode to Forward."
)
return false
var config := ConfigFile.new()
var err := config.load(import_path)
if err != OK:
PopochiuUtils.print_error("Couldn't open %s to change its Loop mode." % audio_stream)
return false
if config.get_value("params", "edit/loop_mode", 0) != 0:
return false
config.set_value("params", "edit/loop_mode", 1 + AudioStreamWAV.LOOP_FORWARD)
config.save(import_path)
return true
#endregion

View file

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

View file

@ -0,0 +1,141 @@
[gd_scene load_steps=15 format=3 uid="uid://bpj8jlet25coy"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/tab_audio/tab_audio.gd" id="1_u4f8v"]
[ext_resource type="PackedScene" uid="uid://b55ialbvpilxv" path="res://addons/popochiu/editor/main_dock/popochiu_group/popochiu_group.tscn" id="2"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_filter.gd" id="2_1v1d0"]
[ext_resource type="Texture2D" uid="uid://d1dnmfkhscb7r" path="res://addons/popochiu/icons/music.png" id="3_uojli"]
[ext_resource type="Texture2D" uid="uid://cfh1uxtaff0ks" path="res://addons/popochiu/icons/sfx.png" id="4_xdj1c"]
[ext_resource type="Texture2D" uid="uid://6ewpl4v0td2h" path="res://addons/popochiu/icons/voice.png" id="5_jptq2"]
[ext_resource type="Texture2D" uid="uid://528j2rksws2c" path="res://addons/popochiu/icons/ui.png" id="6_a24xe"]
[sub_resource type="Image" id="Image_i4bix"]
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_jd5m0"]
image = SubResource("Image_i4bix")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gdosa"]
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_qmbvx"]
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_4uhm3"]
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_p4efq"]
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_j1gb1"]
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="TabAudio" type="VBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource("1_u4f8v")
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
[node name="BtnScanAudioFiles" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
text = "Scan audio files"
icon = SubResource("ImageTexture_jd5m0")
[node name="PopochiuFilter" type="LineEdit" parent="."]
layout_mode = 2
placeholder_text = "Filter Popochiu objects"
clear_button_enabled = true
right_icon = SubResource("ImageTexture_jd5m0")
script = ExtResource("2_1v1d0")
[node name="ScrollContainer" type="ScrollContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="UnassignedGroup" parent="ScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_gdosa")
title = "Unassigned"
can_create = false
[node name="MusicGroup" parent="ScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_qmbvx")
icon = ExtResource("3_uojli")
title = "Music"
can_create = false
[node name="SFXGroup" parent="ScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_4uhm3")
icon = ExtResource("4_xdj1c")
title = "Sound effects"
can_create = false
[node name="VoiceGroup" parent="ScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_p4efq")
icon = ExtResource("5_jptq2")
title = "Voices"
can_create = false
[node name="UIGroup" parent="ScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_j1gb1")
icon = ExtResource("6_a24xe")
title = "Graphic interface"
can_create = false

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")]

View file

@ -0,0 +1,208 @@
@tool
extends VBoxContainer
## Acts like a HUD for working with Popochiu objects: Rooms, Characters, Inventory items, and Dialog
## trees.
const OBJECT_ROW_FOLDER = "res://addons/popochiu/editor/main_dock/popochiu_row/object_row/"
const POPOCHIU_OBJECT_ROW_SCENE = preload(OBJECT_ROW_FOLDER + "popochiu_object_row.tscn")
const POPOCHIU_ROOM_ROW_SCENE = preload(OBJECT_ROW_FOLDER + "room_row/popochiu_room_row.tscn")
const PopochiuObjectRow := preload(OBJECT_ROW_FOLDER + "popochiu_object_row.gd")
const PopochiuCharacterRow = preload(OBJECT_ROW_FOLDER + "character_row/popochiu_character_row.gd")
const PopochiuInventoryItemRow = preload(
OBJECT_ROW_FOLDER + "inventory_item_row/popochiu_inventory_item_row.gd"
)
const PopochiuDialogRow = preload(OBJECT_ROW_FOLDER + "dialog_row/popochiu_dialog_row.gd")
var last_selected: PopochiuObjectRow = null
var _rows_paths := []
var _has_data := false
@onready var _types := {
PopochiuResources.Types.ROOM: {
path = PopochiuResources.ROOMS_PATH,
group = find_child("RoomsGroup"),
popup = PopochiuEditorHelper.CREATE_ROOM,
scene = PopochiuResources.ROOMS_PATH.path_join("%s/room_%s.tscn")
},
PopochiuResources.Types.CHARACTER: {
path = PopochiuResources.CHARACTERS_PATH,
group = find_child("CharactersGroup"),
popup = PopochiuEditorHelper.CREATE_CHARACTER,
scene = PopochiuResources.CHARACTERS_PATH.path_join("%s/character_%s.tscn")
},
PopochiuResources.Types.INVENTORY_ITEM: {
path = PopochiuResources.INVENTORY_ITEMS_PATH,
group = find_child("ItemsGroup"),
popup = PopochiuEditorHelper.CREATE_INVENTORY_ITEM,
scene = PopochiuResources.INVENTORY_ITEMS_PATH.path_join("%s/inventory_item_%s.tscn")
},
PopochiuResources.Types.DIALOG: {
path = PopochiuResources.DIALOGS_PATH,
group = find_child("DialogsGroup"),
popup = PopochiuEditorHelper.CREATE_DIALOG,
scene = PopochiuResources.DIALOGS_PATH.path_join("%s/dialog_%s.tres")
}
}
#region Godot ######################################################################################
func _ready() -> void:
$PopochiuFilter.groups = _types
for t in _types.values():
t.group.create_clicked.connect(PopochiuEditorHelper.show_creation_popup.bind(t.popup))
# Connect to helper signals
PopochiuEditorHelper.signal_bus.main_scene_changed.connect(_set_main_scene)
PopochiuEditorHelper.signal_bus.pc_changed.connect(_set_pc)
PopochiuEditorHelper.signal_bus.main_object_added.connect(_add_to_list)
#endregion
#region Public #####################################################################################
func fill_data() -> void:
# Search the FileSystem for Rooms, Characters, InventoryItems and Dialogs
for type_key: int in _types:
var resources := Array(DirAccess.get_directories_at(_types[type_key].path)).map(
_get_popochiu_objects_resources.bind(type_key)
)
for resource: Resource in resources:
_create_row(type_key, resource)
func check_data() -> void:
if not _has_data:
# Try to load the Main tab data in case they couldn't be loaded while
# opening the engine
fill_data()
#endregion
#region Private ####################################################################################
func _set_main_scene(path: String) -> void:
ProjectSettings.set_setting(PopochiuResources.MAIN_SCENE, path)
assert(
ProjectSettings.save() == OK,
"[Popochiu] Couldn't set %s as the Main Scene in Project Settings" % path
)
_types[PopochiuResources.Types.ROOM].group.clear_favs()
func _set_pc(script_name: String) -> void:
if PopochiuResources.get_data_value("setup", "pc", "") == script_name:
return
assert(
PopochiuResources.set_data_value("setup", "pc", script_name) == OK,
"[Popochiu] Couldn't set %s as the Player-controlled Character (PC)" % script_name
)
var characters_group: PopochiuGroup = _types[PopochiuResources.Types.CHARACTER].group
characters_group.clear_favs()
(characters_group.get_by_name(script_name) as PopochiuCharacterRow).is_pc = true
func _add_to_list(type: int, name_to_add: String) -> PopochiuObjectRow:
var row := _create_object_row(type, name_to_add)
_types[type].group.add(row)
return row
func _get_popochiu_objects_resources(
dir_name: String, type_key: PopochiuResources.Types
) -> Resource:
var resource_filesystem := EditorInterface.get_resource_filesystem()
var dir_path := (_types[type_key].path as String).path_join(dir_name)
for file_name: String in DirAccess.get_files_at(dir_path):
if file_name.get_extension() != "tres": continue
var resource: Resource = load(dir_path.path_join(file_name))
if (
resource is PopochiuRoomData
or resource is PopochiuCharacterData
or resource is PopochiuInventoryItemData
or resource is PopochiuDialog
):
return resource
PopochiuUtils.print_error("No data file (.tres) found for [b]%s[/b]" % dir_path)
return null
func _create_row(type_key: int, resource: Resource) -> void:
if _types[type_key].scene.replace("%s", resource.resource_name) in _rows_paths: return
var row: PopochiuObjectRow = _create_object_row(type_key, resource.script_name)
_types[type_key].group.add(row)
# Check if the object in the list is in its corresponding array in Popochiu (Popochiu.tscn)
var is_in_core := true
var has_state_script: bool = FileAccess.file_exists(row.path.replace(".tscn", "_state.gd"))
match type_key:
PopochiuResources.Types.ROOM:
is_in_core = PopochiuResources.has_data_value("rooms", resource.script_name)
# Check if the room is the main scene
var main_scene: String = ProjectSettings.get_setting(PopochiuResources.MAIN_SCENE)
if main_scene == resource.scene:
row.is_main = true
PopochiuResources.Types.CHARACTER:
is_in_core = PopochiuResources.has_data_value("characters", resource.script_name)
if resource.script_name == PopochiuResources.get_data_value("setup", "pc", ""):
row.is_pc = true
PopochiuResources.Types.INVENTORY_ITEM:
is_in_core = PopochiuResources.has_data_value("inventory_items", resource.script_name)
var items: Array = PopochiuConfig.get_inventory_items_on_start()
if resource.script_name in items:
row.is_on_start = true
PopochiuResources.Types.DIALOG:
is_in_core = PopochiuResources.has_data_value("dialogs", resource.script_name)
if not is_in_core:
row.show_as_not_in_core()
func _create_object_row(type: int, name_to_add: String) -> PopochiuObjectRow:
var new_obj: PopochiuObjectRow = null
match type:
PopochiuResources.Types.ROOM:
new_obj = POPOCHIU_ROOM_ROW_SCENE.instantiate()
PopochiuResources.Types.CHARACTER:
new_obj = POPOCHIU_OBJECT_ROW_SCENE.instantiate()
new_obj.set_script(PopochiuCharacterRow)
PopochiuResources.Types.INVENTORY_ITEM:
new_obj = POPOCHIU_OBJECT_ROW_SCENE.instantiate()
new_obj.set_script(PopochiuInventoryItemRow)
PopochiuResources.Types.DIALOG:
new_obj = POPOCHIU_OBJECT_ROW_SCENE.instantiate()
new_obj.set_script(PopochiuDialogRow)
new_obj.name = name_to_add
new_obj.type = type
new_obj.path = _types[type].scene.replace("%s", name_to_add.to_snake_case())
new_obj.clicked.connect(_select_object)
_rows_paths.append(new_obj.path)
_has_data = true
return new_obj
func _select_object(por: PopochiuObjectRow) -> void:
if last_selected and last_selected != por:
last_selected.deselect()
last_selected = por
#endregion

View file

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

View file

@ -0,0 +1,118 @@
[gd_scene load_steps=14 format=3 uid="uid://bynwdds8o3tcx"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_filter.gd" id="1_akrwb"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/tab_main/tab_main.gd" id="1_jdtyo"]
[ext_resource type="PackedScene" uid="uid://b55ialbvpilxv" path="res://addons/popochiu/editor/main_dock/popochiu_group/popochiu_group.tscn" id="2_71uuj"]
[ext_resource type="Texture2D" uid="uid://cec7vj2roo7ef" path="res://addons/popochiu/icons/room.png" id="3_v0n5j"]
[ext_resource type="Texture2D" uid="uid://mir6j58lju3l" path="res://addons/popochiu/icons/character.png" id="4_q3ysu"]
[ext_resource type="Texture2D" uid="uid://dxtuplm5v6w33" path="res://addons/popochiu/icons/inventory_item.png" id="5_h6p8m"]
[ext_resource type="Texture2D" uid="uid://bb53j2q1cm45l" path="res://addons/popochiu/icons/dialog.png" id="6_y67sq"]
[sub_resource type="Image" id="Image_vdhps"]
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_c80ss"]
image = SubResource("Image_vdhps")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_q8xlx"]
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.439216, 0.427451, 0.921569, 0.74902)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_r2ioy"]
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.556863, 0.313726, 0.160784, 0.74902)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_odbd1"]
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.337255, 0.67451, 0.301961, 0.74902)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_wku8y"]
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.556863, 0.235294, 0.592157, 0.74902)
[node name="Main" type="VBoxContainer"]
size_flags_horizontal = 3
size_flags_vertical = 3
focus_mode = 2
script = ExtResource("1_jdtyo")
metadata/_tab_index = 0
[node name="PopochiuFilter" type="LineEdit" parent="."]
layout_mode = 2
placeholder_text = "Filter Popochiu objects"
clear_button_enabled = true
right_icon = SubResource("ImageTexture_c80ss")
script = ExtResource("1_akrwb")
[node name="MainScrollContainer" type="ScrollContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
follow_focus = true
[node name="VBoxContainer" type="VBoxContainer" parent="MainScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="RoomsGroup" parent="MainScrollContainer/VBoxContainer" instance=ExtResource("2_71uuj")]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_q8xlx")
icon = ExtResource("3_v0n5j")
color = Color(0.439216, 0.427451, 0.921569, 0.74902)
title = "Rooms"
create_text = "Create room"
[node name="CharactersGroup" parent="MainScrollContainer/VBoxContainer" instance=ExtResource("2_71uuj")]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_r2ioy")
icon = ExtResource("4_q3ysu")
color = Color(0.556863, 0.313726, 0.160784, 0.74902)
title = "Characters"
create_text = "Create character"
[node name="ItemsGroup" parent="MainScrollContainer/VBoxContainer" instance=ExtResource("2_71uuj")]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_odbd1")
icon = ExtResource("5_h6p8m")
color = Color(0.337255, 0.67451, 0.301961, 0.74902)
title = "Inventory items"
create_text = "Create inventory item"
[node name="DialogsGroup" parent="MainScrollContainer/VBoxContainer" instance=ExtResource("2_71uuj")]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_wku8y")
icon = ExtResource("6_y67sq")
color = Color(0.556863, 0.235294, 0.592157, 0.74902)
title = "Dialog trees"
create_text = "Create dialog tree"

View file

@ -0,0 +1,405 @@
@tool
extends VBoxContainer
## Handles the Room tab in Popochiu's dock
const OBJECT_ROW_FOLDER = "res://addons/popochiu/editor/main_dock/popochiu_row/object_row/"
const POPOCHIU_OBJECT_ROW_SCENE = preload(OBJECT_ROW_FOLDER + "popochiu_object_row.tscn")
const PopochiuRoomObjectRow = preload(
"res://addons/popochiu/editor/main_dock/popochiu_row/object_row/" +
"room_object_row/popochiu_room_object_row.gd"
)
var opened_room: PopochiuRoom = null
var opened_room_state_path: String = ""
var _rows_paths := []
var _last_selected: PopochiuRoomObjectRow = null
var _characters_in_room := []
var _btn_add_character: MenuButton
var _delete_dialog: PopochiuEditorHelper.DeleteConfirmation
@onready var _types: Dictionary = {
PopochiuResources.Types.PROP: {
group = %PropsGroup as PopochiuGroup,
popup = PopochiuEditorHelper.CREATE_PROP,
method = "get_props",
type_class = PopochiuProp,
parent = "Props"
},
PopochiuResources.Types.HOTSPOT: {
group = %HotspotsGroup as PopochiuGroup,
popup = PopochiuEditorHelper.CREATE_HOTSPOT,
method = "get_hotspots",
type_class = PopochiuHotspot,
parent = "Hotspots"
},
PopochiuResources.Types.REGION: {
group = %RegionsGroup as PopochiuGroup,
popup = PopochiuEditorHelper.CREATE_REGION,
method = "get_regions",
type_class = PopochiuRegion,
parent = "Regions"
},
PopochiuResources.Types.MARKER: {
group = %MarkersGroup as PopochiuGroup,
popup = PopochiuEditorHelper.CREATE_MARKER,
method = "get_markers",
type_class = Marker2D,
parent = "Markers"
},
PopochiuResources.Types.WALKABLE_AREA: {
group = %WalkableAreasGroup as PopochiuGroup,
popup = PopochiuEditorHelper.CREATE_WALKABLE_AREA,
method = "get_walkable_areas",
type_class = PopochiuWalkableArea,
parent = "WalkableAreas"
},
PopochiuResources.Types.CHARACTER: {
group = %CharactersGroup as PopochiuGroup,
method = "get_characters",
type_class = PopochiuCharacter,
parent = "Characters"
}
}
@onready var popochiu_filter: LineEdit = %PopochiuFilter
@onready var room_name: Button = %RoomName
@onready var no_room_info: Label = %NoRoomInfo
@onready var tool_buttons: HBoxContainer = %ToolButtons
@onready var btn_script: Button = %BtnScript
@onready var btn_resource: Button = %BtnResource
@onready var btn_resource_script: Button = %BtnResourceScript
#region Godot ######################################################################################
func _ready() -> void:
popochiu_filter.groups = _types
# Setup the button that will allow to add characters to the room
_btn_add_character = MenuButton.new()
_btn_add_character.text = "Add character to room"
_btn_add_character.icon = get_theme_icon("Add", "EditorIcons")
_btn_add_character.flat = false
_btn_add_character.size_flags_horizontal = SIZE_SHRINK_END
_btn_add_character.add_theme_stylebox_override("normal", get_theme_stylebox("normal", "Button"))
_btn_add_character.add_theme_stylebox_override("hover", get_theme_stylebox("hover", "Button"))
_btn_add_character.add_theme_stylebox_override(
"pressed", get_theme_stylebox("pressed", "Button")
)
_btn_add_character.about_to_popup.connect(_on_add_character_pressed)
_types[PopochiuResources.Types.CHARACTER].group.add_header_button(_btn_add_character)
# Disable all buttons by default until a PopochiuRoom is opened in the editor
room_name.hide()
popochiu_filter.hide()
no_room_info.show()
tool_buttons.hide()
btn_script.icon = get_theme_icon("Script", "EditorIcons")
btn_resource.icon = get_theme_icon("Object", "EditorIcons")
btn_resource_script.icon = get_theme_icon("GDScript", "EditorIcons")
room_name.pressed.connect(_select_file)
btn_script.pressed.connect(_open_script)
btn_resource.pressed.connect(_edit_resource)
btn_resource_script.pressed.connect(_open_resource_script)
for t in _types.values():
t.group.disable_create()
if t.has("popup"):
t.group.create_clicked.connect(PopochiuEditorHelper.show_creation_popup.bind(t.popup))
#endregion
#region Public #####################################################################################
func scene_changed(scene_root: Node) -> void:
# Set the default tab state
if is_instance_valid(opened_room):
await _clear_content()
if not scene_root is PopochiuRoom:
return
if scene_root is PopochiuRoom and scene_root.script_name.is_empty():
PopochiuUtils.print_error("This room doesn't have a [code]script_name[/code] value!")
return
if opened_room == scene_root:
return
# Updated the opened room's info
opened_room = scene_root
opened_room_state_path = PopochiuResources.get_data_value(
"rooms", opened_room.script_name, ""
)
if not PopochiuEditorHelper.undo_redo.history_changed.is_connected(_check_undoredo_history):
PopochiuEditorHelper.undo_redo.history_changed.connect(_check_undoredo_history)
room_name.text = opened_room.script_name
room_name.show()
tool_buttons.show()
popochiu_filter.show()
_btn_add_character.disabled = false
# Fill info of Props, Hotspots, Walkable areas, Regions and Points
for type_id in _types:
for child in opened_room.call(_types[type_id].method):
_create_row_in_dock(type_id, child)
_types[type_id].group.enable_create()
# Listen to node additions/deletions in container nodes
var container: Node2D = opened_room.get_node(_types[type_id].parent)
container.child_entered_tree.connect(_on_child_added.bind(type_id))
container.child_exiting_tree.connect(_on_child_removed.bind(type_id))
no_room_info.hide()
get_parent().current_tab = 1
func scene_closed(filepath: String) -> void:
if is_instance_valid(opened_room) and opened_room.scene_file_path == filepath:
_clear_content()
#endregion
#region Private ####################################################################################
func _clear_content() -> void:
for type_id in _types:
var container: Node2D = opened_room.get_node(_types[type_id].parent)
if container.child_entered_tree.is_connected(_on_child_added):
container.child_entered_tree.disconnect(_on_child_added)
if container.child_exiting_tree.is_connected(_on_child_removed):
container.child_exiting_tree.disconnect(_on_child_removed)
if PopochiuEditorHelper.undo_redo.history_changed.is_connected(_check_undoredo_history):
PopochiuEditorHelper.undo_redo.history_changed.disconnect(_check_undoredo_history)
opened_room = null
opened_room_state_path = ""
_characters_in_room.clear()
_rows_paths.clear()
room_name.hide()
tool_buttons.hide()
popochiu_filter.hide()
no_room_info.show()
if is_instance_valid(_last_selected):
_last_selected.deselect()
_last_selected = null
for t: Dictionary in _types.values():
t.group.clear_list()
t.group.disable_create()
_btn_add_character.disabled = true
await get_tree().process_frame
func _create_object_row(
type: int, node_name: String, path := "", node_path := ""
) -> PopochiuRoomObjectRow:
var object_row_instance := POPOCHIU_OBJECT_ROW_SCENE.instantiate()
object_row_instance.set_script(PopochiuRoomObjectRow)
var new_obj: PopochiuRoomObjectRow = object_row_instance
new_obj.name = node_name
new_obj.type = type
new_obj.path = path
new_obj.node_path = node_path
new_obj.clicked.connect(_select_in_tree)
_rows_paths.append("%s/%d/%s" % [opened_room.script_name, type, node_name])
return new_obj
func _select_in_tree(por: PopochiuRoomObjectRow) -> void:
if _last_selected and _last_selected != por:
_last_selected.deselect()
if is_instance_valid(opened_room):
var node := opened_room.get_node("%s/%s" % [_types[por.type].parent, por.node_path])
PopochiuEditorHelper.select_node(node)
_last_selected = por
func _select_file() -> void:
EditorInterface.select_file(opened_room.scene_file_path)
func _open_script() -> void:
EditorInterface.select_file(opened_room.get_script().resource_path)
EditorInterface.set_main_screen_editor("Script")
EditorInterface.edit_script(opened_room.get_script())
func _edit_resource() -> void:
EditorInterface.select_file(opened_room_state_path)
EditorInterface.edit_resource(load(opened_room_state_path))
func _open_resource_script() -> void:
var prd: PopochiuRoomData = load(opened_room_state_path)
EditorInterface.select_file(prd.get_script().resource_path)
EditorInterface.set_main_screen_editor("Script")
EditorInterface.edit_resource(prd.get_script())
# Removes the character from the room
func _on_remove_character_pressed(row: PopochiuRoomObjectRow) -> void:
_delete_dialog = PopochiuEditorHelper.DELETE_CONFIRMATION_SCENE.instantiate()
_delete_dialog.title = "Remove character in room"
_delete_dialog.message = "Are you sure you want to remove [b]%s[/b] from this room?" % row.name
_delete_dialog.on_confirmed = _on_remove_character_confirmed.bind(row)
PopochiuEditorHelper.show_delete_confirmation(_delete_dialog)
func _on_remove_character_confirmed(row: PopochiuRoomObjectRow) -> void:
_characters_in_room.erase(str(row.name))
opened_room.get_node("Characters").get_node("Character%s *" % row.name).queue_free()
row.queue_free()
EditorInterface.save_scene()
# Fills the list to show after pressing "+ Add character to room" and listens to selections to add
# the clicked character to the room
func _on_add_character_pressed() -> void:
var characters_menu := _btn_add_character.get_popup()
characters_menu.clear()
var idx := 0
for key in PopochiuResources.get_section_keys("characters"):
characters_menu.add_item(key, idx)
characters_menu.set_item_disabled(idx, _characters_in_room.has(key))
idx += 1
if not characters_menu.id_pressed.is_connected(_on_character_selected):
characters_menu.id_pressed.connect(_on_character_selected)
# Adds the clicked character in the "+ Add character to room" menu to the
# current room
func _on_character_selected(id: int) -> void:
var characters_menu := _btn_add_character.get_popup()
var char_name := characters_menu.get_item_text(
characters_menu.get_item_index(id)
)
var instance: PopochiuCharacter = (load(
"res://game/characters/%s/character_%s.tscn".replace("%s", char_name.to_snake_case())
) as PackedScene).instantiate(PackedScene.GEN_EDIT_STATE_INSTANCE)
opened_room.get_node("Characters").add_child(instance)
instance.owner = opened_room
EditorInterface.save_scene()
PopochiuEditorHelper.select_node(instance)
## Called when a [param child] is added to the room's tree without using the Popochiu dock.
## [param type_id] can be used to classify the object (prop, hotspot, etc.).
func _create_row_in_dock(type_id: int, child: Node) -> PopochiuRoomObjectRow:
var row: PopochiuRoomObjectRow = null
if child is PopochiuCharacter:
# Get the script_name of the character
var char_name: String = child.name.trim_prefix("Character").rstrip(" *")
_characters_in_room.append(char_name)
# Create the row for the character
row = _create_object_row(
type_id,
char_name,
"res://game/characters/%s/character_%s.tscn".replace("%s", char_name.to_snake_case()),
child.name
)
row.is_menu_hidden = true
_types[type_id].group.add(row)
# Create button to remove the character from the room
var remove_btn := Button.new()
remove_btn.icon = get_theme_icon("Remove", "EditorIcons")
remove_btn.tooltip_text = "Remove character from room"
remove_btn.flat = true
remove_btn.pressed.connect(_on_remove_character_pressed.bind(row))
row.add_button(remove_btn)
elif is_instance_of(child, _types[type_id].type_class):
var row_path := _get_row_path(type_id, child)
if row_path in _rows_paths: return
var node_path := _get_node_path(type_id, child)
row = _create_object_row(type_id, child.name, row_path, node_path)
_types[type_id].group.add(row)
return row
func _get_row_path(type_id: int, child: Node) -> String:
var row_path := child.scene_file_path
if row_path.is_empty() and child.script and not "addons" in child.script.resource_path:
row_path = child.script.resource_path
return row_path
func _get_node_path(type_id: int, child: Node) -> String:
return String(child.get_path()).split("%s/" % _types[type_id].parent)[1]
func _on_child_added(node: Node, type_id: int) -> void:
_create_row_in_dock(type_id, node)
if not is_instance_of(node, _types[type_id].type_class): return
node.position = Vector2(
ProjectSettings.get_setting(PopochiuResources.DISPLAY_WIDTH),
ProjectSettings.get_setting(PopochiuResources.DISPLAY_HEIGHT)
) / 2.0
func _on_child_removed(node: Node, type_id: int) -> void:
if not is_instance_of(node, _types[type_id].type_class): return
var node_name := node.name
if node is PopochiuCharacter:
# Get the script_name of the character
node_name = node_name.lstrip("Character").rstrip(" *")
_characters_in_room.erase(str(node_name))
else:
_rows_paths.erase("%s/%d/%s" % [opened_room.script_name, type_id, node_name])
_types[type_id].group.remove_by_name(node_name)
func _check_undoredo_history() -> void:
if not opened_room or not is_instance_valid(opened_room):
return
var walkable_areas: Array = opened_room.call(
_types[PopochiuResources.Types.WALKABLE_AREA].method
)
if walkable_areas.is_empty(): return
for wa: PopochiuWalkableArea in walkable_areas:
(wa.get_node("Perimeter") as NavigationRegion2D).bake_navigation_polygon()
#endregion

View file

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

View file

@ -0,0 +1,193 @@
[gd_scene load_steps=18 format=3 uid="uid://q1bjkxavt2ay"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/tab_room/tab_room.gd" id="1_dnc56"]
[ext_resource type="PackedScene" uid="uid://b55ialbvpilxv" path="res://addons/popochiu/editor/main_dock/popochiu_group/popochiu_group.tscn" id="2"]
[ext_resource type="Script" path="res://addons/popochiu/editor/main_dock/popochiu_filter.gd" id="2_bv3t4"]
[ext_resource type="Texture2D" uid="uid://bj4bxswex7nsl" path="res://addons/popochiu/icons/prop.png" id="3_rksqc"]
[ext_resource type="Texture2D" uid="uid://jbdlyvx4gumd" path="res://addons/popochiu/icons/hotspot.png" id="4_6mx6c"]
[ext_resource type="Texture2D" uid="uid://dvh13sj4uj4b2" path="res://addons/popochiu/icons/walkable_area.png" id="5_j6ot2"]
[ext_resource type="Texture2D" uid="uid://cosxi1ulfp7rg" path="res://addons/popochiu/icons/region.png" id="6_2h2fq"]
[ext_resource type="Texture2D" uid="uid://btdsnflrn3j6o" path="res://addons/popochiu/icons/point.png" id="7_8ygji"]
[ext_resource type="Texture2D" uid="uid://mir6j58lju3l" path="res://addons/popochiu/icons/character.png" id="9_4yetu"]
[sub_resource type="Image" id="Image_xqhe0"]
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_51sph"]
image = SubResource("Image_xqhe0")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_s3433"]
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_wj0h8"]
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_m7com"]
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_b8j46"]
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_ttmyn"]
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_30r2w"]
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="TabRoom" type="VBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource("1_dnc56")
[node name="PopochiuFilter" type="LineEdit" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 2
placeholder_text = "Filter Popochiu objects"
clear_button_enabled = true
right_icon = SubResource("ImageTexture_51sph")
script = ExtResource("2_bv3t4")
[node name="RoomName" type="Button" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 2
text = "Room name"
[node name="ToolButtons" type="HBoxContainer" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 2
alignment = 1
[node name="BtnScript" type="Button" parent="ToolButtons"]
unique_name_in_owner = true
layout_mode = 2
text = "Script"
icon = SubResource("ImageTexture_51sph")
[node name="BtnResource" type="Button" parent="ToolButtons"]
unique_name_in_owner = true
layout_mode = 2
text = "State"
icon = SubResource("ImageTexture_51sph")
[node name="BtnResourceScript" type="Button" parent="ToolButtons"]
unique_name_in_owner = true
layout_mode = 2
text = "State"
icon = SubResource("ImageTexture_51sph")
[node name="RoomScrollContainer" type="ScrollContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="VBoxContainer" type="VBoxContainer" parent="RoomScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="NoRoomInfo" type="Label" parent="RoomScrollContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(312, 0)
layout_mode = 2
text = "Open a room in Main tab to see or create Props, Hotspots, Regions and Points."
autowrap_mode = 3
[node name="PropsGroup" parent="RoomScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_s3433")
icon = ExtResource("3_rksqc")
title = "Props"
create_text = "Create prop"
[node name="HotspotsGroup" parent="RoomScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_wj0h8")
icon = ExtResource("4_6mx6c")
title = "Hotspots"
create_text = "Create hotspot"
[node name="WalkableAreasGroup" parent="RoomScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_m7com")
icon = ExtResource("5_j6ot2")
title = "Walkable areas"
create_text = "Create walkable area"
[node name="RegionsGroup" parent="RoomScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_b8j46")
icon = ExtResource("6_2h2fq")
title = "Regions"
create_text = "Create regions"
[node name="MarkersGroup" parent="RoomScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_ttmyn")
icon = ExtResource("7_8ygji")
title = "Markers"
create_text = "Create marker"
[node name="CharactersGroup" parent="RoomScrollContainer/VBoxContainer" instance=ExtResource("2")]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_30r2w")
icon = ExtResource("9_4yetu")
title = "Characters in room"
can_create = false
create_text = "Add character to room"