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,17 @@
extends PopochiuDialogText
#region Private ####################################################################################
func _modify_size(msg: String, _target_position: Vector2) -> void:
var _size := await _calculate_size(msg)
# Define size and position (before calculating overflow)
rich_text_label.size.y = _size.y
rich_text_label.position.y = get_meta(DFLT_POSITION).y - (_size.y - get_meta(DFLT_SIZE).y)
func _append_text(msg: String, props: Dictionary) -> void:
rich_text_label.text = "[center][color=%s]%s[/color][/center]" % [props.color.to_html(), msg]
#endregion

View file

@ -0,0 +1,58 @@
[gd_scene load_steps=4 format=3 uid="uid://bpl3qjbxonfpb"]
[ext_resource type="Script" path="res://addons/popochiu/engine/objects/gui/components/dialog_text/dialog_caption/dialog_caption.gd" id="1_17s2p"]
[ext_resource type="Theme" uid="uid://dpequqav4rjaf" path="res://addons/popochiu/engine/objects/gui/resources/base_gui_theme.tres" id="1_xoamn"]
[ext_resource type="Texture2D" uid="uid://h156lkhxk5tl" path="res://addons/popochiu/engine/objects/gui/components/dialog_text/images/ico_continue.png" id="3_etbl2"]
[node name="DialogCaption" type="Control" groups=["popochiu_gui_component"]]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme = ExtResource("1_xoamn")
script = ExtResource("1_17s2p")
[node name="RichTextLabel" type="RichTextLabel" parent="."]
unique_name_in_owner = true
clip_contents = false
custom_minimum_size = Vector2(16, 16)
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 20.0
offset_top = -20.0
offset_right = -20.0
offset_bottom = -4.0
grow_horizontal = 2
grow_vertical = 0
size_flags_horizontal = 0
mouse_filter = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
bbcode_enabled = true
text = "[center]A [shake]caption[/shake] dialog text[/center]"
fit_content = true
scroll_active = false
meta_underlined = false
[node name="ContinueIcon" type="TextureProgressBar" parent="RichTextLabel"]
unique_name_in_owner = true
texture_filter = 1
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -16.0
offset_right = 16.0
grow_horizontal = 0
grow_vertical = 0
value = 100.0
fill_mode = 2
texture_progress = ExtResource("3_etbl2")

View file

@ -0,0 +1,47 @@
extends PopochiuDialogText
#region Private ####################################################################################
func _modify_size(msg: String, target_position: Vector2) -> void:
var _size := await _calculate_size(msg)
# Define size and position (before calculating overflow)
rich_text_label.size = _size
rich_text_label.position = target_position - rich_text_label.size / 2.0
rich_text_label.position.y -= rich_text_label.size.y / 2.0
# Calculate overflow and reposition
if rich_text_label.position.x < 0.0:
rich_text_label.position.x = limit_margin
elif rich_text_label.position.x + rich_text_label.size.x + continue_icon_size.x > _x_limit:
rich_text_label.position.x = (
_x_limit - limit_margin - rich_text_label.size.x - continue_icon_size.x
)
if rich_text_label.position.y < 0.0:
rich_text_label.position.y = limit_margin
elif rich_text_label.position.y + rich_text_label.size.y > _y_limit:
rich_text_label.position.y = _y_limit - limit_margin - rich_text_label.size.y
func _set_default_label_size(lbl: Label) -> void:
lbl.size.y = get_meta(DFLT_SIZE).y
func _append_text(msg: String, props: Dictionary) -> void:
var center: float = floor(rich_text_label.position.x + (rich_text_label.size.x / 2))
if center == props.position.x:
rich_text_label.text = "[center]%s[/center]" % msg
elif center < props.position.x:
rich_text_label.text = "[right]%s[/right]" % msg
else:
rich_text_label.text = msg
func _get_icon_from_position() -> float:
return rich_text_label.size.y / 2.0 - 1.0
func _get_icon_to_position() -> float:
return rich_text_label.size.y / 2.0 + 3.0
#endregion

