diff --git a/addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.gd b/addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.gd index ed7e48cc6..5f3a7050a 100644 --- a/addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.gd +++ b/addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.gd @@ -1,81 +1,39 @@ -extends Control +extends CanvasLayer -enum SizingModes {AdjustAlways, AdjustOnStart, Fixed} -@export var sizing_mode: SizingModes = SizingModes.AdjustAlways - -@export var max_width :float= 0 -@export var max_lines = 10 +## This layout won't do anything on it's own +var bubbles :Array[Dictionary] = [] +var fallback_bubble :Control = null func _ready(): - if max_width <= 0: - max_width = get_viewport().size.x/2 - - -func _on_DialogText_continued_revealing_text(new_character = ""): - if sizing_mode == SizingModes.AdjustAlways: - var font = $DialogText.get_theme_font("normal_font") - var line_height = font.get_height() - var longest_line_len = 0 - var lines = 0 - for line in $DialogText.text.substr(0, $DialogText.visible_characters).split("\n"): - longest_line_len = font.get_string_size(line).x if font.get_string_size(line).x > longest_line_len else longest_line_len - if font.get_string_size(line).x > max_width-60: - lines += ceil(font.get_string_size(line).x/(max_width-60))-1 - lines += 1 - - # because there is a margin and a number inside the stylebox (especially to the left) this needs to be added - longest_line_len += 100 - if sizing_mode == SizingModes.AdjustAlways: - custom_minimum_size.x = min(max_width, longest_line_len) - # a margin has to be added vertically as well because of the stylebox - custom_minimum_size.y = line_height*min(lines, max_lines)+20 - # Enable Scroll bar when more then max lines - $DialogText.scroll_active = lines > max_lines - - elif lines*line_height+40 > $DialogText.size.y: - $DialogText.scroll_active = true + Dialogic.Text.about_to_show_text.connect(_on_dialogic_text_event) - if $DialogText.scroll_active: -# $DialogText.get_v_scroll_bar().position.x = $DialogText.size.x-20 -# $DialogText.get_v_scroll_bar().margin_right = -20 - $DialogText.scroll_to_line($DialogText.get_line_count()) - - -func _on_dialog_text_started_revealing_text(): - print($NameLabel/DialogicNode_NameLabel.text) - if sizing_mode == SizingModes.AdjustOnStart: - var font = $DialogText.get_theme_font("normal_font") - var line_height = font.get_height() - var longest_line_len = 0 - var lines = 0 - for line in $DialogText.text.split("\n"): - longest_line_len = font.get_string_size(line).x if font.get_string_size(line).x > longest_line_len else longest_line_len - if font.get_string_size(line).x > max_width-60: - lines += ceil(font.get_string_size(line).x/(max_width-60))-1 - lines += 1 + var control := Control.new() + add_child(control) + control.position = control.get_viewport_rect().size / 2.0 + fallback_bubble = preload("res://addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.tscn").instantiate() + fallback_bubble.speaker_node = control + fallback_bubble.get_node('Tail').hide() + fallback_bubble.safe_zone = 0 + fallback_bubble.base_direction = Vector2.ZERO + + add_child(fallback_bubble) - # because there is a margin and a number inside the stylebox (especially to the left) this needs to be added - longest_line_len += 100 - custom_minimum_size.x = min(max_width, longest_line_len) - # a margin has to be added vertically as well because of the stylebox - custom_minimum_size.y = line_height*min(lines, max_lines) - if Dialogic.Choices.is_question(Dialogic.current_event_idx): - custom_minimum_size.y += 80 - $DialogText.offset_bottom = -25 - - # Enable Scroll bar when more then max lines - $DialogText.scroll_active = lines > max_lines - if lines*line_height+40 > $DialogText.size.y: - $DialogText.scroll_active = true - else: - $DialogText.offset_bottom = -7 +func register_character(character:DialogicCharacter, node:Node2D): + var new_bubble := preload("res://addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.tscn").instantiate() + new_bubble.speaker_node = node + add_child(new_bubble) + bubbles.append({'node':node, 'bubble':new_bubble, 'character':character}) -func _on_dialog_text_finished_revealing_text(): - if sizing_mode == SizingModes.AdjustAlways: - if Dialogic.Choices.is_question(Dialogic.current_event_idx): - $DialogText.offset_bottom = -25 +func _on_dialogic_text_event(info:Dictionary): + var no_bubble_open := true + for b in bubbles: + if b.character == info.character: + no_bubble_open = false + b.bubble.open() else: - $DialogText.offset_bottom = -7 + b.bubble.close() + if no_bubble_open: + fallback_bubble.open() diff --git a/addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.tscn b/addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.tscn index 4eff89787..e7e59f261 100644 --- a/addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.tscn +++ b/addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.tscn @@ -1,191 +1,8 @@ -[gd_scene load_steps=14 format=3] +[gd_scene load_steps=2 format=3 uid="uid://syki6k0e6aac"] [ext_resource type="Script" path="res://addons/dialogic/Modules/DefaultStyles/TextBubble/DialogicTextBubbleLayout.gd" id="1_502mo"] -[ext_resource type="Texture2D" uid="uid://b3sccqj6l42w6" path="res://addons/dialogic/Example Assets/backgrounds/BubbleEnd.png" id="2_sqahx"] -[ext_resource type="Script" path="res://addons/dialogic/Modules/Text/node_dialog_text.gd" id="3_ou07r"] -[ext_resource type="Script" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="4_6ctnn"] -[ext_resource type="Script" path="res://addons/dialogic/Modules/Choice/node_choice_button.gd" id="5_d7df1"] -[ext_resource type="Script" path="res://addons/dialogic/Modules/DefaultStyles/HideWithChild.gd" id="6_dlfb7"] -[ext_resource type="Script" path="res://addons/dialogic/Modules/Text/node_name_label.gd" id="7_xx1xf"] -[sub_resource type="StyleBoxFlat" id="11"] -bg_color = Color(0.847059, 0.627451, 0.364706, 1) -border_width_left = 2 -border_width_top = 2 -border_width_right = 2 -border_width_bottom = 2 -border_color = Color(1, 1, 1, 0.768627) -border_blend = true -corner_radius_top_left = 5 -corner_radius_top_right = 5 -corner_radius_bottom_right = 5 -corner_radius_bottom_left = 5 - -[sub_resource type="StyleBoxFlat" id="12"] -content_margin_left = 5.0 -content_margin_right = 5.0 -bg_color = Color(0.647059, 0.647059, 0.647059, 1) -border_width_top = 10 -border_width_bottom = 10 -border_color = Color(0.8, 0.8, 0.8, 0) -corner_radius_top_left = 5 -corner_radius_top_right = 5 -corner_radius_bottom_right = 5 -corner_radius_bottom_left = 5 - -[sub_resource type="Theme" id="13"] -VScrollBar/styles/grabber = SubResource("11") -VScrollBar/styles/grabber_highlight = SubResource("11") -VScrollBar/styles/grabber_pressed = SubResource("11") -VScrollBar/styles/scroll = SubResource("12") - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kr20r"] -bg_color = Color(0.970602, 0.970602, 0.970602, 1) -corner_radius_top_left = 20 -corner_radius_top_right = 20 -corner_radius_bottom_right = 20 -corner_radius_bottom_left = 20 -shadow_color = Color(0, 0, 0, 0.211765) -shadow_size = 10 - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_g4yjl"] -draw_center = false -border_width_bottom = 3 -border_color = Color(0.227451, 0.227451, 0.227451, 1) - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_h6ls0"] -content_margin_left = 5.0 -content_margin_right = 5.0 -bg_color = Color(0.901961, 0.901961, 0.901961, 1) -corner_radius_top_left = 10 -corner_radius_top_right = 10 -corner_radius_bottom_right = 10 -corner_radius_bottom_left = 10 -shadow_color = Color(0, 0, 0, 0.278431) -shadow_size = 5 - -[node name="Control" type="Control"] -custom_minimum_size = Vector2(100, 75) -layout_mode = 3 -anchors_preset = 0 -offset_left = -13.0 -offset_top = -112.0 -offset_right = 87.0 -offset_bottom = -37.0 -grow_vertical = 0 -theme = SubResource("13") +[node name="TextBubbleHolder" type="CanvasLayer"] script = ExtResource("1_502mo") sizing_mode = 1 max_width = 200.0 - -[node name="BubbleEnd" type="TextureRect" parent="."] -layout_mode = 1 -anchors_preset = 2 -anchor_top = 1.0 -anchor_bottom = 1.0 -offset_left = 8.0 -offset_top = -4.0 -offset_right = 89.0 -offset_bottom = 41.0 -grow_vertical = 0 -texture = ExtResource("2_sqahx") -expand_mode = 1 - -[node name="OverlayPanel" type="Panel" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -mouse_filter = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_kr20r") - -[node name="DialogText" type="RichTextLabel" parent="."] -layout_mode = 1 -anchors_preset = -1 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 9.0 -offset_top = 8.0 -offset_right = -9.0 -offset_bottom = -7.0 -grow_horizontal = 2 -grow_vertical = 2 -theme_override_colors/default_color = Color(0, 0, 0, 1) -text = "Some Text" -scroll_active = false -script = ExtResource("3_ou07r") - -[node name="DialogicNode_TypeSounds" type="AudioStreamPlayer" parent="DialogText"] -script = ExtResource("4_6ctnn") - -[node name="ChoiceContainer" type="HBoxContainer" parent="."] -layout_mode = 1 -anchors_preset = 12 -anchor_top = 1.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 8.0 -offset_top = -31.0 -offset_right = -8.0 -grow_horizontal = 2 -grow_vertical = 0 -alignment = 2 - -[node name="DialogicNode_ChoiceButton" type="Button" parent="ChoiceContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -theme_override_colors/font_color = Color(0.188235, 0.188235, 0.188235, 1) -theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) -theme_override_colors/font_hover_color = Color(0.682353, 0.482353, 0.137255, 1) -theme_override_colors/font_focus_color = Color(0.27451, 0.180392, 0.0627451, 1) -theme_override_styles/focus = SubResource("StyleBoxFlat_g4yjl") -text = "Yes!" -flat = true -script = ExtResource("5_d7df1") - -[node name="DialogicNode_ChoiceButton2" type="Button" parent="ChoiceContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -theme_override_colors/font_color = Color(0.188235, 0.188235, 0.188235, 1) -theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) -theme_override_colors/font_hover_color = Color(0.682353, 0.482353, 0.137255, 1) -theme_override_colors/font_focus_color = Color(0.27451, 0.180392, 0.0627451, 1) -theme_override_styles/focus = SubResource("StyleBoxFlat_g4yjl") -text = "Yes!" -flat = true -script = ExtResource("5_d7df1") - -[node name="DialogicNode_ChoiceButton3" type="Button" parent="ChoiceContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -theme_override_colors/font_color = Color(0.188235, 0.188235, 0.188235, 1) -theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) -theme_override_colors/font_hover_color = Color(0.682353, 0.482353, 0.137255, 1) -theme_override_colors/font_focus_color = Color(0.27451, 0.180392, 0.0627451, 1) -theme_override_styles/focus = SubResource("StyleBoxFlat_g4yjl") -text = "Yes!" -flat = true -script = ExtResource("5_d7df1") - -[node name="NameLabel" type="PanelContainer" parent="."] -layout_mode = 1 -anchors_preset = -1 -offset_left = 12.0 -offset_top = -15.0 -offset_right = 16.0 -offset_bottom = 11.0 -grow_horizontal = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_h6ls0") -script = ExtResource("6_dlfb7") - -[node name="DialogicNode_NameLabel" type="Label" parent="NameLabel"] -layout_mode = 2 -horizontal_alignment = 1 -script = ExtResource("7_xx1xf") - -[connection signal="continued_revealing_text" from="DialogText" to="." method="_on_DialogText_continued_revealing_text"] -[connection signal="finished_revealing_text" from="DialogText" to="." method="_on_dialog_text_finished_revealing_text"] -[connection signal="finished_revealing_text" from="DialogText" to="." method="_on_DialogText_continued_revealing_text"] -[connection signal="started_revealing_text" from="DialogText" to="." method="_on_dialog_text_started_revealing_text"] diff --git a/addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.gd b/addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.gd new file mode 100644 index 000000000..7fe2acffd --- /dev/null +++ b/addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.gd @@ -0,0 +1,113 @@ +extends Control + +@onready var tail : Line2D = $Tail +@onready var bubble : Control = $Background +var speaker_node : Node = null + +var max_width := 300 + +var bubble_rect : Rect2 = Rect2(0.0, 0.0, 2.0, 2.0) +var base_position = Vector2.ZERO + +var base_direction = Vector2(1.0, -1.0).normalized() +var safe_zone = 50.0 + + +func _ready() -> void: + scale = Vector2.ZERO + modulate.a = 0.0 + if speaker_node: + position = speaker_node.get_global_transform_with_canvas().origin + + +func _process(delta): + if speaker_node: + base_position = speaker_node.get_global_transform_with_canvas().origin + + var center = get_viewport_rect().size / 2.0 + + var dist_x = abs(base_position.x - center.x) + var dist_y = abs(base_position.y - center.y) + var x_e = center.x - bubble_rect.size.x + var y_e = center.y - bubble_rect.size.y + var influence_x = remap(clamp(dist_x, x_e, center.x), x_e, center.x * 0.8, 0.0, 1.0) + var influence_y = remap(clamp(dist_y, y_e, center.y), y_e, center.y * 0.8, 0.0, 1.0) + if base_position.x > center.x: influence_x = -influence_x + if base_position.y > center.y: influence_y = -influence_y + var edge_influence = Vector2(influence_x, influence_y) + + var direction = (base_direction + edge_influence).normalized() + + var p : Vector2 = base_position + direction * (safe_zone + lerp(bubble_rect.size.y, bubble_rect.size.x, abs(direction.x)) * 0.4) + p = p.clamp(bubble_rect.size / 2.0, get_viewport_rect().size - bubble_rect.size / 2.0) + + position = lerp(position, p, 10.0 * delta) + + var point_a : Vector2 = Vector2.ZERO + var point_b : Vector2 = (base_position - position) * 0.5 + + var offset = Vector2.from_angle(point_a.angle_to_point(point_b)) * bubble_rect.size * abs(direction.x) * 0.4 + + point_a += offset + point_b += offset * 0.5 + + var curve = Curve2D.new() + var direction_point = Vector2(0, (point_b.y - point_a.y)) + curve.add_point(point_a, Vector2.ZERO, direction_point * 0.5) + curve.add_point(point_b) + tail.points = curve.tessellate(5) + tail.width = bubble_rect.size.x * 0.15 + + +func open() -> void: + show() + %DialogText.enabled = true + var open_tween := create_tween().set_parallel(true) + open_tween.tween_property(self, "scale", Vector2.ONE, 0.1).from(Vector2.ZERO) + open_tween.tween_property(self, "modulate:a", 1.0, 0.1).from(0.0) + + + +func close() -> void: + %DialogText.enabled = false + var close_tween := create_tween().set_parallel(true) + close_tween.tween_property(self, "scale", Vector2.ONE * 0.8, 0.1) + close_tween.tween_property(self, "modulate:a", 0.0, 0.1) + await close_tween.finished + hide() + + +func _on_dialog_text_started_revealing_text(): + var font = %DialogText.get_theme_font("normal_font") + var line_height = font.get_height() + %DialogText.size = font.get_string_size(%DialogText.get_parsed_text()) + if %DialogText.size.x > max_width: + %DialogText.size.y = line_height*ceil(%DialogText.size.x/max_width) + %DialogText.size.x = max_width + if Dialogic.Choices.is_question(Dialogic.current_event_idx): + %DialogText.size.y += 30 + %DialogText.position = -%DialogText.size/2 + + _resize_bubble() + + +func _resize_bubble() -> void: + var bubble_size = %DialogText.size+Vector2(20,20) + var half_size = (bubble_size / 2.0) + %DialogText.pivot_offset = half_size + bubble.pivot_offset = half_size + + bubble_rect = Rect2(position, bubble_size * Vector2(1.1, 1.1)) + + var t := create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK) + t.tween_property(bubble, "custom_minimum_size", bubble_rect.size, 0.2) + + # set bubble's ratio + var bubble_ratio := Vector2.ONE + if bubble_rect.size.x < bubble_rect.size.y: + bubble_ratio.y = bubble_rect.size.y / bubble_rect.size.x + else: + bubble_ratio.x = bubble_rect.size.x / bubble_rect.size.y + + bubble.material.set("shader_parameter/ratio", bubble_ratio) + diff --git a/addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.tscn b/addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.tscn new file mode 100644 index 000000000..5bd228fb4 --- /dev/null +++ b/addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.tscn @@ -0,0 +1,176 @@ +[gd_scene load_steps=18 format=3 uid="uid://dlx7jcvm52tyw"] + +[ext_resource type="Script" path="res://addons/dialogic/Modules/DefaultStyles/TextBubble/TextBubble.gd" id="1_jdhpk"] +[ext_resource type="Shader" path="res://addons/dialogic/Modules/DefaultStyles/TextBubble/speech_bubble.gdshader" id="2_1mhvf"] +[ext_resource type="Script" path="res://addons/dialogic/Modules/Text/node_dialog_text.gd" id="3_syv35"] +[ext_resource type="Script" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="4_7bm4b"] +[ext_resource type="Script" path="res://addons/dialogic/Modules/DefaultStyles/HideWithChild.gd" id="5_371j3"] +[ext_resource type="Script" path="res://addons/dialogic/Modules/Text/node_name_label.gd" id="6_5gd03"] +[ext_resource type="Script" path="res://addons/dialogic/Modules/Choice/node_choice_button.gd" id="7_0tnh1"] + +[sub_resource type="Curve" id="Curve_0j8nu"] +_data = [Vector2(0, 1), 0.0, -1.0, 0, 1, Vector2(1, 0), -1.0, 0.0, 1, 0] +point_count = 2 + +[sub_resource type="Curve" id="Curve_4meji"] +_data = [Vector2(0, 0), 0.0, 0.161733, 0, 0, Vector2(1, 1), 2.89773, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="CurveTexture" id="CurveTexture_q6qf6"] +curve = SubResource("Curve_4meji") + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_lsfnp"] +noise_type = 0 +fractal_type = 0 +cellular_jitter = 0.15 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_kr7hw"] +noise = SubResource("FastNoiseLite_lsfnp") + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_0momr"] +noise_type = 2 +fractal_type = 0 +cellular_jitter = 0.15 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_gnq3a"] +noise = SubResource("FastNoiseLite_0momr") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_60xbe"] +shader = ExtResource("2_1mhvf") +shader_parameter/radius = 0.25 +shader_parameter/ratio = Vector2(1, 1) +shader_parameter/crease = 0.1 +shader_parameter/texture_scale = 0.1 +shader_parameter/texture_offset = Vector2(0.1, 0.1) +shader_parameter/deformation_sampler = SubResource("NoiseTexture2D_kr7hw") +shader_parameter/spikes_sampler = SubResource("NoiseTexture2D_gnq3a") +shader_parameter/curve_sampler = SubResource("CurveTexture_q6qf6") + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_h6ls0"] +content_margin_left = 5.0 +content_margin_right = 5.0 +bg_color = Color(0.901961, 0.901961, 0.901961, 1) +corner_radius_top_left = 10 +corner_radius_top_right = 10 +corner_radius_bottom_right = 10 +corner_radius_bottom_left = 10 +shadow_color = Color(0, 0, 0, 0.278431) +shadow_size = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_g4yjl"] +draw_center = false +border_width_bottom = 3 +border_color = Color(0.227451, 0.227451, 0.227451, 1) + +[node name="TextBubble" type="Control"] +layout_mode = 3 +anchors_preset = 0 +script = ExtResource("1_jdhpk") + +[node name="Tail" type="Line2D" parent="."] +width = 96.0 +width_curve = SubResource("Curve_0j8nu") + +[node name="Background" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_60xbe") +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_top = -1.0 +offset_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="DialogText" type="RichTextLabel" parent="."] +unique_name_in_owner = true +clip_contents = false +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -53.0 +offset_top = -13.0 +offset_right = 53.0 +offset_bottom = 12.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_colors/default_color = Color(0, 0, 0, 1) +text = "Some Text" +scroll_active = false +visible_characters_behavior = 1 +script = ExtResource("3_syv35") + +[node name="DialogicNode_TypeSounds" type="AudioStreamPlayer" parent="DialogText"] +script = ExtResource("4_7bm4b") + +[node name="NameLabel" type="PanelContainer" parent="DialogText"] +layout_mode = 1 +anchors_preset = -1 +offset_left = -4.0 +offset_top = -29.0 +offset_right = 7.0 +offset_bottom = -3.0 +grow_horizontal = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_h6ls0") +script = ExtResource("5_371j3") + +[node name="NameLabel" type="Label" parent="DialogText/NameLabel"] +unique_name_in_owner = true +layout_mode = 2 +horizontal_alignment = 1 +script = ExtResource("6_5gd03") + +[node name="ChoiceContainer" type="HBoxContainer" parent="DialogText"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -31.0 +grow_horizontal = 2 +grow_vertical = 0 +alignment = 2 + +[node name="DialogicNode_ChoiceButton" type="Button" parent="DialogText/ChoiceContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_colors/font_color = Color(0.188235, 0.188235, 0.188235, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0.682353, 0.482353, 0.137255, 1) +theme_override_colors/font_focus_color = Color(0.27451, 0.180392, 0.0627451, 1) +theme_override_styles/focus = SubResource("StyleBoxFlat_g4yjl") +text = "Yes!" +flat = true +script = ExtResource("7_0tnh1") + +[node name="DialogicNode_ChoiceButton2" type="Button" parent="DialogText/ChoiceContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_colors/font_color = Color(0.188235, 0.188235, 0.188235, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0.682353, 0.482353, 0.137255, 1) +theme_override_colors/font_focus_color = Color(0.27451, 0.180392, 0.0627451, 1) +theme_override_styles/focus = SubResource("StyleBoxFlat_g4yjl") +text = "Yes!" +flat = true +script = ExtResource("7_0tnh1") + +[node name="DialogicNode_ChoiceButton3" type="Button" parent="DialogText/ChoiceContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_colors/font_color = Color(0.188235, 0.188235, 0.188235, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_colors/font_hover_color = Color(0.682353, 0.482353, 0.137255, 1) +theme_override_colors/font_focus_color = Color(0.27451, 0.180392, 0.0627451, 1) +theme_override_styles/focus = SubResource("StyleBoxFlat_g4yjl") +text = "Yes!" +flat = true +script = ExtResource("7_0tnh1") + +[connection signal="started_revealing_text" from="DialogText" to="." method="_on_dialog_text_started_revealing_text"] diff --git a/addons/dialogic/Modules/DefaultStyles/TextBubble/speech_bubble.gdshader b/addons/dialogic/Modules/DefaultStyles/TextBubble/speech_bubble.gdshader new file mode 100644 index 000000000..7d5ffe08e --- /dev/null +++ b/addons/dialogic/Modules/DefaultStyles/TextBubble/speech_bubble.gdshader @@ -0,0 +1,23 @@ +shader_type canvas_item; +uniform sampler2D deformation_sampler : filter_linear, repeat_enable; +uniform sampler2D spikes_sampler : filter_linear, repeat_enable; +uniform sampler2D curve_sampler; +uniform float radius = 0.25; +uniform vec2 ratio = vec2(1.0, 1.0); + +uniform float crease : hint_range(0.0, 1.0, 0.01) = 0.1; +uniform float texture_scale : hint_range(0.0, 0.5, 0.01) = 0.2; +uniform vec2 texture_offset = vec2(0.1); + +void fragment() { + vec2 ratio_uv = UV * ratio; + float spikes = texture(spikes_sampler, ratio_uv * texture_scale + texture_offset).x; + + float d = length(max(abs(ratio_uv - vec2(0.5) * ratio) + radius - vec2(0.5) * ratio,0.0)) - radius; + d += (distance(vec2(0.5), UV) - 0.5) * radius; + float curve = texture(curve_sampler, vec2(d + spikes, 0.0)).x; + d += curve * crease; + d += texture(deformation_sampler, ratio_uv * 0.05 + TIME * 0.05).x * 0.05; + float mask = smoothstep(0.0, -0.005, d); + COLOR.a = mask; +} diff --git a/addons/dialogic/Modules/Text/event_text.gd b/addons/dialogic/Modules/Text/event_text.gd index 927ce2294..19fd26134 100644 --- a/addons/dialogic/Modules/Text/event_text.gd +++ b/addons/dialogic/Modules/Text/event_text.gd @@ -78,6 +78,8 @@ func _execute() -> void: if dialogic.has_subsystem('Glossary'): final_text = dialogic.Glossary.parse_glossary(final_text) + final_text = dialogic.Text.parse_text(final_text) + dialogic.Text.about_to_show_text.emit({'text':final_text, 'character':character, 'portrait':portrait}) final_text = await dialogic.Text.update_dialog_text(final_text) #Plays the audio region for the current line. @@ -240,7 +242,7 @@ func build_event_editor(): 'placeholder' : "(Don't change)", 'icon' : load("res://addons/dialogic/Editor/Images/Resources/portrait.svg")}, 'character != null and !has_no_portraits()') - add_body_edit('text', ValueType.MultilineText, '', '', {'autofocus' = true}) + add_body_edit('text', ValueType.MultilineText) func do_any_characters_exist() -> bool: return !DialogicUtil.list_resources_of_type(".dch").is_empty() diff --git a/addons/dialogic/Modules/Text/node_dialog_text.gd b/addons/dialogic/Modules/Text/node_dialog_text.gd index 3ac0b6b7f..5aeab8aa0 100644 --- a/addons/dialogic/Modules/Text/node_dialog_text.gd +++ b/addons/dialogic/Modules/Text/node_dialog_text.gd @@ -10,10 +10,13 @@ enum ALIGNMENT {LEFT, CENTER, RIGHT} @export var alignment : ALIGNMENT = ALIGNMENT.LEFT +@export var enabled := true var revealing := false var speed:float = 0.01 var speed_counter:float = 0 + + func _ready() -> void: # add to necessary add_to_group('dialogic_dialog_text') @@ -22,9 +25,11 @@ func _ready() -> void: text = "" - # this is called by the DialogicGameHandler to set text func reveal_text(_text:String) -> void: + if !enabled: + return + speed = Dialogic.Settings.get_setting('text_speed', 0.01) text = _text if alignment == ALIGNMENT.CENTER: @@ -36,6 +41,7 @@ func reveal_text(_text:String) -> void: speed_counter = 0 emit_signal('started_revealing_text') + # called by the timer -> reveals more text func continue_reveal() -> void: if visible_characters < get_total_character_count(): diff --git a/addons/dialogic/Modules/Text/subsystem_text.gd b/addons/dialogic/Modules/Text/subsystem_text.gd index 76d2a2978..d6a4df452 100644 --- a/addons/dialogic/Modules/Text/subsystem_text.gd +++ b/addons/dialogic/Modules/Text/subsystem_text.gd @@ -3,6 +3,7 @@ extends DialogicSubsystem ## Subsystem that handles showing of dialog text (+text effects & modifiers), name label, and next indicator +signal about_to_show_text(info:Dictionary) signal text_finished(info:Dictionary) signal speaker_updated(character:DialogicCharacter) signal textbox_visibility_changed(visible:bool) @@ -61,12 +62,17 @@ func resume() -> void: ## MAIN METHODS #################################################################################################### -## Shows the given text on all visible DialogText nodes. -## Instant can be used to skip all reveiling. -func update_dialog_text(text:String, instant:bool= false) -> String: +## Applies modifiers, effects and coloring to the text +func parse_text(text:String) -> String: text = parse_text_modifiers(text) text = parse_text_effects(text) text = color_names(text) + return text + + +## Shows the given text on all visible DialogText nodes. +## Instant can be used to skip all revieling. +func update_dialog_text(text:String, instant:bool= false) -> String: if ProjectSettings.get_setting('dialogic/text/hide_empty_textbox', true): if text.is_empty(): @@ -128,6 +134,7 @@ func set_autoadvance(enabled:=true, wait_time:Variant=1.0, temp:= false) -> void dialogic.current_state_info['autoadvance']['enabled'] = enabled dialogic.current_state_info['autoadvance']['wait_time'] = wait_time + func set_manualadvance(enabled:=true, temp:= false) -> void: if !dialogic.current_state_info.has('manual_advance'): dialogic.current_state_info['manual_advance'] = {'enabled':true, 'temp_enabled':true}