|
|
|
@@ -43,7 +43,6 @@ SubtitleEditor::SubtitleEditor() : m_repl(8181) {
|
|
|
|
|
m_subtitle_db = load_subtitle_project();
|
|
|
|
|
m_filter = m_filter_placeholder;
|
|
|
|
|
m_filter_hints = m_filter_placeholder;
|
|
|
|
|
m_repl.connect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubtitleEditor::repl_set_continue_point(const std::string_view& continue_point) {
|
|
|
|
@@ -70,6 +69,16 @@ std::string SubtitleEditor::repl_get_process_string(const std::string_view& enti
|
|
|
|
|
process_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 (game-text-id zero) \"{}\" (the-as entity #f) *entity-pool* "
|
|
|
|
|
"(game-task none))",
|
|
|
|
|
hint_name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubtitleEditor::repl_execute_cutscene_code(const SubtitleEditorDB::Entry& entry) {
|
|
|
|
|
// Reset the game first to get to a known state
|
|
|
|
|
repl_reset_game();
|
|
|
|
@@ -150,7 +159,24 @@ void SubtitleEditor::draw_window() {
|
|
|
|
|
draw_edit_options();
|
|
|
|
|
draw_repl_options();
|
|
|
|
|
|
|
|
|
|
draw_current_cutscene();
|
|
|
|
|
if (!m_current_scene) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_selected_text_color);
|
|
|
|
|
}
|
|
|
|
|
if (ImGui::TreeNode("Currently Selected Cutscene")) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
if (m_current_scene) {
|
|
|
|
|
draw_subtitle_options(*m_current_scene, true);
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
|
|
|
|
|
ImGui::Text("Select a Scene from Below!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ImGui::TreeNode("All Cutscenes")) {
|
|
|
|
|
ImGui::InputText("New Scene Name", &m_new_scene_name);
|
|
|
|
@@ -183,13 +209,50 @@ void SubtitleEditor::draw_window() {
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO - hints
|
|
|
|
|
if (ImGui::TreeNode("All Hints")) {
|
|
|
|
|
ImGui::InputText("New Scene Name", &m_new_scene_name);
|
|
|
|
|
// TODO - make this a dropdown
|
|
|
|
|
ImGui::InputText("New Scene ID (hex)", &m_new_scene_id);
|
|
|
|
|
ImGui::InputText("New Scene Group", &m_new_scene_group);
|
|
|
|
|
ImGui::InputText("Filter", &m_filter, ImGuiInputTextFlags_::ImGuiInputTextFlags_AutoSelectAll);
|
|
|
|
|
if (is_scene_in_current_lang(m_new_scene_name)) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("Scene already exists with that name, no!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
if (m_new_scene_group.empty()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("You must provide a group to sort the scene into!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
if (!is_scene_in_current_lang(m_new_scene_name) && !m_new_scene_group.empty()) {
|
|
|
|
|
if (ImGui::Button("Add Scene")) {
|
|
|
|
|
GameSubtitleSceneInfo newScene;
|
|
|
|
|
newScene.m_name = m_new_scene_name;
|
|
|
|
|
if (m_new_scene_id == "0") {
|
|
|
|
|
newScene.m_kind = SubtitleSceneKind::Hint;
|
|
|
|
|
newScene.m_id = strtoul(m_new_scene_id.c_str(), nullptr, 16);
|
|
|
|
|
} else {
|
|
|
|
|
newScene.m_kind = SubtitleSceneKind::HintNamed;
|
|
|
|
|
newScene.m_id = strtoul(m_new_scene_id.c_str(), nullptr, 16);
|
|
|
|
|
}
|
|
|
|
|
newScene.m_sorting_group = m_new_scene_group;
|
|
|
|
|
m_subtitle_db.m_banks.at(m_current_language)->add_scene(newScene);
|
|
|
|
|
m_new_scene_name = "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
draw_all_hint_groups();
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::End();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubtitleEditor::draw_edit_options() {
|
|
|
|
|
if (ImGui::TreeNode("Editing Options")) {
|
|
|
|
|
// TODO - validate these / make it a dropdown
|
|
|
|
|
// - source of truth is the files
|
|
|
|
|
ImGui::InputInt("Editing language ID", &m_current_language);
|
|
|
|
|
ImGui::InputInt("Base language ID", &m_base_language);
|
|
|
|
|
ImGui::Checkbox("Show missing cutscenes from base", &m_base_show_missing_cutscenes);
|
|
|
|
@@ -252,6 +315,17 @@ void SubtitleEditor::draw_all_cutscene_groups() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubtitleEditor::draw_all_hint_groups() {
|
|
|
|
|
for (auto& group_name : m_subtitle_db.m_subtitle_groups->m_group_order) {
|
|
|
|
|
ImGui::SetNextItemOpen(true);
|
|
|
|
|
if (ImGui::TreeNode(group_name.c_str())) {
|
|
|
|
|
draw_all_hints(group_name, false);
|
|
|
|
|
draw_all_hints(group_name, true);
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubtitleEditor::draw_all_scenes(std::string group_name, bool base_cutscenes) {
|
|
|
|
|
auto& scenes =
|
|
|
|
|
m_subtitle_db.m_banks.at(base_cutscenes ? m_base_language : m_current_language)->m_scenes;
|
|
|
|
@@ -279,6 +353,7 @@ void SubtitleEditor::draw_all_scenes(std::string group_name, bool base_cutscenes
|
|
|
|
|
if (base_cutscenes) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ImGui::TreeNode(
|
|
|
|
|
fmt::format("{}-{}", scene_name, base_cutscenes ? m_base_language : m_current_language)
|
|
|
|
|
.c_str(),
|
|
|
|
@@ -296,77 +371,7 @@ void SubtitleEditor::draw_all_scenes(std::string group_name, bool base_cutscenes
|
|
|
|
|
m_subtitle_db.m_banks.at(m_current_language)->add_scene(scene_info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!m_repl.is_connected()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("REPL not connected, can't play!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
} else if (m_db.count(scene_info.m_name) > 0) {
|
|
|
|
|
if (ImGui::Button("Play Scene")) {
|
|
|
|
|
if (m_db.count(scene_info.m_name) == 1) {
|
|
|
|
|
repl_execute_cutscene_code(m_db[scene_info.m_name]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
ImGui::TextWrapped("You may have to click twice, load times cause issues");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|
if (ImGui::BeginCombo("Sorting Group", scene_info.m_sorting_group.c_str())) {
|
|
|
|
|
for (size_t i = 0; i < m_subtitle_db.m_subtitle_groups->m_group_order.size(); ++i) {
|
|
|
|
|
const bool isSelected = (scene_info.m_sorting_group_idx == (int)i);
|
|
|
|
|
if (ImGui::Selectable(m_subtitle_db.m_subtitle_groups->m_group_order[i].c_str(),
|
|
|
|
|
isSelected)) {
|
|
|
|
|
// Remove from current group
|
|
|
|
|
m_subtitle_db.m_subtitle_groups->remove_scene(scene_info.m_sorting_group,
|
|
|
|
|
scene_info.m_name);
|
|
|
|
|
// Add to new group
|
|
|
|
|
scene_info.m_sorting_group_idx = i;
|
|
|
|
|
scene_info.m_sorting_group = m_subtitle_db.m_subtitle_groups->m_group_order.at(i);
|
|
|
|
|
m_subtitle_db.m_subtitle_groups->add_scene(scene_info.m_sorting_group,
|
|
|
|
|
scene_info.m_name);
|
|
|
|
|
}
|
|
|
|
|
if (isSelected) {
|
|
|
|
|
ImGui::SetItemDefaultFocus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < scene_info.m_lines.size(); i++) {
|
|
|
|
|
auto& subtitleLine = scene_info.m_lines.at(i);
|
|
|
|
|
std::string summary;
|
|
|
|
|
if (subtitleLine.line_utf8.empty()) {
|
|
|
|
|
summary = fmt::format("[{}] Clear Screen", subtitleLine.frame);
|
|
|
|
|
} else {
|
|
|
|
|
summary = fmt::format("[{}] {} - '{}...'", subtitleLine.frame, subtitleLine.speaker_utf8,
|
|
|
|
|
subtitleLine.line_utf8.substr(0, 30));
|
|
|
|
|
}
|
|
|
|
|
if (subtitleLine.line_utf8.empty()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
} 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 (subtitleLine.line_utf8.empty() || subtitleLine.offscreen) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
ImGui::InputInt("Starting Frame", &subtitleLine.frame,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsDecimal);
|
|
|
|
|
ImGui::InputText("Speaker", &subtitleLine.speaker_utf8,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsUppercase);
|
|
|
|
|
ImGui::InputText("Text", &subtitleLine.line_utf8,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsUppercase);
|
|
|
|
|
ImGui::Checkbox("Offscreen?", &subtitleLine.offscreen);
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, m_warning_color);
|
|
|
|
|
if (ImGui::Button("Remove Line")) {
|
|
|
|
|
scene_info.m_lines.erase(scene_info.m_lines.begin() + i);
|
|
|
|
|
}
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
} else if (subtitleLine.line_utf8.empty() || subtitleLine.offscreen) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
draw_subtitle_options(scene_info);
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
} else if (base_cutscenes || is_current_scene) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
@@ -374,126 +379,167 @@ void SubtitleEditor::draw_all_scenes(std::string group_name, bool base_cutscenes
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubtitleEditor::draw_current_cutscene() {
|
|
|
|
|
if (!m_current_scene) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_selected_text_color);
|
|
|
|
|
}
|
|
|
|
|
if (ImGui::TreeNode("Currently Selected Movie")) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
if (m_current_scene) {
|
|
|
|
|
if (!m_repl.is_connected()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("REPL not connected, can't play!");
|
|
|
|
|
void SubtitleEditor::draw_all_hints(std::string group_name, bool base_cutscenes) {
|
|
|
|
|
auto& scenes =
|
|
|
|
|
m_subtitle_db.m_banks.at(base_cutscenes ? m_base_language : m_current_language)->m_scenes;
|
|
|
|
|
auto scenes_in_group = m_subtitle_db.m_subtitle_groups->m_groups[group_name];
|
|
|
|
|
for (auto& scene_name : scenes_in_group) {
|
|
|
|
|
if (scenes.count(scene_name) == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto& scene_info = scenes[scene_name];
|
|
|
|
|
// Don't duplicate entries
|
|
|
|
|
if (base_cutscenes && is_scene_in_current_lang(scene_name)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (scene_info.m_kind != SubtitleSceneKind::Hint &&
|
|
|
|
|
scene_info.m_kind != SubtitleSceneKind::HintNamed) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((!m_filter.empty() && m_filter != m_filter_placeholder) &&
|
|
|
|
|
scene_name.find(m_filter) == std::string::npos) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (base_cutscenes) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ImGui::TreeNode(
|
|
|
|
|
fmt::format("{}-{}", scene_name, base_cutscenes ? m_base_language : m_current_language)
|
|
|
|
|
.c_str(),
|
|
|
|
|
"%s", scene_name.c_str())) {
|
|
|
|
|
if (base_cutscenes) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
} else if (m_db.count(m_current_scene->m_name) > 0) {
|
|
|
|
|
if (ImGui::Button("Play Scene")) {
|
|
|
|
|
if (m_db.count(m_current_scene->m_name) == 1) {
|
|
|
|
|
repl_execute_cutscene_code(m_db[m_current_scene->m_name]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
ImGui::TextWrapped("You may have to click twice, load times cause issues");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|
if (ImGui::BeginCombo("Sorting Group", m_current_scene->m_sorting_group.c_str())) {
|
|
|
|
|
for (size_t i = 0; i < m_subtitle_db.m_subtitle_groups->m_group_order.size(); ++i) {
|
|
|
|
|
const bool isSelected = (m_current_scene->m_sorting_group_idx == (int)i);
|
|
|
|
|
if (ImGui::Selectable(m_subtitle_db.m_subtitle_groups->m_group_order[i].c_str(),
|
|
|
|
|
isSelected)) {
|
|
|
|
|
// Remove from current group
|
|
|
|
|
m_subtitle_db.m_subtitle_groups->remove_scene(m_current_scene->m_sorting_group,
|
|
|
|
|
m_current_scene->m_name);
|
|
|
|
|
// Add to new group
|
|
|
|
|
m_current_scene->m_sorting_group_idx = i;
|
|
|
|
|
m_current_scene->m_sorting_group = m_subtitle_db.m_subtitle_groups->m_group_order.at(i);
|
|
|
|
|
m_subtitle_db.m_subtitle_groups->add_scene(m_current_scene->m_sorting_group,
|
|
|
|
|
m_current_scene->m_name);
|
|
|
|
|
}
|
|
|
|
|
if (isSelected) {
|
|
|
|
|
ImGui::SetItemDefaultFocus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
|
}
|
|
|
|
|
ImGui::InputInt("Frame Number", &m_current_scene_frame,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsDecimal);
|
|
|
|
|
ImGui::InputText("Text", &m_current_scene_text,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsUppercase);
|
|
|
|
|
ImGui::InputText("Speaker", &m_current_scene_speaker,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsUppercase);
|
|
|
|
|
ImGui::Checkbox("Offscreen", &m_current_scene_offscreen);
|
|
|
|
|
bool rendered_text_entry_btn = false;
|
|
|
|
|
if (m_current_scene_frame < 0 || m_current_scene_text.empty() ||
|
|
|
|
|
m_current_scene_speaker.empty()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("Can't add a new text entry with the current fields!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
} else {
|
|
|
|
|
rendered_text_entry_btn = true;
|
|
|
|
|
if (ImGui::Button("Add Text Entry")) {
|
|
|
|
|
m_current_scene->add_line(m_current_scene_frame, "", m_current_scene_text, "",
|
|
|
|
|
m_current_scene_speaker, m_current_scene_offscreen);
|
|
|
|
|
if (base_cutscenes) {
|
|
|
|
|
if (ImGui::Button("Copy from Base Language")) {
|
|
|
|
|
m_subtitle_db.m_banks.at(m_current_language)->add_scene(scene_info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (m_current_scene_frame < 0) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("Can't add a clear screen entry with the current fields!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
} else {
|
|
|
|
|
if (rendered_text_entry_btn) {
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Add Clear Screen Entry")) {
|
|
|
|
|
m_current_scene->add_line(m_current_scene_frame, "", "", "", "", false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
for (size_t i = 0; i < m_current_scene->m_lines.size(); i++) {
|
|
|
|
|
auto& subtitleLine = m_current_scene->m_lines.at(i);
|
|
|
|
|
std::string summary;
|
|
|
|
|
if (subtitleLine.line_utf8.empty()) {
|
|
|
|
|
summary = fmt::format("[{}] Clear Screen", subtitleLine.frame);
|
|
|
|
|
} else {
|
|
|
|
|
summary = fmt::format("[{}] {} - '{}...'", subtitleLine.frame, subtitleLine.speaker_utf8,
|
|
|
|
|
subtitleLine.line_utf8.substr(0, 30));
|
|
|
|
|
}
|
|
|
|
|
if (subtitleLine.line_utf8.empty()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
} 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 (subtitleLine.line_utf8.empty() || subtitleLine.offscreen) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
ImGui::InputInt("Starting Frame", &subtitleLine.frame,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsDecimal);
|
|
|
|
|
ImGui::InputText("Speaker", &subtitleLine.speaker_utf8,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsUppercase);
|
|
|
|
|
ImGui::InputText("Text", &subtitleLine.line_utf8,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsUppercase);
|
|
|
|
|
ImGui::Checkbox("Offscreen?", &subtitleLine.offscreen);
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, m_warning_color);
|
|
|
|
|
if (ImGui::Button("Remove Line")) {
|
|
|
|
|
m_current_scene->m_lines.erase(m_current_scene->m_lines.begin() + i);
|
|
|
|
|
}
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
} else if (subtitleLine.line_utf8.empty() || subtitleLine.offscreen) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
|
|
|
|
|
ImGui::Text("Select a Scene from Below!");
|
|
|
|
|
draw_subtitle_options(scene_info);
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
} else if (base_cutscenes) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubtitleEditor::draw_subtitle_options(GameSubtitleSceneInfo& scene, bool current_scene) {
|
|
|
|
|
if (!m_repl.is_connected()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("REPL not connected, can't play!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
} else {
|
|
|
|
|
// Cutscenes
|
|
|
|
|
if (scene.m_kind == SubtitleSceneKind::Movie && m_db.count(scene.m_name) > 0) {
|
|
|
|
|
if (ImGui::Button("Play Scene")) {
|
|
|
|
|
repl_execute_cutscene_code(m_db[scene.m_name]);
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
ImGui::TextWrapped("You may have to click twice, load times cause issues");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|
// Hints
|
|
|
|
|
else if (scene.m_kind == SubtitleSceneKind::Hint ||
|
|
|
|
|
scene.m_kind == SubtitleSceneKind::HintNamed) {
|
|
|
|
|
if (ImGui::Button("Play Hint")) {
|
|
|
|
|
repl_play_hint(scene.m_name);
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
ImGui::TextWrapped("You may have to click twice, load times cause issues");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ImGui::BeginCombo("Sorting Group", scene.m_sorting_group.c_str())) {
|
|
|
|
|
for (size_t i = 0; i < m_subtitle_db.m_subtitle_groups->m_group_order.size(); ++i) {
|
|
|
|
|
const bool isSelected = (scene.m_sorting_group_idx == (int)i);
|
|
|
|
|
if (ImGui::Selectable(m_subtitle_db.m_subtitle_groups->m_group_order[i].c_str(),
|
|
|
|
|
isSelected)) {
|
|
|
|
|
// Remove from current group
|
|
|
|
|
m_subtitle_db.m_subtitle_groups->remove_scene(scene.m_sorting_group, scene.m_name);
|
|
|
|
|
// Add to new group
|
|
|
|
|
scene.m_sorting_group_idx = i;
|
|
|
|
|
scene.m_sorting_group = m_subtitle_db.m_subtitle_groups->m_group_order.at(i);
|
|
|
|
|
m_subtitle_db.m_subtitle_groups->add_scene(scene.m_sorting_group, scene.m_name);
|
|
|
|
|
}
|
|
|
|
|
if (isSelected) {
|
|
|
|
|
ImGui::SetItemDefaultFocus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
|
}
|
|
|
|
|
if (current_scene) {
|
|
|
|
|
draw_new_cutscene_line_form();
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < scene.m_lines.size(); i++) {
|
|
|
|
|
auto& subtitleLine = scene.m_lines.at(i);
|
|
|
|
|
std::string summary;
|
|
|
|
|
if (subtitleLine.line_utf8.empty()) {
|
|
|
|
|
summary = fmt::format("[{}] Clear Screen", subtitleLine.frame);
|
|
|
|
|
} else {
|
|
|
|
|
summary = fmt::format("[{}] {} - '{}...'", subtitleLine.frame, subtitleLine.speaker_utf8,
|
|
|
|
|
subtitleLine.line_utf8.substr(0, 30));
|
|
|
|
|
}
|
|
|
|
|
if (subtitleLine.line_utf8.empty()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color);
|
|
|
|
|
} 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 (subtitleLine.line_utf8.empty() || subtitleLine.offscreen) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
ImGui::InputInt("Starting Frame", &subtitleLine.frame,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsDecimal);
|
|
|
|
|
ImGui::InputText("Speaker", &subtitleLine.speaker_utf8);
|
|
|
|
|
ImGui::InputText("Text", &subtitleLine.line_utf8);
|
|
|
|
|
ImGui::Checkbox("Offscreen?", &subtitleLine.offscreen);
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, m_warning_color);
|
|
|
|
|
if (ImGui::Button("Remove Line")) {
|
|
|
|
|
scene.m_lines.erase(scene.m_lines.begin() + i);
|
|
|
|
|
}
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
|
} else if (subtitleLine.line_utf8.empty() || subtitleLine.offscreen) {
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubtitleEditor::draw_new_cutscene_line_form() {
|
|
|
|
|
ImGui::InputInt("Frame Number", &m_current_scene_frame,
|
|
|
|
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_CharsDecimal);
|
|
|
|
|
ImGui::InputText("Text", &m_current_scene_text);
|
|
|
|
|
ImGui::InputText("Speaker", &m_current_scene_speaker);
|
|
|
|
|
ImGui::Checkbox("Offscreen", &m_current_scene_offscreen);
|
|
|
|
|
bool rendered_text_entry_btn = false;
|
|
|
|
|
if (m_current_scene_frame < 0 || m_current_scene_text.empty() ||
|
|
|
|
|
m_current_scene_speaker.empty()) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("Can't add a new text entry with the current fields!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
} else {
|
|
|
|
|
rendered_text_entry_btn = true;
|
|
|
|
|
if (ImGui::Button("Add Text Entry")) {
|
|
|
|
|
m_current_scene->add_line(m_current_scene_frame, "", m_current_scene_text, "",
|
|
|
|
|
m_current_scene_speaker, m_current_scene_offscreen);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (m_current_scene_frame < 0) {
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, m_error_text_color);
|
|
|
|
|
ImGui::Text("Can't add a clear screen entry with the current fields!");
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
} else {
|
|
|
|
|
if (rendered_text_entry_btn) {
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Add Clear Screen Entry")) {
|
|
|
|
|
m_current_scene->add_line(m_current_scene_frame, "", "", "", "", false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|