feat: add multiple done boxes

bug: can edit the text only once for whatever reason?
This commit is contained in:
LunarAkai 2025-07-02 23:22:29 +02:00
commit 3fa14dc268
16 changed files with 215 additions and 48 deletions

7
addons/uuid/plugin.cfg Normal file
View file

@ -0,0 +1,7 @@
[plugin]
name="godot-uuid"
description="Unique identifier generation v4 for Godot Engine"
author="Binogure Studio"
version="3.0.0"
script="plugin.gd"

10
addons/uuid/plugin.gd Normal file
View file

@ -0,0 +1,10 @@
@tool
extends EditorPlugin
const AUTOLOAD_NAME = 'uuid'
func _enable_plugin() -> void:
add_autoload_singleton(AUTOLOAD_NAME, 'res://addons/uuid/uuid.gd')
func _disable_plugin() -> void:
remove_autoload_singleton(AUTOLOAD_NAME)

View file

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

113
addons/uuid/uuid.gd Normal file
View file

@ -0,0 +1,113 @@
# Note: The code might not be as pretty it could be, since it's written
# in a way that maximizes performance. Methods are inlined and loops are avoided.
extends Node
const BYTE_MASK: int = 0b11111111
static func uuidbin():
# 16 random bytes with the bytes on index 6 and 8 modified
return [
randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK,
randi() & BYTE_MASK, randi() & BYTE_MASK, ((randi() & BYTE_MASK) & 0x0f) | 0x40, randi() & BYTE_MASK,
((randi() & BYTE_MASK) & 0x3f) | 0x80, randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK,
randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK,
]
static func uuidbinrng(rng: RandomNumberGenerator):
return [
rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK,
rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, ((rng.randi() & BYTE_MASK) & 0x0f) | 0x40, rng.randi() & BYTE_MASK,
((rng.randi() & BYTE_MASK) & 0x3f) | 0x80, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK,
rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK,
]
static func v4():
# 16 random bytes with the bytes on index 6 and 8 modified
var b = uuidbin()
return '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x' % [
# low
b[0], b[1], b[2], b[3],
# mid
b[4], b[5],
# hi
b[6], b[7],
# clock
b[8], b[9],
# clock
b[10], b[11], b[12], b[13], b[14], b[15]
]
static func v4_rng(rng: RandomNumberGenerator):
# 16 random bytes with the bytes on index 6 and 8 modified
var b = uuidbinrng(rng)
return '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x' % [
# low
b[0], b[1], b[2], b[3],
# mid
b[4], b[5],
# hi
b[6], b[7],
# clock
b[8], b[9],
# clock
b[10], b[11], b[12], b[13], b[14], b[15]
]
var _uuid: Array
func _init(rng := RandomNumberGenerator.new()):
_uuid = uuidbinrng(rng)
func as_array():
return _uuid.duplicate()
func as_dict(big_endian := true):
if big_endian:
return {
"low" : (_uuid[0] << 24) + (_uuid[1] << 16) + (_uuid[2] << 8 ) + _uuid[3],
"mid" : (_uuid[4] << 8 ) + _uuid[5],
"hi" : (_uuid[6] << 8 ) + _uuid[7],
"clock": (_uuid[8] << 8 ) + _uuid[9],
"node" : (_uuid[10] << 40) + (_uuid[11] << 32) + (_uuid[12] << 24) + (_uuid[13] << 16) + (_uuid[14] << 8 ) + _uuid[15]
}
else:
return {
"low" : _uuid[0] + (_uuid[1] << 8 ) + (_uuid[2] << 16) + (_uuid[3] << 24),
"mid" : _uuid[4] + (_uuid[5] << 8 ),
"hi" : _uuid[6] + (_uuid[7] << 8 ),
"clock": _uuid[8] + (_uuid[9] << 8 ),
"node" : _uuid[10] + (_uuid[11] << 8 ) + (_uuid[12] << 16) + (_uuid[13] << 24) + (_uuid[14] << 32) + (_uuid[15] << 40)
}
func as_string():
return '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x' % [
# low
_uuid[0], _uuid[1], _uuid[2], _uuid[3],
# mid
_uuid[4], _uuid[5],
# hi
_uuid[6], _uuid[7],
# clock
_uuid[8], _uuid[9],
# node
_uuid[10], _uuid[11], _uuid[12], _uuid[13], _uuid[14], _uuid[15]
]
func is_equal(other):
# Godot Engine compares Array recursively
# There's no need for custom comparison here.
return _uuid == other._uuid