View file

@ -0,0 +1,47 @@
[gd_scene load_steps=4 format=3 uid="uid://bn7o13nv11ka1"]
[ext_resource type="Script" path="res://addons/popochiu/engine/objects/gui/components/dialog_text/dialog_overhead/dialog_overhead.gd" id="1_a5mdx"]
[ext_resource type="Theme" uid="uid://dpequqav4rjaf" path="res://addons/popochiu/engine/objects/gui/resources/base_gui_theme.tres" id="2_t336a"]
[ext_resource type="Texture2D" uid="uid://h156lkhxk5tl" path="res://addons/popochiu/engine/objects/gui/components/dialog_text/images/ico_continue.png" id="3_67j10"]
[node name="DialogOverhead" type="Control" groups=["popochiu_gui_component"]]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme = ExtResource("2_t336a")
script = ExtResource("1_a5mdx")
[node name="RichTextLabel" type="RichTextLabel" parent="."]
unique_name_in_owner = true
clip_contents = false
custom_minimum_size = Vector2(16, 16)
layout_mode = 0
offset_right = 153.0
offset_bottom = 16.0
size_flags_horizontal = 0
mouse_filter = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
bbcode_enabled = true
text = "An [shake]overhead[/shake] dialog text"
fit_content = true
scroll_active = false
meta_underlined = false
[node name="ContinueIcon" type="TextureProgressBar" parent="RichTextLabel"]
unique_name_in_owner = true
texture_filter = 1
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_right = 16.0
offset_bottom = 16.0
grow_horizontal = 0
value = 100.0
fill_mode = 2
texture_progress = ExtResource("3_67j10")

View file

@ -0,0 +1,45 @@
extends PopochiuDialogText
@onready var left_avatar_container: PanelContainer = %LeftAvatarContainer
@onready var left_avatar: TextureRect = %LeftAvatar
@onready var right_avatar_container: PanelContainer = %RightAvatarContainer
@onready var right_avatar: TextureRect = %RightAvatar
#region Godot ######################################################################################
func _ready() -> void:
super()
# Connect to singletons signals
PopochiuUtils.c.character_spoke.connect(_update_avatar)
#endregion
#region Private ####################################################################################
func _update_avatar(chr: PopochiuCharacter, _msg := '') -> void:
if not rich_text_label.visible:
return
left_avatar_container.modulate.a = 0.0
left_avatar.texture = null
right_avatar_container.modulate.a = 0.0
right_avatar.texture = null
var char_pos: Vector2 = PopochiuUtils.get_screen_coords_for(chr).floor() / (
PopochiuUtils.e.scale if PopochiuUtils.e.settings.scale_gui else Vector2.ONE
)
if char_pos.x <= PopochiuUtils.e.half_width:
left_avatar_container.modulate.a = 1.0
left_avatar.texture = chr.get_avatar_for_emotion(chr.emotion)
else:
right_avatar_container.modulate.a = 1.0
right_avatar.texture = chr.get_avatar_for_emotion(chr.emotion)
func _set_default_size() -> void:
pass
#endregion

View file

