From 3d573f0e70310af1b73136a2614dbf40462bf58c Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sun, 17 Nov 2013 17:21:23 -0800 Subject: [PATCH] Add Split at cursor (at video frame) --- aegisub/src/command/edit.cpp | 58 +++++++++++++++++++++++----------- aegisub/src/subs_edit_ctrl.cpp | 8 +++-- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/aegisub/src/command/edit.cpp b/aegisub/src/command/edit.cpp index db67e008c..47bb3c3c6 100644 --- a/aegisub/src/command/edit.cpp +++ b/aegisub/src/command/edit.cpp @@ -79,6 +79,13 @@ struct validate_sel_nonempty : public Command { } }; +struct validate_video_and_sel_nonempty : public Command { + CMD_TYPE(COMMAND_VALIDATE) + bool Validate(const agi::Context *c) { + return c->videoController->IsLoaded() && !c->selectionController->GetSelectedSet().empty(); + } +}; + struct validate_sel_multiple : public Command { CMD_TYPE(COMMAND_VALIDATE) bool Validate(const agi::Context *c) { @@ -651,33 +658,25 @@ struct edit_line_duplicate : public validate_sel_nonempty { } }; -struct edit_line_duplicate_shift : public Command { +struct edit_line_duplicate_shift : public validate_video_and_sel_nonempty { CMD_NAME("edit/line/split/after") STR_MENU("Split lines after current frame") STR_DISP("Split lines after current frame") STR_HELP("Split the current line into a line which ends on the current frame and a line which starts on the next frame") CMD_TYPE(COMMAND_VALIDATE) - bool Validate(const agi::Context *c) { - return !c->selectionController->GetSelectedSet().empty() && c->videoController->IsLoaded(); - } - void operator()(agi::Context *c) { duplicate_lines(c, 1); } }; -struct edit_line_duplicate_shift_back : public Command { +struct edit_line_duplicate_shift_back : public validate_video_and_sel_nonempty { CMD_NAME("edit/line/split/before") STR_MENU("Split lines before current frame") STR_DISP("Split lines before current frame") STR_HELP("Split the current line into a line which ends on the previous frame and a line which starts on the current frame") CMD_TYPE(COMMAND_VALIDATE) - bool Validate(const agi::Context *c) { - return !c->selectionController->GetSelectedSet().empty() && c->videoController->IsLoaded(); - } - void operator()(agi::Context *c) { duplicate_lines(c, -1); } @@ -992,7 +991,8 @@ struct edit_line_split_by_karaoke : public validate_sel_nonempty { } }; -void split_lines(agi::Context *c, bool estimate) { +template +void split_lines(agi::Context *c, Func&& set_time) { int pos = c->textSelectionController->GetSelectionStart(); AssDialogue *n1 = c->selectionController->GetActiveLine(); @@ -1003,22 +1003,24 @@ void split_lines(agi::Context *c, bool estimate) { n1->Text = boost::trim_right_copy(orig.substr(0, pos)); n2->Text = boost::trim_left_copy(orig.substr(pos)); - if (estimate && orig.size()) { - double splitPos = double(pos) / orig.size(); - n2->Start = n1->End = (int)((n1->End - n1->Start) * splitPos) + n1->Start; - } + set_time(n1, n2); - c->ass->Commit(_("split"), AssFile::COMMIT_DIAG_ADDREM | (estimate ? AssFile::COMMIT_DIAG_FULL : AssFile::COMMIT_DIAG_TEXT)); + c->ass->Commit(_("split"), AssFile::COMMIT_DIAG_ADDREM | AssFile::COMMIT_DIAG_FULL); } -struct edit_line_split_estimate : public validate_sel_nonempty { +struct edit_line_split_estimate : public validate_video_and_sel_nonempty { CMD_NAME("edit/line/split/estimate") STR_MENU("Split at cursor (estimate times)") STR_DISP("Split at cursor (estimate times)") STR_HELP("Split the current line at the cursor, dividing the original line's duration between the new ones") void operator()(agi::Context *c) { - split_lines(c, true); + split_lines(c, [](AssDialogue *n1, AssDialogue *n2) { + size_t len = n1->Text.get().size() + n2->Text.get().size(); + if (!len) return; + double splitPos = double(n1->Text.get().size()) / len; + n2->Start = n1->End = (int)((n1->End - n1->Start) * splitPos) + n1->Start; + }); } }; @@ -1029,7 +1031,24 @@ struct edit_line_split_preserve : public validate_sel_nonempty { STR_HELP("Split the current line at the cursor, setting both lines to the original line's times") void operator()(agi::Context *c) { - split_lines(c, false); + split_lines(c, [](AssDialogue *, AssDialogue *) { }); + } +}; + +struct edit_line_split_video : public validate_video_and_sel_nonempty { + CMD_NAME("edit/line/split/video") + STR_MENU("Split at cursor (at video frame)") + STR_DISP("Split at cursor (at video frame)") + STR_HELP("Split the current line at the cursor, dividing the line's duration at the current video frame") + + void operator()(agi::Context *c) { + split_lines(c, [&](AssDialogue *n1, AssDialogue *n2) { + int cur_frame = mid( + c->videoController->FrameAtTime(n1->Start, agi::vfr::START), + c->videoController->GetFrameN(), + c->videoController->FrameAtTime(n1->End, agi::vfr::END)); + n1->End = n2->Start = c->videoController->TimeAtFrame(cur_frame, agi::vfr::END); + }); } }; @@ -1168,6 +1187,7 @@ namespace cmd { reg(agi::util::make_unique()); reg(agi::util::make_unique()); reg(agi::util::make_unique()); + reg(agi::util::make_unique()); reg(agi::util::make_unique()); reg(agi::util::make_unique()); reg(agi::util::make_unique()); diff --git a/aegisub/src/subs_edit_ctrl.cpp b/aegisub/src/subs_edit_ctrl.cpp index 196c1720f..986534075 100644 --- a/aegisub/src/subs_edit_ctrl.cpp +++ b/aegisub/src/subs_edit_ctrl.cpp @@ -65,6 +65,7 @@ enum { EDIT_MENU_SPLIT_PRESERVE = 1400, EDIT_MENU_SPLIT_ESTIMATE, + EDIT_MENU_SPLIT_VIDEO, EDIT_MENU_CUT, EDIT_MENU_COPY, EDIT_MENU_PASTE, @@ -118,6 +119,7 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxSize wsize, long style, a if (context) { Bind(wxEVT_COMMAND_MENU_SELECTED, bind(&cmd::call, "edit/line/split/preserve", context), EDIT_MENU_SPLIT_PRESERVE); Bind(wxEVT_COMMAND_MENU_SELECTED, bind(&cmd::call, "edit/line/split/estimate", context), EDIT_MENU_SPLIT_ESTIMATE); + Bind(wxEVT_COMMAND_MENU_SELECTED, bind(&cmd::call, "edit/line/split/video", context), EDIT_MENU_SPLIT_VIDEO); } Bind(wxEVT_CONTEXT_MENU, &SubsTextEditCtrl::OnContextMenu, this); @@ -344,8 +346,10 @@ void SubsTextEditCtrl::OnContextMenu(wxContextMenuEvent &event) { // Split if (context) { menu.AppendSeparator(); - menu.Append(EDIT_MENU_SPLIT_PRESERVE,_("Split at cursor (preserve times)")); - menu.Append(EDIT_MENU_SPLIT_ESTIMATE,_("Split at cursor (estimate times)")); + menu.Append(EDIT_MENU_SPLIT_PRESERVE, _("Split at cursor (preserve times)")); + menu.Append(EDIT_MENU_SPLIT_ESTIMATE, _("Split at cursor (estimate times)")); + cmd::Command *split_video = cmd::get("edit/line/split/video"); + menu.Append(EDIT_MENU_SPLIT_VIDEO, split_video->StrMenu(context))->Enable(split_video->Validate(context)); } PopupMenu(&menu);