1
addons/uuid/uuid.gd.uid Normal file
View file

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

View file

@ -22,6 +22,7 @@ config/icon="res://icon.svg"
[autoload]
SignalBus="*res://src/Singletons/signal_bus.gd"
uuid="*res://addons/uuid/uuid.gd"
[display]
@ -32,6 +33,10 @@ window/size/transparent=true
window/subwindows/embed_subwindows=false
window/per_pixel_transparency/allowed=true
[editor_plugins]
enabled=PackedStringArray("res://addons/uuid/plugin.cfg")
[input]
right_click={

View file

@ -3,14 +3,16 @@ extends Node
signal on_window_closed(window: Window)
signal on_new_container_requested
signal on_entry_deleted(node: Node)
signal settings_window_closed
signal edit_window_closed
signal edit_window_requested(window: Window, text: String, edit_id: int)
signal edit_window_text_saved(window: Window, text: String, edit_id: int)
signal edit_window_requested(window: Window, text: String, node: Node)
signal edit_window_text_saved(window: Window, text: String, node: Node)
signal main_panel_color_changed(color: Color)
signal main_window_color_changed(color: Color)
signal side_panel_color_changed(color: Color)
signal on_panel_created()
signal on_panel_requested(index: int)
signal on_panel_requested(index)

View file

@ -5,7 +5,7 @@ class_name ContainerSelectionButton extends MarginContainer
@export var popup_menu: PopupMenu
@export var edit_collection_name_window: PackedScene
var button_index: int
var button_index
var instantiated_menu
# Called when the node enters the scene tree for the first time.
@ -16,9 +16,6 @@ func _enter_tree() -> void:
var text: String = "Collection %d" % button_index
button.text = text
## Request to change to a panel with the ID - 1 of the button. [br]
## Buttons are 1-indexed, while [member UIManager.panel_array] is 0-index
func _on_button_pressed() -> void:
SignalBus.on_panel_requested.emit(button_index)

View file

@ -6,14 +6,12 @@ class_name DoneBox extends HBoxContainer
@export var entry_text_box: RichTextLabel
var instantiated_menu
var id: int
var node: Node
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
options_menu.get_popup().id_pressed.connect(_on_index_pressed)
SignalBus.edit_window_text_saved.connect(on_edit_window_text_save)
SignalBus.edit_window_closed.connect(on_edit_window_closed)
SignalBus.on_window_closed.connect(on_edit_window_closed)
@ -27,16 +25,17 @@ func _on_index_pressed(index:int) -> void:
if index == 0:
instantiated_menu = edit_menu.instantiate()
add_child(instantiated_menu)
SignalBus.edit_window_requested.emit(instantiated_menu, entry_text_box.text)
SignalBus.edit_window_requested.emit(instantiated_menu, entry_text_box.text, self)
print("Node: ", node)
if index == 1:
queue_free()
func on_edit_window_text_save(window: Window, text: String, edit_id: int) -> void:
func on_edit_window_closed(window: Window) -> void:
if not is_instance_of(window, Editmenu):
return
id = edit_id
entry_text_box.text = text
func on_edit_window_closed() -> void:
instantiated_menu.queue_free()
if instantiated_menu != null:
SignalBus.on_entry_deleted.emit(self)
instantiated_menu.queue_free()

View file

@ -138,7 +138,7 @@ unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
script = ExtResource("5_05tj4")
current_active_panel = NodePath("MainPanel")
current_active_panel = NodePath("")
main_panel_scene = ExtResource("9_cqoei")
container_collection_box = NodePath("Panel/MarginContainer/ScrollContainer/ContainerBox")
container_button_scene = ExtResource("5_14o3q")
@ -215,9 +215,6 @@ icon_alignment = 1
script = ExtResource("12_g3kvb")
settings_menu = ExtResource("13_v0ovx")
[node name="MainPanel" parent="Panel/VBoxContainer/UIManager" instance=ExtResource("9_cqoei")]
layout_mode = 2
[node name="Control" type="Control" parent="."]
anchors_preset = 0
offset_right = 1183.0

View file

@ -1,18 +1,24 @@
class_name MainPanel extends ScrollContainer
const uuid_util = preload('res://addons/uuid/uuid.gd')
@export var container_name_label: RichTextLabel
@export var style_box: StyleBoxFlat
@export var panel_main_color: Color
@export var day_container: Container
var id: int = 0
@export_group("Entries")
@export var done_boxes: Array[DoneBox] = []
@export var done_box_scene: PackedScene
var id
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
panel_main_color = style_box.bg_color
create_panel_name()
SignalBus.main_panel_color_changed.connect(_on_main_panel_color_changed)
#SignalBus.edit_window_text_saved.connect(on_edit_window_text_save)
SignalBus.on_entry_deleted.connect(on_entry_deleted)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
@ -25,6 +31,17 @@ func _on_main_panel_color_changed(color: Color):
func create_panel_name() -> void:
var panel_name: String = "Container %d" % id
var panel_name: String = "Container %s" % id
container_name_label.text = panel_name
func _on_add_button_pressed() -> void:
var new_done_box: DoneBox = done_box_scene.instantiate()
done_boxes.append(new_done_box)
day_container.add_child(new_done_box)
day_container.move_child(new_done_box, -1)
print(done_boxes)
func on_entry_deleted(node: Node) -> void:
done_boxes.erase(node)

View file

@ -7,7 +7,7 @@
[ext_resource type="Texture2D" uid="uid://dof65a47bfapk" path="res://src/assets/icons/library-plus.svg" id="5_1citv"]
[ext_resource type="PackedScene" uid="uid://d1b10b44uwo8y" path="res://src/UI/done_box.tscn" id="5_bb2jg"]
[node name="MainPanel" type="ScrollContainer" node_paths=PackedStringArray("container_name_label")]
[node name="MainPanel" type="ScrollContainer" node_paths=PackedStringArray("container_name_label", "day_container")]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
@ -19,6 +19,8 @@ horizontal_scroll_mode = 0
script = ExtResource("2_5qsb6")
container_name_label = NodePath("Panel/VBoxContainer/RichTextLabel")
style_box = ExtResource("3_enj05")
day_container = NodePath("Panel/VBoxContainer/MarginContainer/VBoxContainer/DayContainer")
done_box_scene = ExtResource("5_bb2jg")
[node name="Panel" type="Panel" parent="."]
layout_mode = 2
@ -85,9 +87,6 @@ layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 10
[node name="DoneBox" parent="Panel/VBoxContainer/MarginContainer/VBoxContainer/DayContainer" instance=ExtResource("5_bb2jg")]
layout_mode = 2
[node name="Button" type="Button" parent="Panel/VBoxContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
theme = ExtResource("1_c0dr6")
@ -96,3 +95,5 @@ icon = ExtResource("5_1citv")
icon_alignment = 1
vertical_icon_alignment = 0
expand_icon = true
[connection signal="pressed" from="Panel/VBoxContainer/MarginContainer/VBoxContainer/Button" to="." method="_on_add_button_pressed"]

View file

@ -1,5 +1,7 @@
class_name UIManager extends HBoxContainer
const uuid_util = preload('res://addons/uuid/uuid.gd')
@export_category("Main Panel")
@export var current_active_panel: MainPanel
@export var panel_array: Array[MainPanel] = []
@ -14,14 +16,15 @@ var instantiated_window: Window
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
current_active_panel.id = 0
panel_array.append(current_active_panel)
#current_active_panel.id = 0
#panel_array.append(current_active_panel)
SignalBus.on_panel_created.connect(_on_panel_created)
SignalBus.on_panel_requested.connect(_on_panel_requested)
SignalBus.on_new_container_requested.connect(_on_new_container_requested)
SignalBus.edit_window_text_saved.connect(_on_edit_window_text_saved)
#SignalBus.on_entry_deleted.connect(on_entry_deleted)
# Called every frame. 'delta' is the elapsed time since the previous frame.
@ -31,15 +34,18 @@ func _process(delta: float) -> void:
func _on_panel_created() -> void:
var new_panel: MainPanel = main_panel_scene.instantiate()
new_panel.id = panel_array.size()
new_panel.id = uuid_util.v4()
panel_array.append(new_panel)
func _on_panel_requested(index: int) -> void:
func _on_panel_requested(index) -> void:
if current_active_panel == panel_array[index]:
print("Already active")
return
print("Panel: %d requested" % index)
current_active_panel.hide()
if current_active_panel != null:
current_active_panel.hide()
current_active_panel = panel_array[index]
if not current_active_panel.is_inside_tree():
add_child(current_active_panel)
@ -55,8 +61,18 @@ func _on_new_container_requested() -> void:
container_collection_box.add_child(new_button)
container_collection_box.move_child(new_button, -2)
func _on_edit_window_text_saved(window: Window, text: String, edit_id: int) -> void:
if not is_instance_of(window, EditCollectionNameWindow):
return
container_selection_buttons[edit_id].button.text = text
func _on_edit_window_text_saved(window: Window, text: String, node: Node) -> void:
if is_instance_of(window, EditCollectionNameWindow):
var i: int = container_selection_buttons.find(node)
container_selection_buttons[i].button.text = text
rename_container_text_box_when_button_is_renamed(node)
elif is_instance_of(window, Editmenu):
for panel in panel_array:
if panel.done_boxes.has(node):
var i: int = panel.done_boxes.find(node)
panel.done_boxes[i].entry_text_box.text = text
func rename_container_text_box_when_button_is_renamed(id) -> void:
panel_array[id].container_name_label.text = container_selection_buttons[id].button.text

View file

@ -2,7 +2,7 @@ class_name EditCollectionNameWindow extends Window
@export var text_edit: LineEdit
var id: int
var id: Node
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
@ -16,7 +16,7 @@ func _process(delta: float) -> void:
func cancel() -> void:
SignalBus.edit_window_closed.emit()
SignalBus.on_window_closed.emit(self)
func save() -> void:
@ -24,7 +24,7 @@ func save() -> void:
SignalBus.on_window_closed.emit(self)
func on_edit_window_requested(window: Window, text: String, edit_id: int) -> void:
func on_edit_window_requested(window: Window, text: String, edit_id: Node) -> void:
if not is_instance_of(window, EditCollectionNameWindow):
return
text_edit.text = text

View file

@ -2,7 +2,7 @@ class_name Editmenu extends Window
@export var text_edit: TextEdit
var id: int
var node: Node
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
@ -17,10 +17,10 @@ func _process(delta: float) -> void:
func _on_close_requested() -> void:
cancel()
func on_edit_window_requested(window: Window, text: String, edit_id: int) -> void:
func on_edit_window_requested(window: Window, text: String, _node: Node) -> void:
if not is_instance_of(window, Editmenu):
return
id = edit_id
node = _node
text_edit.text = text
func _on_cancel_button_button_down() -> void:
@ -28,6 +28,7 @@ func _on_cancel_button_button_down() -> void:
func _on_save_button_button_down() -> void:
print("Save: ", node)
save()
@ -36,12 +37,12 @@ func _on_save_button_pressed() -> void:
func cancel() -> void:
SignalBus.edit_window_closed.emit()
SignalBus.on_window_closed.emit(self)
func save() -> void:
SignalBus.edit_window_text_saved.emit(self, text_edit.text, id)
SignalBus.edit_window_closed.emit()
SignalBus.edit_window_text_saved.emit(self, text_edit.text, node)
SignalBus.on_window_closed.emit(self)
func _on_cancel_button_pressed() -> void:

View file

@ -20,7 +20,7 @@ unicode = 115
[sub_resource type="Shortcut" id="Shortcut_i6crh"]
events = [SubResource("InputEventKey_lut1q")]
[node name="Control" type="Window" node_paths=PackedStringArray("text_edit")]
[node name="Editmenu" type="Window" node_paths=PackedStringArray("text_edit")]
title = "Edit Entry"
initial_position = 1
size = Vector2i(600, 300)