diff --git a/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitle_entry.gd b/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitle_entry.gd new file mode 100644 index 00000000..6c76877d --- /dev/null +++ b/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitle_entry.gd @@ -0,0 +1,17 @@ +class_name SubtitleEntry + + +# Entry order. First is 1. +var id: int +# Start and end time in seconds. +var start_time: float +# End time in seconds. +var end_time: float +# Subtitle text. +var content: String + +func _init(_id: int, _start_time: float, _end_time: float, _content: String) -> void: + id = _id + start_time = _start_time + end_time = _end_time + content = _content diff --git a/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitle_entry.gd.uid b/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitle_entry.gd.uid new file mode 100644 index 00000000..973c1fde --- /dev/null +++ b/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitle_entry.gd.uid @@ -0,0 +1 @@ +uid://curj8kp4ivly0 diff --git a/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitles_label.gd b/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitles_label.gd new file mode 100644 index 00000000..4cbbb660 --- /dev/null +++ b/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitles_label.gd @@ -0,0 +1,123 @@ +@tool +class_name SubtitlesLabel +extends RichTextLabel + + +var _player: VideoStreamPlayer +var _subtitles: Array[SubtitleEntry] = [] +var _current_entry: SubtitleEntry = null +var _template: String = "" + + +func _ready() -> void: + _player = $".." + + +func _process(_delta: float) -> void: + if _player and _player.visible and _player.is_playing() and not _subtitles.is_empty(): + _update_content(_player.stream_position) + + +func _update_content(current_time: float) -> void: + if _current_entry and current_time > _current_entry.end_time: + _current_entry = null + text = "" + + if _current_entry == null: + for entry in _subtitles: + if current_time >= entry.start_time and current_time <= entry.end_time: + _current_entry = entry + break + + if _current_entry: + if _template.is_empty(): + text = _current_entry.content + else: + text = _template % [_current_entry.content] + + +func parse_subtitles_file(path: String) -> Error: + _subtitles = [] + var file := FileAccess.open(path, FileAccess.READ) + if not file: + return FAILED + + var state := 0 # 0: read id, 1: read time, 2: read content + var current_id := 0 + var start_time := 0.0 + var end_time := 0.0 + var content := "" + + # Compile regex patterns + var time_regex = RegEx.new() + time_regex.compile("(?[0-9,:]+)\\s*-->\\s*(?[0-9,:]+)") + + while not file.eof_reached(): + var line := file.get_line().strip_edges() + + match state: + 0: # Read ID + if line.is_empty(): + continue + current_id = line.to_int() + state = 1 + + 1: # Read Time + if line.is_empty(): + continue + var result = time_regex.search(line) + if result: + start_time = _parse_time_string(result.get_string("start")) + end_time = _parse_time_string(result.get_string("end")) + state = 2 + + 2: # Read Content + if line.is_empty(): + if not content.is_empty(): + content = _process_content(content) + var entry = SubtitleEntry.new(current_id, start_time, end_time, content) + _subtitles.append(entry) + content = "" + state = 0 + continue + if not content.is_empty(): + content += "\n" + content += line + + if not content.is_empty(): + content = _process_content(content) + var entry = SubtitleEntry.new(current_id, start_time, end_time, content) + _subtitles.append(entry) + + return OK + + +func _parse_time_string(time_str: String) -> float: + var time_split = time_str.replace(",", ".").split(":") + var hours := time_split[0].to_float() + var minutes := time_split[1].to_float() + var seconds := time_split[2].to_float() + return hours * 3600 + minutes * 60 + seconds + + +func _process_content(content: String) -> String: + content = content.replace("", "[b]").replace("", "[/b]").replace("{b}", "[b]").replace("{/b}", "[/b]") + content = content.replace("", "[i]").replace("", "[/i]").replace("{i}", "[i]").replace("{/i}", "[/i]") + content = content.replace("", "[u]").replace("", "[/u]").replace("{u}", "[u]").replace("{/u}", "[/u]") + content = content.replace("", "[/color]") + + var color_regex = RegEx.new() + color_regex.compile("") + content = color_regex.sub(content, "[color=\\1]") + + var line_pos_regex = RegEx.new() + line_pos_regex.compile("\\{\\\\a([0-9]+)\\}") + var matches = line_pos_regex.search_all(content) + for m in matches: + var count = m.get_string(1).to_int() + if count > 0: + content = content.replace(m.get_string(), "\n".repeat(count - 1)) + else: + content = content.replace(m.get_string(), "") + + return content diff --git a/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitles_label.gd.uid b/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitles_label.gd.uid new file mode 100644 index 00000000..803de107 --- /dev/null +++ b/addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitles_label.gd.uid @@ -0,0 +1 @@ +uid://dnjyb6nrg1s02 diff --git a/addons/escoria-ui-return-monkey-island/video_player/video_player.gd b/addons/escoria-ui-return-monkey-island/video_player/video_player.gd index 23abdbcb..e8e9e451 100644 --- a/addons/escoria-ui-return-monkey-island/video_player/video_player.gd +++ b/addons/escoria-ui-return-monkey-island/video_player/video_player.gd @@ -3,8 +3,9 @@ extends Node signal finished -func play(video_file: String): - $VideoStreamPlayer.set_stream(load(video_file)) +func play(video_path: String): + $VideoStreamPlayer.set_stream(load(video_path)) + $VideoStreamPlayer/SubtitlesLabel.parse_subtitles_file(_get_srt_path(video_path)) $VideoStreamPlayer.play() func _on_VideoPlayer_finished(): @@ -17,11 +18,21 @@ func skip(): self.visible = false emit_signal("finished") + func get_player(): return $VideoStreamPlayer + func is_playing() -> bool: var play = $VideoStreamPlayer.is_playing() return play + + func _on_Skip_pressed(): skip() + + +# Get subtitles file path from the video file path. +func _get_srt_path(video_path: String): + var locale = TranslationServer.get_locale() + return video_path.left(-3) + locale + ".srt" diff --git a/addons/escoria-ui-return-monkey-island/video_player/video_player.tscn b/addons/escoria-ui-return-monkey-island/video_player/video_player.tscn index 4941122f..23aa07b1 100644 --- a/addons/escoria-ui-return-monkey-island/video_player/video_player.tscn +++ b/addons/escoria-ui-return-monkey-island/video_player/video_player.tscn @@ -1,10 +1,13 @@ -[gd_scene load_steps=5 format=3 uid="uid://ctg3fukoficqk"] +[gd_scene load_steps=7 format=3 uid="uid://ctg3fukoficqk"] [ext_resource type="Script" uid="uid://ckl3iy3v3v68s" path="res://addons/escoria-ui-return-monkey-island/video_player/video_player.gd" id="1"] [ext_resource type="Theme" uid="uid://bf2eet52fueam" path="res://addons/escoria-ui-return-monkey-island/theme/ui.tres" id="1_384st"] +[ext_resource type="Script" uid="uid://dnjyb6nrg1s02" path="res://addons/escoria-ui-return-monkey-island/video_player/subtitles/subtitles_label.gd" id="SubtitlesLabel"] [sub_resource type="VideoStreamTheora" id="1"] +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_reqeu"] + [sub_resource type="Shortcut" id="3"] [node name="video_player" type="Control"] @@ -27,6 +30,23 @@ offset_right = 1280.0 offset_bottom = 720.0 stream = SubResource("1") +[node name="SubtitlesLabel" type="RichTextLabel" parent="VideoStreamPlayer"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -89.0 +offset_bottom = -2.0 +grow_horizontal = 2 +grow_vertical = 0 +theme_override_font_sizes/normal_font_size = 24 +theme_override_styles/normal = SubResource("StyleBoxEmpty_reqeu") +autowrap_mode = 0 +horizontal_alignment = 1 +script = ExtResource("SubtitlesLabel") +metadata/_custom_type_script = "uid://dnjyb6nrg1s02" + [node name="PanelContainer" type="PanelContainer" parent="."] layout_mode = 1 anchors_preset = 3 diff --git a/gymkhana/videos/turno_cocina/intro.en.srt b/gymkhana/videos/turno_cocina/intro.en.srt new file mode 100644 index 00000000..4d77f4d3 --- /dev/null +++ b/gymkhana/videos/turno_cocina/intro.en.srt @@ -0,0 +1,8 @@ +1 +00:00:00,000 --> 00:00:03,000 +Test + +2 +00:00:05,000 --> 00:00:36,000 +2 + diff --git a/gymkhana/videos/turno_cocina/intro.es.srt b/gymkhana/videos/turno_cocina/intro.es.srt new file mode 100644 index 00000000..9776e344 --- /dev/null +++ b/gymkhana/videos/turno_cocina/intro.es.srt @@ -0,0 +1,13 @@ +1 +00:00:00,000 --> 00:00:03,000 +Test ES + +2 +00:00:05,000 --> 00:00:07,000 +2 ES + +2 +00:00:08,000 --> 00:00:36,000 +Aquí va una línea que es bastante larga, a ver que pasa con ella +Y una seguna línea de regalo + diff --git a/gymkhana/videos/turno_cocina/intro_subs.ogv b/gymkhana/videos/turno_cocina/intro_subs.ogv deleted file mode 100644 index b29d89b0..00000000 Binary files a/gymkhana/videos/turno_cocina/intro_subs.ogv and /dev/null differ diff --git a/gymkhana/videos/turno_cocina/intro_subs.ogv.uid b/gymkhana/videos/turno_cocina/intro_subs.ogv.uid deleted file mode 100644 index 2cbe969b..00000000 --- a/gymkhana/videos/turno_cocina/intro_subs.ogv.uid +++ /dev/null @@ -1 +0,0 @@ -uid://k2q0o6vc54p7