diff --git a/common/serialization/subtitles/subtitles_ser.cpp b/common/serialization/subtitles/subtitles_ser.cpp index 36619a8bc2..91da5b6d3b 100644 --- a/common/serialization/subtitles/subtitles_ser.cpp +++ b/common/serialization/subtitles/subtitles_ser.cpp @@ -468,7 +468,7 @@ void open_text_project(const std::string& kind, }); } -GameSubtitleDB load_subtitle_project() { +GameSubtitleDB load_subtitle_project(GameVersion game_version) { // Load the subtitle files GameSubtitleDB db; db.m_subtitle_groups = std::make_unique(); @@ -476,8 +476,9 @@ GameSubtitleDB load_subtitle_project() { try { goos::Reader reader; std::vector inputs; - std::string subtitle_project = - (file_util::get_jak_project_dir() / "game" / "assets" / "game_subtitle.gp").string(); + std::string subtitle_project = (file_util::get_jak_project_dir() / "game" / "assets" / + version_to_game_name(game_version) / "game_subtitle.gp") + .string(); open_text_project("subtitle", subtitle_project, inputs); for (auto& filename : inputs) { auto code = reader.read_from_file({filename}); diff --git a/common/serialization/subtitles/subtitles_ser.h b/common/serialization/subtitles/subtitles_ser.h index ec1c85b891..5bdf483c99 100644 --- a/common/serialization/subtitles/subtitles_ser.h +++ b/common/serialization/subtitles/subtitles_ser.h @@ -11,6 +11,7 @@ #include "common/log/log.h" #include "common/util/Assert.h" #include "common/util/FontUtils.h" +#include "common/versions/versions.h" /*! * The text bank contains all lines (accessed with an ID) for a language. @@ -191,4 +192,4 @@ GameTextVersion parse_text_only_version(const goos::Object& data); void open_text_project(const std::string& kind, const std::string& filename, std::vector& inputs); -GameSubtitleDB load_subtitle_project(); +GameSubtitleDB load_subtitle_project(GameVersion game_version); diff --git a/game/assets/jak1/subtitle/subtitle-groups.json b/game/assets/jak1/subtitle/subtitle-groups.json index b61d6cdc1e..e7909e9c6f 100644 --- a/game/assets/jak1/subtitle/subtitle-groups.json +++ b/game/assets/jak1/subtitle/subtitle-groups.json @@ -539,7 +539,9 @@ "sagevb38", "sagevb39" ], - "uncategorized": [], + "uncategorized": [ + "evilbro-misty-end" + ], "village1": [ "ASSTLP01", "ASSTLP02", diff --git a/game/tools/subtitles/subtitle_editor.cpp b/game/tools/subtitles/subtitle_editor.cpp index df955bb90d..3ad5f728b9 100644 --- a/game/tools/subtitles/subtitle_editor.cpp +++ b/game/tools/subtitles/subtitle_editor.cpp @@ -7,13 +7,14 @@ #include "common/util/FileUtil.h" #include "common/util/json_util.h" +#include "game/runtime.h" + #include "third-party/fmt/core.h" #include "third-party/imgui/imgui.h" #include "third-party/imgui/imgui_stdlib.h" SubtitleEditor::SubtitleEditor() : m_repl(8181) { update_subtitle_editor_db(); - m_subtitle_db = load_subtitle_project(); m_filter = m_filter_placeholder; m_filter_hints = m_filter_placeholder; } @@ -44,8 +45,6 @@ std::string SubtitleEditor::repl_get_process_string(const std::string_view& enti void SubtitleEditor::repl_play_hint(const std::string_view& hint_name) { repl_reset_game(); - // repl_set_continue_point("village1-hut"); - // TODO - move into water fountain m_repl.eval( fmt::format("(level-hint-spawn (text-id zero) \"{}\" (the-as entity #f) *entity-pool* " "(game-task none))", @@ -123,6 +122,15 @@ bool SubtitleEditor::is_scene_in_current_lang(const std::string& scene_name) { void SubtitleEditor::draw_window() { ImGui::Begin("Subtitle Editor"); + if (!db_loaded) { + if (ImGui::Button("Load Subtitles")) { + m_subtitle_db = load_subtitle_project(g_game_version); + db_loaded = true; + } + ImGui::End(); + return; + } + if (ImGui::Button("Save Changes")) { m_files_saved_successfully = std::make_optional(write_subtitle_db_to_files(m_subtitle_db)); repl_rebuild_text(); @@ -604,51 +612,54 @@ void SubtitleEditor::draw_subtitle_options(GameSubtitleSceneInfo& scene, bool cu } auto font = get_font_bank(parse_text_only_version(m_subtitle_db.m_banks[m_current_language]->file_path)); - for (size_t i = 0; i < scene.m_lines.size(); i++) { - auto& subtitleLine = scene.m_lines.at(i); - auto linetext = font->convert_game_to_utf8(subtitleLine.line.c_str()); - auto linespkr = font->convert_game_to_utf8(subtitleLine.speaker.c_str()); + int i = 0; + for (auto subtitleLine = scene.m_lines.begin(); subtitleLine != scene.m_lines.end();) { + auto linetext = font->convert_game_to_utf8(subtitleLine->line.c_str()); + auto linespkr = font->convert_game_to_utf8(subtitleLine->speaker.c_str()); std::string summary; if (linetext.empty()) { - summary = fmt::format("[{}] Clear Screen", subtitleLine.frame); + summary = fmt::format("[{}] Clear Screen", subtitleLine->frame); } else if (linetext.length() >= 30) { summary = - fmt::format("[{}] {} - '{}...'", subtitleLine.frame, linespkr, linetext.substr(0, 30)); + fmt::format("[{}] {} - '{}...'", subtitleLine->frame, linespkr, linetext.substr(0, 30)); } else { - summary = fmt::format("[{}] {} - '{}'", subtitleLine.frame, linespkr, linetext.substr(0, 30)); + summary = + fmt::format("[{}] {} - '{}'", subtitleLine->frame, linespkr, linetext.substr(0, 30)); } if (linetext.empty()) { ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color); - } else if (subtitleLine.offscreen) { + } else if (subtitleLine->offscreen) { ImGui::PushStyleColor(ImGuiCol_Text, m_offscreen_text_color); } if (ImGui::TreeNode(fmt::format("{}", i).c_str(), "%s", summary.c_str())) { - if (linetext.empty() || subtitleLine.offscreen) { + if (linetext.empty() || subtitleLine->offscreen) { ImGui::PopStyleColor(); } - ImGui::InputInt("Starting Frame", &subtitleLine.frame, + ImGui::InputInt("Starting Frame", &subtitleLine->frame, ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsDecimal); ImGui::InputText("Speaker", &linespkr); ImGui::InputText("Text", &linetext); - ImGui::Checkbox("Offscreen?", &subtitleLine.offscreen); - // TODO - deleting while iterating is a bad pattern, especially with imgui's declarative - // style - // disabling this for now, it's not working in it's current state. - // if (scene.m_lines.size() > 1) { // prevent creating an empty scene - // ImGui::PushStyleColor(ImGuiCol_Button, m_warning_color); - // if (ImGui::Button("Remove Line")) { - // scene.m_lines.erase(scene.m_lines.begin() + i); - // } - // ImGui::PopStyleColor(); - //} + ImGui::Checkbox("Offscreen?", &subtitleLine->offscreen); + if (scene.m_lines.size() > 1) { // prevent creating an empty scene + ImGui::PushStyleColor(ImGuiCol_Button, m_warning_color); + if (ImGui::Button("Remove")) { + subtitleLine = scene.m_lines.erase(subtitleLine); + ImGui::PopStyleColor(); + ImGui::TreePop(); + continue; + } + ImGui::PopStyleColor(); + } ImGui::TreePop(); - } else if (linetext.empty() || subtitleLine.offscreen) { + } else if (linetext.empty() || subtitleLine->offscreen) { ImGui::PopStyleColor(); } auto newtext = font->convert_utf8_to_game(linetext, true); auto newspkr = font->convert_utf8_to_game(linespkr, true); - subtitleLine.line = newtext; - subtitleLine.speaker = newspkr; + subtitleLine->line = newtext; + subtitleLine->speaker = newspkr; + i++; + subtitleLine++; } } diff --git a/game/tools/subtitles/subtitle_editor.h b/game/tools/subtitles/subtitle_editor.h index 655e16355d..b2be02dfdf 100644 --- a/game/tools/subtitles/subtitle_editor.h +++ b/game/tools/subtitles/subtitle_editor.h @@ -46,6 +46,8 @@ class SubtitleEditor { void draw_all_hint_groups(); void draw_all_hints(std::string group_name, bool base_cutscenes); + bool db_loaded = false; + GameSubtitleDB m_subtitle_db; std::map m_db = {}; GameSubtitleSceneInfo* m_current_scene = nullptr;