@tool extends CenterContainer signal text_finished signal finished signal intro signal emit_thunder #TODO properly implement animation taking stage, as it should do, disabling processing when it does not have stage. var max_lines: float = 0 @export var story_array: PackedStringArray = []: set(str_array): story_array = str_array if is_node_ready(): substring_sizes = [] if Engine.is_editor_hint(): TranslationServer.set_locale("en") var p: int = 0 label.text = "[p]" for i in range(str_array.size()): label.text += TranslationServer.translate(str_array[i]).strip_edges() + " " substring_sizes.append(TranslationServer.translate(str_array[i]).strip_edges().length() + 1) if not paragraph_lengths[-1] == story_array.size()-1: paragraph_lengths.append(story_array.size()-1) push_warning("Paragraph lenghts of scene %s are misconfigured!" % name) if paragraph_lengths[p] == i: p += 1 label.text += "[/p][p][font_size=8] [/font_size][/p][p]" substring_sizes[-1] = substring_sizes[-1] + 1 label.text += "[/p]" max_lines = float(label.get_line_count()) @export var paragraph_lengths: PackedInt32Array = [1] @export var progress: float = 0: set(value): progress = value if is_node_ready() and not all_text_revealed: var start_index = 0 if progress >= substring_sizes.size() or progress < 0: label.visible_ratio = 1 elif progress > 0: for i in range(min(progress, substring_sizes.size()-1) as int) if progress > 0 else range(substring_sizes.size()-1): start_index += substring_sizes[i] label.visible_characters = start_index + substring_sizes[min(progress as int, substring_sizes.size()-1)] * fmod(progress, 1) else: label.visible_ratio = 0 var all_text_revealed: bool = false: set(revealed): var reset_progress := false if revealed and not all_text_revealed: var tween: Tween = get_tree().create_tween() tween.set_ease(Tween.EASE_OUT) tween.tween_property(label, "visible_ratio", 1, 1.5) elif not revealed and all_text_revealed: reset_progress = true all_text_revealed = revealed if all_text_revealed: progress = -1 if reset_progress: progress = 0 @export var test_scroll: bool: set(scroll): try_scroll() @onready var label:RichTextLabel = %StoryLabel @onready var scroll_container:ScrollContainer = %StoryScroll @onready var animation_player: AnimationPlayer = %AnimationPlayer @onready var skip_control: SkipControl = %SkipControl @export var animation_complete:bool = false: set(value): animation_complete = value if value: scroll_container.vertical_scroll_mode = ScrollContainer.ScrollMode.SCROLL_MODE_AUTO progress = -1 else: scroll_container.scroll_vertical = ScrollContainer.ScrollMode.SCROLL_MODE_DISABLED animation_complete = value var substring_sizes: Array[int] func _ready() -> void: State.settings_changed.connect(func(): story_array = story_array) skip_control = %SkipControl if skip_control is SkipControl and not Engine.is_editor_hint(): skip_control.skip.connect(skip_text) if get_tree().root.get_child(-1) == self: TranslationServer.set_locale("de") play_scene() story_array = story_array progress = progress func try_scroll(): var forward_target: int #print( "max lines: " + str(max_lines)) #print( "current lines: " + str(label.get_character_line(label.visible_characters))) var visible_ratio: float = float(label.get_character_line(label.visible_characters)) / max_lines #print("Tried scrolling with ratio of %f. Comparing %f against %f" % [visible_ratio, label.size.y * visible_ratio - scroll_container.scroll_vertical, scroll_container.size.y * 0.9]) if label.size.y * visible_ratio + scroll_container.scroll_vertical > scroll_container.size.y * 0.9: if scroll_container.scroll_vertical + scroll_container.size.y * 0.9 < label.size.y: forward_target = scroll_container.scroll_vertical + scroll_container.size.y * 0.8 else: forward_target = label.size.y - scroll_container.size.y if scroll_target != null: var tween: Tween = get_tree().create_tween() ##tween.set_trans() scroll_target = forward_target func play_scene(): # FIXME: find out why this needs to be set to prevent scenes from being fully revealed all_text_revealed = false animation_complete = false ##FIXME match State.speech_language: match TranslationServer.get_locale(): "de": animation_player.queue("en") "en": animation_player.queue("en") await text_finished if name == "draven": trigger_intro() animation_complete = true all_text_revealed = true skip_control.start_proceed_countdown() await skip_control.proceed animation_player.play("vanish") await animation_player.animation_finished finished.emit() func _unhandled_input(event: InputEvent) -> void: var just_revealed_text = false if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_WHEEL_DOWN: scroll_target += 40 if not all_text_revealed: just_revealed_text all_text_revealed = true if event.button_index == MOUSE_BUTTON_WHEEL_UP: scroll_target -= 40 if not all_text_revealed: just_revealed_text all_text_revealed = true if just_revealed_text: if animation_complete: all_text_revealed = true var scroll_target: float = 0: set(value): scroll_target = clampf(value, 0, label.size.y - scroll_container.size.y+10) func _process(delta: float) -> void: # FIXME: maybe change this to has stage? if visible and not Engine.is_editor_hint(): if scroll_container.scroll_vertical != scroll_target: scroll_container.scroll_vertical += (scroll_target-scroll_container.scroll_vertical)*delta*6 var intro_triggered:= false func trigger_intro(): if not intro_triggered: intro.emit() intro_triggered = true var was_skipped = false func skip_text(): if not animation_complete: animation_player.stop(true) was_skipped = true text_finished.emit() if name == "draven": $AnimationPlayer/Music.stop() elif name == "JuiJutsu": _emit_thunder() func _on_text_finished(): if not animation_complete: text_finished.emit() func _emit_thunder(): emit_thunder.emit()