@ -0,0 +1,106 @@
[gd_scene load_steps=6 format=3 uid="uid://33wmak2jumqm"]
[ext_resource type="Script" path="res://addons/popochiu/engine/objects/gui/components/dialog_text/dialog_portrait/dialog_portrait.gd" id="1_ejue5"]
[ext_resource type="Theme" uid="uid://dpequqav4rjaf" path="res://addons/popochiu/engine/objects/gui/resources/base_gui_theme.tres" id="1_x1xka"]
[ext_resource type="Texture2D" uid="uid://h156lkhxk5tl" path="res://addons/popochiu/engine/objects/gui/components/dialog_text/images/ico_continue.png" id="4_lqu2o"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8fbbc"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mjjs7"]
content_margin_left = 4.0
content_margin_top = 2.0
content_margin_right = 4.0
content_margin_bottom = 2.0
bg_color = Color(0, 0, 0, 0.705882)
[node name="DialogPortrait" type="Control" groups=["popochiu_gui_component"]]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme = ExtResource("1_x1xka")
script = ExtResource("1_ejue5")
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -48.0
grow_horizontal = 2
grow_vertical = 0
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_8fbbc")
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer"]
layout_mode = 2
mouse_filter = 2
theme_override_constants/separation = 2
[node name="LeftAvatarContainer" type="PanelContainer" parent="PanelContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
mouse_filter = 2
[node name="LeftAvatar" type="TextureRect" parent="PanelContainer/HBoxContainer/LeftAvatarContainer"]
unique_name_in_owner = true
texture_filter = 1
custom_minimum_size = Vector2(48, 48)
layout_mode = 2
size_flags_vertical = 4
mouse_filter = 2
stretch_mode = 3
[node name="TextContainer" type="PanelContainer" parent="PanelContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_mjjs7")
[node name="RichTextLabel" type="RichTextLabel" parent="PanelContainer/HBoxContainer/TextContainer"]
unique_name_in_owner = true
clip_contents = false
custom_minimum_size = Vector2(16, 16)
layout_mode = 2
size_flags_horizontal = 3
mouse_filter = 2
bbcode_enabled = true
text = "A [shake]portrait[/shake] dialog text."
scroll_active = false
meta_underlined = false
[node name="ContinueIcon" type="TextureProgressBar" parent="PanelContainer/HBoxContainer/TextContainer/RichTextLabel"]
unique_name_in_owner = true
texture_filter = 1
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -16.0
offset_top = -16.0
grow_horizontal = 0
grow_vertical = 0
mouse_filter = 2
value = 100.0
fill_mode = 2
texture_progress = ExtResource("4_lqu2o")
[node name="RightAvatarContainer" type="PanelContainer" parent="PanelContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
mouse_filter = 2
[node name="RightAvatar" type="TextureRect" parent="PanelContainer/HBoxContainer/RightAvatarContainer"]
unique_name_in_owner = true
texture_filter = 1
custom_minimum_size = Vector2(48, 48)
layout_mode = 2
size_flags_vertical = 4
mouse_filter = 2
stretch_mode = 3

View file

@ -0,0 +1,301 @@
class_name PopochiuDialogText
extends Control
## Show dialogue texts char by char using a [RichTextLabel].
##
## An invisible [Label] is used to calculate the width of the [RichTextLabel] node.
signal animation_finished
signal text_show_started
signal text_show_finished
const DFLT_SIZE := "dflt_size"
const DFLT_POSITION := "dflt_position"
@export var wrap_width := 200.0
@export var limit_margin := 4.0
var tween: Tween = null
var continue_icon_tween: Tween = null
var _secs_per_character := 1.0
var _is_waiting_input := false
var _auto_continue := false
var _dialog_pos := Vector2.ZERO
var _x_limit := 0.0
var _y_limit := 0.0
@onready var rich_text_label: RichTextLabel = %RichTextLabel
@onready var continue_icon: TextureProgressBar = %ContinueIcon
@onready var continue_icon_size := continue_icon.texture_progress.get_size()
#region Godot ######################################################################################
func _ready() -> void:
# Set the default values
rich_text_label.text = ""
set_meta(DFLT_SIZE, rich_text_label.size)
set_meta(DFLT_POSITION, rich_text_label.position)
modulate.a = 0.0
_secs_per_character = PopochiuUtils.e.text_speed
_x_limit = PopochiuUtils.e.width / (
PopochiuUtils.e.scale.x if PopochiuUtils.e.settings.scale_gui else 1.0
)
_y_limit = PopochiuUtils.e.height / (
PopochiuUtils.e.scale.y if PopochiuUtils.e.settings.scale_gui else 1.0
)
# Connect to singletons events
PopochiuUtils.e.text_speed_changed.connect(change_speed)
PopochiuUtils.c.character_spoke.connect(_show_dialogue)
continue_icon.hide()
func _input(event: InputEvent) -> void:
if (
not PopochiuUtils.get_click_or_touch_index(event) in [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT]
or modulate.a == 0.0
):
return
accept_event()
if rich_text_label.visible_ratio == 1.0:
disappear()
else:
stop()
#endregion
#region Public #####################################################################################
func play_text(props: Dictionary) -> void:
var msg: String = PopochiuUtils.e.get_text(props.text)
_is_waiting_input = false
_dialog_pos = props.position
if PopochiuConfig.should_talk_gibberish():
msg = PopochiuUtils.d.create_gibberish(msg)
# Call the virtual method that modifies the size of the RichTextLabel in case the dialog style
# requires it.
await _modify_size(msg, props.position)
# Assign the text and align mode
msg = "[color=%s]%s[/color]" % [props.color.to_html(), msg]
_append_text(msg, props)
if _secs_per_character > 0.0:
# The text will appear with an animation
if is_instance_valid(tween) and tween.is_running():
tween.kill()
tween = create_tween()
tween.tween_property(
rich_text_label, "visible_ratio",
1,
_secs_per_character * rich_text_label.get_total_character_count()
).from(0.0)
tween.finished.connect(_wait_input)
else:
_wait_input()
modulate.a = 1.0
func stop() ->void:
if modulate.a == 0.0:
return
if _is_waiting_input:
_notify_completion()
else:
# Skip tweens
if is_instance_valid(tween) and tween.is_running():
tween.kill()
rich_text_label.visible_ratio = 1.0
_wait_input()
func disappear() -> void:
if modulate.a == 0.0: return
_auto_continue = false
modulate.a = 0.0
_is_waiting_input = false
if is_instance_valid(tween) and tween.is_running():
tween.kill()
rich_text_label.clear()
rich_text_label.text = ""
_set_default_size()
continue_icon.hide()
continue_icon.modulate.a = 1.0
if is_instance_valid(continue_icon_tween) and continue_icon_tween.is_running():
continue_icon_tween.kill()
set_process_input(false)
text_show_finished.emit()
PopochiuUtils.g.dialog_line_finished.emit()
func change_speed() -> void:
_secs_per_character = PopochiuUtils.e.text_speed
#endregion
#region Private ####################################################################################
func _show_dialogue(chr: PopochiuCharacter, msg := "") -> void:
if not visible: return
play_text({
text = msg,
color = chr.text_color,
position = PopochiuUtils.get_screen_coords_for(chr, chr.dialog_pos).floor() / (
PopochiuUtils.e.scale if PopochiuUtils.e.settings.scale_gui else Vector2.ONE
),
})
PopochiuUtils.g.dialog_line_started.emit()
set_process_input(true)
text_show_started.emit()
func _modify_size(_msg: String, _target_position: Vector2) -> void:
await get_tree().process_frame
## Creates a RichTextLabel to calculate the resulting size of this node once the whole text is shown.
func _calculate_size(msg: String) -> Vector2:
var rt := RichTextLabel.new()
rt.add_theme_font_override("normal_font", get_theme_font("normal_font"))
rt.bbcode_enabled = true
rt.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
rt.text = msg
rt.size = get_meta(DFLT_SIZE)
rich_text_label.add_child(rt)
# Create a Label to check if the text exceeds the wrap_width
var lbl := Label.new()
lbl.add_theme_font_override("normal_font", get_theme_font("normal_font"))
_set_default_label_size(lbl)
lbl.text = rt.get_parsed_text()
rich_text_label.add_child(lbl)
rt.clear()
rt.text = ""
await get_tree().process_frame
var _size := lbl.size
if _size.x > wrap_width:
# This node will have the width of the wrap_width
_size.x = wrap_width
rt.fit_content = true
rt.size.x = _size.x
rt.text = msg
await get_tree().process_frame
_size = rt.size
else:
# This node will have the width of the text
_size.y = get_meta(DFLT_SIZE).y
var characters_count := lbl.get_total_character_count()
lbl.free()
rt.free()
return _size
func _set_default_label_size(lbl: Label) -> void:
lbl.size = get_meta(DFLT_SIZE)
func _append_text(msg: String, _props: Dictionary) -> void:
rich_text_label.append_text(msg)
func _wait_input() -> void:
_is_waiting_input = true
if is_instance_valid(tween) and tween.finished.is_connected(_wait_input):
tween.finished.disconnect(_wait_input)
if PopochiuUtils.e.auto_continue_after >= 0.0:
_auto_continue = true
await get_tree().create_timer(PopochiuUtils.e.auto_continue_after + 0.2).timeout
if _auto_continue:
_continue(true)
else:
_show_icon()
func _show_icon() -> void:
if is_instance_valid(continue_icon_tween) and continue_icon_tween.is_running():
continue_icon_tween.kill()
continue_icon_tween = create_tween()
if not PopochiuUtils.e.settings.auto_continue_text:
# For manual continuation: make the icon jump
continue_icon.value = 100.0
continue_icon_tween.tween_property(
continue_icon, "position:y", _get_icon_to_position(), 0.8
).from(_get_icon_from_position()).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT)
continue_icon_tween.set_loops()
else:
# For automatic continuation: Make the icon appear as a progress bar indicating the time
# players have to read before auto-continuing.
continue_icon.value = 0.0
continue_icon.position.y = size.y / 2.0
continue_icon_tween.tween_property(
continue_icon, "value",
100.0, 3.0,
).from_current().set_ease(Tween.EASE_OUT)
continue_icon_tween.finished.connect(_continue)
continue_icon_tween.pause()
await get_tree().create_timer(0.2).timeout
continue_icon_tween.play()
continue_icon.show()
func _get_icon_from_position() -> float:
return rich_text_label.size.y - continue_icon.size.y + 2.0
func _get_icon_to_position() -> float:
return rich_text_label.size.y - continue_icon.size.y - 1.0
func _notify_completion() -> void:
disappear()
animation_finished.emit()
func _continue(forced_continue := false) -> void:
if PopochiuUtils.e.settings.auto_continue_text or forced_continue:
disappear()
func _set_default_size() -> void:
rich_text_label.size = get_meta(DFLT_SIZE)
#endregion

View file

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

View file

@ -0,0 +1,38 @@
[gd_scene load_steps=4 format=3 uid="uid://cymfte4xe3tnw"]
[ext_resource type="Theme" uid="uid://dpequqav4rjaf" path="res://addons/popochiu/engine/objects/gui/resources/base_gui_theme.tres" id="1_mrmwc"]
[ext_resource type="Script" path="res://addons/popochiu/engine/objects/gui/components/dialog_text/dialog_text.gd" id="2_adpg7"]
[ext_resource type="Texture2D" uid="uid://h156lkhxk5tl" path="res://addons/popochiu/engine/objects/gui/components/dialog_text/images/ico_continue.png" id="3_fqlmr"]
[node name="DialogText" type="Control" groups=["popochiu_gui_component"]]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme = ExtResource("1_mrmwc")
script = ExtResource("2_adpg7")
[node name="RichTextLabel" type="RichTextLabel" parent="."]
unique_name_in_owner = true
layout_mode = 0
offset_right = 74.0
offset_bottom = 12.0
text = "Dialog text"
fit_content = true
[node name="ContinueIcon" type="TextureProgressBar" parent="RichTextLabel"]
unique_name_in_owner = true
texture_filter = 1
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_right = 16.0
offset_bottom = 16.0
grow_horizontal = 0
value = 100.0
fill_mode = 2
texture_progress = ExtResource("3_fqlmr")

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://h156lkhxk5tl"
path="res://.godot/imported/ico_continue.png-1c56d7b39fdf03dafd5aacca996d24e0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/popochiu/engine/objects/gui/components/dialog_text/images/ico_continue.png"
dest_files=["res://.godot/imported/ico_continue.png-1c56d7b39fdf03dafd5aacca996d24e0.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