From 6285e4e277668faccae2ea08c2d0b42dc1cc6e21 Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:19:29 +0100 Subject: [PATCH 01/25] Add video panning --- src/video_display.cpp | 24 ++++++++++++++++++++++-- src/video_display.h | 9 +++++++++ src/visual_tool_cross.cpp | 4 ++-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 00e3081121..dba59b4135 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -119,6 +119,8 @@ VideoDisplay::VideoDisplay(wxToolBar *toolbar, bool freeSize, wxComboBox *zoomBo Bind(wxEVT_LEFT_DCLICK, &VideoDisplay::OnMouseEvent, this); Bind(wxEVT_LEFT_DOWN, &VideoDisplay::OnMouseEvent, this); Bind(wxEVT_LEFT_UP, &VideoDisplay::OnMouseEvent, this); + Bind(wxEVT_MIDDLE_DOWN, &VideoDisplay::OnMouseEvent, this); + Bind(wxEVT_MIDDLE_UP, &VideoDisplay::OnMouseEvent, this); Bind(wxEVT_MOTION, &VideoDisplay::OnMouseEvent, this); Bind(wxEVT_MOUSEWHEEL, &VideoDisplay::OnMouseWheel, this); @@ -210,7 +212,7 @@ void VideoDisplay::DoRender() try { PositionVideo(); videoOut->Render(viewport_left, viewport_bottom, viewport_width, viewport_height); - E(glViewport(0, std::min(viewport_bottom, 0), videoSize.GetWidth(), videoSize.GetHeight())); + E(glViewport(0, viewport_bottom, videoSize.GetWidth(), videoSize.GetHeight())); E(glMatrixMode(GL_PROJECTION)); E(glLoadIdentity()); @@ -315,6 +317,9 @@ void VideoDisplay::PositionVideo() { } } + viewport_left += pan_x; + viewport_bottom -= pan_y; + if (tool) tool->SetDisplayArea(viewport_left / scale_factor, viewport_top / scale_factor, viewport_width / scale_factor, viewport_height / scale_factor); @@ -370,8 +375,23 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) { last_mouse_pos = mouse_pos = event.GetPosition(); - if (tool) + if (event.GetButton() == wxMOUSE_BTN_MIDDLE) { + if ((panning = event.ButtonDown())) + pan_last_pos = event.GetPosition(); + } + if (panning && event.Dragging()) { + pan_x += event.GetX() - pan_last_pos.X(); + pan_y += event.GetY() - pan_last_pos.Y(); + pan_last_pos = event.GetPosition(); + + PositionVideo(); + } + + if (tool) { + if (pan_y) + event.SetPosition(wxPoint(event.GetX(), event.GetY() - pan_y)); tool->OnMouseEvent(event); + } } void VideoDisplay::OnMouseLeave(wxMouseEvent& event) { diff --git a/src/video_display.h b/src/video_display.h index 62113e5534..1e53a26e49 100644 --- a/src/video_display.h +++ b/src/video_display.h @@ -87,6 +87,15 @@ class VideoDisplay final : public wxGLCanvas { /// The current zoom level, where 1.0 = 100% double zoomValue; + /// The last position of the mouse, when dragging + Vector2D pan_last_pos; + /// True if middle mouse button is down, and we should update pan_{x,y} + bool panning = false; + /// The current video pan offset width + int pan_x = 0; + /// The current video pan offset height + int pan_y = 0; + /// The video renderer std::unique_ptr videoOut; diff --git a/src/visual_tool_cross.cpp b/src/visual_tool_cross.cpp index ffbf5329b3..624cd76139 100644 --- a/src/visual_tool_cross.cpp +++ b/src/visual_tool_cross.cpp @@ -69,8 +69,8 @@ void VisualToolCross::Draw() { gl.SetInvert(); gl.SetLineColour(*wxWHITE, 1.0, 1); float lines[] = { - 0.f, mouse_pos.Y(), - video_res.X() + video_pos.X() * 2, mouse_pos.Y(), + video_pos.X(), mouse_pos.Y(), + video_res.X() + video_pos.X(), mouse_pos.Y(), mouse_pos.X(), 0.f, mouse_pos.X(), video_res.Y() + video_pos.Y() * 2 }; From 4b59099a8e785ff2b25df2e3db0432117f9bda9a Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:21:02 +0100 Subject: [PATCH 02/25] Add menu item for resetting the video pan --- src/command/video.cpp | 12 ++++++++++++ src/libresrc/default_menu.json | 1 + src/video_display.cpp | 5 +++++ src/video_display.h | 3 +++ 4 files changed, 21 insertions(+) diff --git a/src/command/video.cpp b/src/command/video.cpp index c0499a38cd..bd9ee22485 100644 --- a/src/command/video.cpp +++ b/src/command/video.cpp @@ -603,6 +603,17 @@ struct video_opt_autoscroll final : public Command { } }; +struct video_pan_reset final : public validator_video_loaded { + CMD_NAME("video/pan_reset") + STR_MENU("Reset video pan") + STR_DISP("Reset video pan") + STR_HELP("Reset the video pan to the original value") + + void operator()(agi::Context *c) override { + c->videoDisplay->ResetPan(); + } +}; + struct video_play final : public validator_video_loaded { CMD_NAME("video/play") CMD_ICON(button_play) @@ -767,6 +778,7 @@ namespace cmd { reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); + reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); diff --git a/src/libresrc/default_menu.json b/src/libresrc/default_menu.json index f213feff3b..1c885af3ed 100644 --- a/src/libresrc/default_menu.json +++ b/src/libresrc/default_menu.json @@ -157,6 +157,7 @@ { "submenu" : "main/video/set zoom", "text" : "Set &Zoom" }, { "submenu" : "main/video/override ar", "text" : "Override &AR" }, { "command" : "video/show_overscan" }, + { "command" : "video/pan_reset" }, {}, { "command" : "video/jump" }, { "command" : "video/jump/start" }, diff --git a/src/video_display.cpp b/src/video_display.cpp index dba59b4135..8edbfbf889 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -417,6 +417,11 @@ void VideoDisplay::OnKeyDown(wxKeyEvent &event) { hotkey::check("Video", con, event); } +void VideoDisplay::ResetPan() { + pan_x = pan_y = 0; + PositionVideo(); +} + void VideoDisplay::SetZoom(double value) { if (value == 0) return; zoomValue = std::max(value, .125); diff --git a/src/video_display.h b/src/video_display.h index 1e53a26e49..4db0635aa7 100644 --- a/src/video_display.h +++ b/src/video_display.h @@ -173,6 +173,9 @@ class VideoDisplay final : public wxGLCanvas { /// @brief Get the current zoom level double GetZoom() const { return zoomValue; } + /// @brief Reset the video pan + void ResetPan(); + /// Get the last seen position of the mouse in script coordinates Vector2D GetMousePosition() const; From 51dafe2917a741a937ce86effd046733a7c741ea Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:31:43 +0100 Subject: [PATCH 03/25] Change tab to spaces --- src/libresrc/default_menu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libresrc/default_menu.json b/src/libresrc/default_menu.json index 1c885af3ed..a6d969a755 100644 --- a/src/libresrc/default_menu.json +++ b/src/libresrc/default_menu.json @@ -157,7 +157,7 @@ { "submenu" : "main/video/set zoom", "text" : "Set &Zoom" }, { "submenu" : "main/video/override ar", "text" : "Override &AR" }, { "command" : "video/show_overscan" }, - { "command" : "video/pan_reset" }, + { "command" : "video/pan_reset" }, {}, { "command" : "video/jump" }, { "command" : "video/jump/start" }, From d78dace12205a84e6c22d8050309839ca79463ec Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 25 Nov 2020 10:54:37 +0100 Subject: [PATCH 04/25] Fix mouse position bug when videoAr > displayAr Crosshair drawing is broken when videoAr != displayAr --- src/video_display.cpp | 19 +++++++++++-------- src/video_display.h | 2 ++ src/visual_tool.cpp | 4 ++++ src/visual_tool.h | 2 ++ src/visual_tool_cross.cpp | 6 +++--- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 8edbfbf889..6016133103 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -212,7 +212,7 @@ void VideoDisplay::DoRender() try { PositionVideo(); videoOut->Render(viewport_left, viewport_bottom, viewport_width, viewport_height); - E(glViewport(0, viewport_bottom, videoSize.GetWidth(), videoSize.GetHeight())); + E(glViewport(0, viewport_bottom_end, videoSize.GetWidth(), videoSize.GetHeight())); E(glMatrixMode(GL_PROJECTION)); E(glLoadIdentity()); @@ -289,8 +289,11 @@ void VideoDisplay::PositionVideo() { auto provider = con->project->VideoProvider(); if (!provider || !IsShownOnScreen()) return; + int client_w, client_h; + GetClientSize(&client_w, &client_h); + viewport_left = 0; - viewport_bottom = GetClientSize().GetHeight() * scale_factor - videoSize.GetHeight(); + viewport_bottom_end = viewport_bottom = client_h * scale_factor - videoSize.GetHeight(); viewport_top = 0; viewport_width = videoSize.GetWidth(); viewport_height = videoSize.GetHeight(); @@ -318,12 +321,15 @@ void VideoDisplay::PositionVideo() { } viewport_left += pan_x; + viewport_top += pan_y; viewport_bottom -= pan_y; + viewport_bottom_end = std::min(viewport_bottom_end, 0); - if (tool) + if (tool) { + tool->SetClientSize(viewport_width, viewport_height); tool->SetDisplayArea(viewport_left / scale_factor, viewport_top / scale_factor, viewport_width / scale_factor, viewport_height / scale_factor); - + } Render(); } @@ -387,11 +393,8 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) { PositionVideo(); } - if (tool) { - if (pan_y) - event.SetPosition(wxPoint(event.GetX(), event.GetY() - pan_y)); + if (tool) tool->OnMouseEvent(event); - } } void VideoDisplay::OnMouseLeave(wxMouseEvent& event) { diff --git a/src/video_display.h b/src/video_display.h index 4db0635aa7..2c80eb583c 100644 --- a/src/video_display.h +++ b/src/video_display.h @@ -79,6 +79,8 @@ class VideoDisplay final : public wxGLCanvas { int viewport_width = 0; /// Screen pixels between the bottom of the canvas and the bottom of the video; used for glViewport int viewport_bottom = 0; + /// The REAL bottom of the viewport; used only for glViewport + int viewport_bottom_end = 0; /// Screen pixels between the bottom of the canvas and the top of the video; used for coordinate space conversion int viewport_top = 0; /// The height of the video in screen pixels diff --git a/src/visual_tool.cpp b/src/visual_tool.cpp index 61d3207226..6465fe2484 100644 --- a/src/visual_tool.cpp +++ b/src/visual_tool.cpp @@ -132,6 +132,10 @@ AssDialogue* VisualToolBase::GetActiveDialogueLine() { return nullptr; } +void VisualToolBase::SetClientSize(int w, int h) { + client_size = Vector2D(w, h); +} + void VisualToolBase::SetDisplayArea(int x, int y, int w, int h) { if (x == video_pos.X() && y == video_pos.Y() && w == video_res.X() && h == video_res.Y()) return; diff --git a/src/visual_tool.h b/src/visual_tool.h index 72eec42249..15d0b007dc 100644 --- a/src/visual_tool.h +++ b/src/visual_tool.h @@ -104,6 +104,7 @@ class VisualToolBase { Vector2D script_res; ///< Script resolution Vector2D video_pos; ///< Top-left corner of the video in the display area Vector2D video_res; ///< Video resolution + Vector2D client_size; ///< The size of the display area const agi::OptionValue *highlight_color_primary_opt; const agi::OptionValue *highlight_color_secondary_opt; @@ -144,6 +145,7 @@ class VisualToolBase { // Stuff called by VideoDisplay virtual void OnMouseEvent(wxMouseEvent &event)=0; virtual void Draw()=0; + virtual void SetClientSize(int w, int h); virtual void SetDisplayArea(int x, int y, int w, int h); virtual void SetToolbar(wxToolBar *) { } virtual ~VisualToolBase() = default; diff --git a/src/visual_tool_cross.cpp b/src/visual_tool_cross.cpp index 624cd76139..87783c616f 100644 --- a/src/visual_tool_cross.cpp +++ b/src/visual_tool_cross.cpp @@ -69,10 +69,10 @@ void VisualToolCross::Draw() { gl.SetInvert(); gl.SetLineColour(*wxWHITE, 1.0, 1); float lines[] = { - video_pos.X(), mouse_pos.Y(), - video_res.X() + video_pos.X(), mouse_pos.Y(), + 0.f, mouse_pos.Y(), + client_size.X(), mouse_pos.Y(), mouse_pos.X(), 0.f, - mouse_pos.X(), video_res.Y() + video_pos.Y() * 2 + mouse_pos.X(), client_size.Y(), }; gl.DrawLines(2, lines, 4); gl.ClearInvert(); From bb65a63288c35b5727a2b955fa7299b1266d8a60 Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 25 Nov 2020 19:36:05 +0100 Subject: [PATCH 05/25] Fix crosshair drawing I'm not sure about that scale_factor, i don't know how to test that --- src/video_display.cpp | 2 +- src/visual_tool_cross.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 6016133103..f40cd013c0 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -326,7 +326,7 @@ void VideoDisplay::PositionVideo() { viewport_bottom_end = std::min(viewport_bottom_end, 0); if (tool) { - tool->SetClientSize(viewport_width, viewport_height); + tool->SetClientSize(client_w * scale_factor, client_h * scale_factor); tool->SetDisplayArea(viewport_left / scale_factor, viewport_top / scale_factor, viewport_width / scale_factor, viewport_height / scale_factor); } diff --git a/src/visual_tool_cross.cpp b/src/visual_tool_cross.cpp index 87783c616f..ae82be7750 100644 --- a/src/visual_tool_cross.cpp +++ b/src/visual_tool_cross.cpp @@ -87,12 +87,12 @@ void VisualToolCross::Draw() { // Place the text in the corner of the cross closest to the center of the video int dx = mouse_pos.X(); int dy = mouse_pos.Y(); - if (dx > video_res.X() / 2) + if (dx > client_size.X() / 2) dx -= tw + 4; else dx += 4; - if (dy < video_res.Y() / 2) + if (dy < client_size.Y() / 2) dy += 3; else dy -= th + 3; From 41d8819eed0776510e184692c078c765c6c7acbc Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 25 Nov 2020 19:40:28 +0100 Subject: [PATCH 06/25] Change pan values with the zoom level changes --- src/video_display.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video_display.cpp b/src/video_display.cpp index f40cd013c0..8b2776fa74 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -427,6 +427,8 @@ void VideoDisplay::ResetPan() { void VideoDisplay::SetZoom(double value) { if (value == 0) return; + pan_x *= value / zoomValue; + pan_y *= value / zoomValue; zoomValue = std::max(value, .125); size_t selIndex = zoomValue / .125 - 1; if (selIndex < zoomBox->GetCount()) From da7154b624437c904f32c24c35417253bdaa614b Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 25 Nov 2020 19:49:28 +0100 Subject: [PATCH 07/25] Respect min. zoom value when changing pan coords --- src/video_display.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 8b2776fa74..9590dfc9c6 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -427,9 +427,10 @@ void VideoDisplay::ResetPan() { void VideoDisplay::SetZoom(double value) { if (value == 0) return; + value = std::max(value, .125); pan_x *= value / zoomValue; pan_y *= value / zoomValue; - zoomValue = std::max(value, .125); + zoomValue = value; size_t selIndex = zoomValue / .125 - 1; if (selIndex < zoomBox->GetCount()) zoomBox->SetSelection(selIndex); From b385aa0f4ffccdc7368376b2d88f8bcf6513cd8e Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 21 Apr 2021 00:19:51 +0200 Subject: [PATCH 08/25] Make video zoom different from preview window zoom --- src/command/video.cpp | 10 ++--- src/frame_main.cpp | 4 +- src/project.cpp | 2 +- src/video_display.cpp | 93 +++++++++++++++++++++++++++---------------- src/video_display.h | 13 +++--- 5 files changed, 74 insertions(+), 48 deletions(-) diff --git a/src/command/video.cpp b/src/command/video.cpp index bd9ee22485..db9f7dcd91 100644 --- a/src/command/video.cpp +++ b/src/command/video.cpp @@ -669,7 +669,7 @@ class video_zoom_100: public validator_video_attached { void operator()(agi::Context *c) override { c->videoController->Stop(); - c->videoDisplay->SetZoom(1.); + c->videoDisplay->SetWindowZoom(1.); } }; @@ -700,7 +700,7 @@ class video_zoom_200: public validator_video_attached { void operator()(agi::Context *c) override { c->videoController->Stop(); - c->videoDisplay->SetZoom(2.); + c->videoDisplay->SetWindowZoom(2.); } }; @@ -718,7 +718,7 @@ class video_zoom_50: public validator_video_attached { void operator()(agi::Context *c) override { c->videoController->Stop(); - c->videoDisplay->SetZoom(.5); + c->videoDisplay->SetWindowZoom(.5); } }; @@ -730,7 +730,7 @@ struct video_zoom_in final : public validator_video_attached { STR_HELP("Zoom video in") void operator()(agi::Context *c) override { - c->videoDisplay->SetZoom(c->videoDisplay->GetZoom() + .125); + c->videoDisplay->SetWindowZoom(c->videoDisplay->GetZoom() + .125); } }; @@ -742,7 +742,7 @@ struct video_zoom_out final : public validator_video_attached { STR_HELP("Zoom video out") void operator()(agi::Context *c) override { - c->videoDisplay->SetZoom(c->videoDisplay->GetZoom() - .125); + c->videoDisplay->SetWindowZoom(c->videoDisplay->GetZoom() - .125); } }; } diff --git a/src/frame_main.cpp b/src/frame_main.cpp index 91531f5cf3..6c17602c72 100644 --- a/src/frame_main.cpp +++ b/src/frame_main.cpp @@ -276,9 +276,9 @@ void FrameMain::OnVideoOpen(AsyncVideoProvider *provider) { double zoom = context->videoDisplay->GetZoom(); wxSize windowSize = GetSize(); if (vidx*3*zoom > windowSize.GetX()*4 || vidy*4*zoom > windowSize.GetY()*6) - context->videoDisplay->SetZoom(zoom * .25); + context->videoDisplay->SetWindowZoom(zoom * .25); else if (vidx*3*zoom > windowSize.GetX()*2 || vidy*4*zoom > windowSize.GetY()*3) - context->videoDisplay->SetZoom(zoom * .5); + context->videoDisplay->SetWindowZoom(zoom * .5); SetDisplayMode(1,-1); diff --git a/src/project.cpp b/src/project.cpp index 5abb79b36d..abe2feb3a4 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -221,7 +221,7 @@ void Project::LoadUnloadFiles(ProjectProperties properties) { vc->SetAspectRatio(properties.ar_value); else vc->SetAspectRatio(ar_mode); - context->videoDisplay->SetZoom(properties.video_zoom); + context->videoDisplay->SetWindowZoom(properties.video_zoom); } } diff --git a/src/video_display.cpp b/src/video_display.cpp index 9590dfc9c6..6b26af9a72 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -87,19 +87,20 @@ VideoDisplay::VideoDisplay(wxToolBar *toolbar, bool freeSize, wxComboBox *zoomBo : wxGLCanvas(parent, -1, attribList) , autohideTools(OPT_GET("Tool/Visual/Autohide")) , con(c) -, zoomValue(OPT_GET("Video/Default Zoom")->GetInt() * .125 + .125) +, windowZoomValue(OPT_GET("Video/Default Zoom")->GetInt() * .125 + .125) +, videoZoomValue(1) , toolBar(toolbar) , zoomBox(zoomBox) , freeSize(freeSize) , retina_helper(agi::make_unique(this)) , scale_factor(retina_helper->GetScaleFactor()) , scale_factor_connection(retina_helper->AddScaleFactorListener([=](int new_scale_factor) { - double new_zoom = zoomValue * new_scale_factor / scale_factor; + double new_zoom = windowZoomValue * new_scale_factor / scale_factor; scale_factor = new_scale_factor; - SetZoom(new_zoom); + SetWindowZoom(new_zoom); })) { - zoomBox->SetValue(fmt_wx("%g%%", zoomValue * 100.)); + zoomBox->SetValue(fmt_wx("%g%%", windowZoomValue * 100.)); zoomBox->Bind(wxEVT_COMBOBOX, &VideoDisplay::SetZoomFromBox, this); zoomBox->Bind(wxEVT_TEXT_ENTER, &VideoDisplay::SetZoomFromBoxText, this); @@ -212,11 +213,14 @@ void VideoDisplay::DoRender() try { PositionVideo(); videoOut->Render(viewport_left, viewport_bottom, viewport_width, viewport_height); - E(glViewport(0, viewport_bottom_end, videoSize.GetWidth(), videoSize.GetHeight())); + + int client_w, client_h; + GetClientSize(&client_w, &client_h); + E(glViewport(0, 0, client_w, client_h)); E(glMatrixMode(GL_PROJECTION)); E(glLoadIdentity()); - E(glOrtho(0.0f, videoSize.GetWidth() / scale_factor, videoSize.GetHeight() / scale_factor, 0.0f, -1000.0f, 1000.0f)); + E(glOrtho(0.0f, client_w / scale_factor, client_h / scale_factor, 0.0f, -1000.0f, 1000.0f)); if (OPT_GET("Video/Overscan Mask")->GetBool()) { double ar = con->videoController->GetAspectRatioValue(); @@ -293,7 +297,7 @@ void VideoDisplay::PositionVideo() { GetClientSize(&client_w, &client_h); viewport_left = 0; - viewport_bottom_end = viewport_bottom = client_h * scale_factor - videoSize.GetHeight(); + viewport_bottom = client_h * scale_factor - videoSize.GetHeight(); viewport_top = 0; viewport_width = videoSize.GetWidth(); viewport_height = videoSize.GetHeight(); @@ -303,27 +307,26 @@ void VideoDisplay::PositionVideo() { int vidH = provider->GetHeight(); AspectRatio arType = con->videoController->GetAspectRatioType(); - double displayAr = double(viewport_width) / viewport_height; + double displayAr = double(client_w) / client_h; double videoAr = arType == AspectRatio::Default ? double(vidW) / vidH : con->videoController->GetAspectRatioValue(); // Window is wider than video, blackbox left/right if (displayAr - videoAr > 0.01) { - int delta = viewport_width - videoAr * viewport_height; + int delta = client_w - videoAr * client_h; viewport_left = delta / 2; - viewport_width -= delta; } // Video is wider than window, blackbox top/bottom else if (videoAr - displayAr > 0.01) { - int delta = viewport_height - viewport_width / videoAr; + int delta = client_h - client_w / videoAr; viewport_top = viewport_bottom = delta / 2; viewport_height -= delta; + viewport_width = viewport_height * videoAr; } } viewport_left += pan_x; viewport_top += pan_y; viewport_bottom -= pan_y; - viewport_bottom_end = std::min(viewport_bottom_end, 0); if (tool) { tool->SetClientSize(client_w * scale_factor, client_h * scale_factor); @@ -338,9 +341,7 @@ void VideoDisplay::UpdateSize() { if (!provider || !IsShownOnScreen()) return; videoSize.Set(provider->GetWidth(), provider->GetHeight()); - videoSize *= zoomValue; - if (con->videoController->GetAspectRatioType() != AspectRatio::Default) - videoSize.SetWidth(videoSize.GetHeight() * con->videoController->GetAspectRatioValue()); + videoSize *= videoZoomValue * windowZoomValue; wxEventBlocker blocker(this); if (freeSize) { @@ -348,13 +349,15 @@ void VideoDisplay::UpdateSize() { while (!top->IsTopLevel()) top = top->GetParent(); wxSize cs = GetClientSize(); + float csAr = (float)cs.GetWidth() / (float)cs.GetHeight(); wxSize oldSize = top->GetSize(); - top->SetSize(top->GetSize() + videoSize / scale_factor - cs); + top->SetSize(top->GetSize() + wxSize(provider->GetHeight() * csAr, provider->GetHeight()) * windowZoomValue / scale_factor - cs); SetClientSize(cs + top->GetSize() - oldSize); } else { - SetMinClientSize(videoSize / scale_factor); - SetMaxClientSize(videoSize / scale_factor); + wxSize newSize = wxSize(provider->GetWidth(), provider->GetHeight()) * windowZoomValue / scale_factor; + SetMinClientSize(newSize); + SetMaxClientSize(newSize); GetGrandParent()->Layout(); } @@ -364,11 +367,16 @@ void VideoDisplay::UpdateSize() { void VideoDisplay::OnSizeEvent(wxSizeEvent &event) { if (freeSize) { - videoSize = GetClientSize() * scale_factor; - PositionVideo(); - zoomValue = double(viewport_height) / con->project->VideoProvider()->GetHeight(); - zoomBox->ChangeValue(fmt_wx("%g%%", zoomValue * 100.)); - con->ass->Properties.video_zoom = zoomValue; + /* If the video is not moved */ + if (videoZoomValue == 1.0f && pan_x == 0 && pan_y == 0) + videoSize = GetClientSize() * scale_factor; + /* If the video is moving, we only need to update the size in this case */ + else if (videoSize.GetWidth() == 0 && videoSize.GetHeight() == 0) + videoSize = GetClientSize() * videoZoomValue * scale_factor; + windowZoomValue = double(GetClientSize().GetHeight()) / con->project->VideoProvider()->GetHeight(); + zoomBox->ChangeValue(fmt_wx("%g%%", windowZoomValue * 100.)); + con->ass->Properties.video_zoom = windowZoomValue; + UpdateSize(); } else { PositionVideo(); @@ -406,7 +414,10 @@ void VideoDisplay::OnMouseLeave(wxMouseEvent& event) { void VideoDisplay::OnMouseWheel(wxMouseEvent& event) { if (int wheel = event.GetWheelRotation()) { if (ForwardMouseWheelEvent(this, event)) - SetZoom(zoomValue + .125 * (wheel / event.GetWheelDelta())); + if (event.ControlDown()) + SetWindowZoom(windowZoomValue + .125 * (wheel / event.GetWheelDelta())); + else + SetVideoZoom(videoZoomValue + .125 * (wheel / event.GetWheelDelta())); } } @@ -422,28 +433,42 @@ void VideoDisplay::OnKeyDown(wxKeyEvent &event) { void VideoDisplay::ResetPan() { pan_x = pan_y = 0; + videoZoomValue = 1; + UpdateSize(); PositionVideo(); } -void VideoDisplay::SetZoom(double value) { +void VideoDisplay::SetWindowZoom(double value) { if (value == 0) return; value = std::max(value, .125); - pan_x *= value / zoomValue; - pan_y *= value / zoomValue; - zoomValue = value; - size_t selIndex = zoomValue / .125 - 1; + pan_x *= value / windowZoomValue; + pan_y *= value / windowZoomValue; + windowZoomValue = value; + size_t selIndex = windowZoomValue / .125 - 1; if (selIndex < zoomBox->GetCount()) zoomBox->SetSelection(selIndex); - zoomBox->ChangeValue(fmt_wx("%g%%", zoomValue * 100.)); - con->ass->Properties.video_zoom = zoomValue; + zoomBox->ChangeValue(fmt_wx("%g%%", windowZoomValue * 100.)); + con->ass->Properties.video_zoom = windowZoomValue; + UpdateSize(); +} + +void VideoDisplay::SetVideoZoom(double value) { + if (value == 0) return; + value = std::max(value, .125); + Vector2D mp = tool->FromScriptCoords(GetMousePosition()); + wxSize cs = GetClientSize(); + pan_x *= value / videoZoomValue; + pan_y *= value / videoZoomValue; + + videoZoomValue = value; UpdateSize(); } void VideoDisplay::SetZoomFromBox(wxCommandEvent &) { int sel = zoomBox->GetSelection(); if (sel != wxNOT_FOUND) { - zoomValue = (sel + 1) * .125; - con->ass->Properties.video_zoom = zoomValue; + windowZoomValue = (sel + 1) * .125; + con->ass->Properties.video_zoom = windowZoomValue; UpdateSize(); } } @@ -455,7 +480,7 @@ void VideoDisplay::SetZoomFromBoxText(wxCommandEvent &) { double value; if (strValue.ToDouble(&value)) - SetZoom(value / 100.); + SetWindowZoom(value / 100.); } void VideoDisplay::SetTool(std::unique_ptr new_tool) { diff --git a/src/video_display.h b/src/video_display.h index 2c80eb583c..594427c421 100644 --- a/src/video_display.h +++ b/src/video_display.h @@ -79,15 +79,15 @@ class VideoDisplay final : public wxGLCanvas { int viewport_width = 0; /// Screen pixels between the bottom of the canvas and the bottom of the video; used for glViewport int viewport_bottom = 0; - /// The REAL bottom of the viewport; used only for glViewport - int viewport_bottom_end = 0; /// Screen pixels between the bottom of the canvas and the top of the video; used for coordinate space conversion int viewport_top = 0; /// The height of the video in screen pixels int viewport_height = 0; - /// The current zoom level, where 1.0 = 100% - double zoomValue; + /// The current window zoom level, where 1.0 = 100% + double windowZoomValue; + /// The current video zoom level, where 1.0 = 100% relative to the display window size + double videoZoomValue; /// The last position of the mouse, when dragging Vector2D pan_last_pos; @@ -171,9 +171,10 @@ class VideoDisplay final : public wxGLCanvas { /// @brief Set the zoom level /// @param value The new zoom level - void SetZoom(double value); + void SetWindowZoom(double value); + void SetVideoZoom(double value); /// @brief Get the current zoom level - double GetZoom() const { return zoomValue; } + double GetZoom() const { return windowZoomValue; } /// @brief Reset the video pan void ResetPan(); From b953c92078f2450a3941c1572797218fd3db4cb8 Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 21 Apr 2021 00:21:06 +0200 Subject: [PATCH 09/25] Make zooming center around the cursor position --- src/video_display.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 6b26af9a72..4955ae78cf 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -318,7 +318,8 @@ void VideoDisplay::PositionVideo() { // Video is wider than window, blackbox top/bottom else if (videoAr - displayAr > 0.01) { int delta = client_h - client_w / videoAr; - viewport_top = viewport_bottom = delta / 2; + viewport_top += delta / 2; + viewport_bottom += delta / 2; viewport_height -= delta; viewport_width = viewport_height * videoAr; } @@ -455,10 +456,27 @@ void VideoDisplay::SetWindowZoom(double value) { void VideoDisplay::SetVideoZoom(double value) { if (value == 0) return; value = std::max(value, .125); - Vector2D mp = tool->FromScriptCoords(GetMousePosition()); + + // With the current blackbox algorithm in PositionVideo(), viewport_{width,height} could go negative. Stop that here wxSize cs = GetClientSize(); - pan_x *= value / videoZoomValue; - pan_y *= value / videoZoomValue; + wxSize videoNewSize = videoSize * (value / videoZoomValue); + float windowAR = (float)cs.GetWidth() / cs.GetHeight(); + float videoAR = (float)videoNewSize.GetWidth() / videoNewSize.GetHeight(); + if (windowAR < videoAR) { + float delta = cs.GetHeight() - cs.GetWidth() / videoAR; + if (videoNewSize.GetHeight() - delta < 0) + return; + } + + // Mouse coordinates, relative to the video, at the current zoom level + Vector2D mp = GetMousePosition() * videoZoomValue * windowZoomValue; + + // The video size will change by this many pixels + int pixelChangeW = videoSize.GetWidth() * (value / videoZoomValue - 1); + int pixelChangeH = videoSize.GetHeight() * (value / videoZoomValue - 1); + + pan_x -= pixelChangeW * (mp.X() / videoSize.GetWidth()); + pan_y -= pixelChangeH * (mp.Y() / videoSize.GetHeight()); videoZoomValue = value; UpdateSize(); From 1c3c9e368bc8fde3205e8dec2c389f1acf65163d Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 21 Apr 2021 00:22:18 +0200 Subject: [PATCH 10/25] Make zooming feel more linear with a "good enough" implementation --- src/video_display.cpp | 20 +++++++++++--------- src/video_display.h | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 4955ae78cf..6120b72175 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -418,7 +418,7 @@ void VideoDisplay::OnMouseWheel(wxMouseEvent& event) { if (event.ControlDown()) SetWindowZoom(windowZoomValue + .125 * (wheel / event.GetWheelDelta())); else - SetVideoZoom(videoZoomValue + .125 * (wheel / event.GetWheelDelta())); + SetVideoZoom(wheel / event.GetWheelDelta()); } } @@ -453,17 +453,19 @@ void VideoDisplay::SetWindowZoom(double value) { UpdateSize(); } -void VideoDisplay::SetVideoZoom(double value) { - if (value == 0) return; - value = std::max(value, .125); +void VideoDisplay::SetVideoZoom(int step) { + if (step == 0) return; + double newVideoZoom = videoZoomValue + (.125 * step) * videoZoomValue; + if (newVideoZoom < 0.125 || newVideoZoom > 10.0) + return; // With the current blackbox algorithm in PositionVideo(), viewport_{width,height} could go negative. Stop that here wxSize cs = GetClientSize(); - wxSize videoNewSize = videoSize * (value / videoZoomValue); + wxSize videoNewSize = videoSize * (newVideoZoom / videoZoomValue); float windowAR = (float)cs.GetWidth() / cs.GetHeight(); float videoAR = (float)videoNewSize.GetWidth() / videoNewSize.GetHeight(); if (windowAR < videoAR) { - float delta = cs.GetHeight() - cs.GetWidth() / videoAR; + int delta = cs.GetHeight() - cs.GetWidth() / videoAR; if (videoNewSize.GetHeight() - delta < 0) return; } @@ -472,13 +474,13 @@ void VideoDisplay::SetVideoZoom(double value) { Vector2D mp = GetMousePosition() * videoZoomValue * windowZoomValue; // The video size will change by this many pixels - int pixelChangeW = videoSize.GetWidth() * (value / videoZoomValue - 1); - int pixelChangeH = videoSize.GetHeight() * (value / videoZoomValue - 1); + int pixelChangeW = std::lround(videoSize.GetWidth() * (newVideoZoom / videoZoomValue - 1.0)); + int pixelChangeH = std::lround(videoSize.GetHeight() * (newVideoZoom / videoZoomValue - 1.0)); pan_x -= pixelChangeW * (mp.X() / videoSize.GetWidth()); pan_y -= pixelChangeH * (mp.Y() / videoSize.GetHeight()); - videoZoomValue = value; + videoZoomValue = newVideoZoom; UpdateSize(); } diff --git a/src/video_display.h b/src/video_display.h index 594427c421..fe64557ee1 100644 --- a/src/video_display.h +++ b/src/video_display.h @@ -172,7 +172,7 @@ class VideoDisplay final : public wxGLCanvas { /// @brief Set the zoom level /// @param value The new zoom level void SetWindowZoom(double value); - void SetVideoZoom(double value); + void SetVideoZoom(int step); /// @brief Get the current zoom level double GetZoom() const { return windowZoomValue; } From 57883bfe832ceb7d389a69e66d471a65807ff929 Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 21 Apr 2021 00:24:07 +0200 Subject: [PATCH 11/25] Fix a zooming bug on linux The preview window would change in width, when the video was being zoomed. Possibly, because on windows, zooming only calls UpdateSize once, but on linux, it gets called multiple, like 8 times. Rounding fixed it. --- src/video_display.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 6120b72175..282d6a58cb 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -349,11 +349,12 @@ void VideoDisplay::UpdateSize() { wxWindow *top = GetParent(); while (!top->IsTopLevel()) top = top->GetParent(); - wxSize cs = GetClientSize(); - float csAr = (float)cs.GetWidth() / (float)cs.GetHeight(); + wxSize oldClientSize = GetClientSize(); + double csAr = (double)oldClientSize.GetWidth() / (double)oldClientSize.GetHeight(); + wxSize newClientSize = wxSize(std::lround(provider->GetHeight() * csAr), provider->GetHeight()) * windowZoomValue / scale_factor; wxSize oldSize = top->GetSize(); - top->SetSize(top->GetSize() + wxSize(provider->GetHeight() * csAr, provider->GetHeight()) * windowZoomValue / scale_factor - cs); - SetClientSize(cs + top->GetSize() - oldSize); + top->SetSize(oldSize + (newClientSize - oldClientSize)); + SetClientSize(oldClientSize + (top->GetSize() - oldSize)); } else { wxSize newSize = wxSize(provider->GetWidth(), provider->GetHeight()) * windowZoomValue / scale_factor; From b2dd7fe4a19d719416cd1df871a6c76fbfa9e21c Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Fri, 16 Jul 2021 13:07:19 +0200 Subject: [PATCH 12/25] Add reset hotkey as Ctrl-R I'm not entirely sure, that this is how it's supposed to be added. This requires editing the already existing hotkey.json file (shows path in log, if it exists). Should this also be added to hotkey.cpp? --- src/libresrc/default_hotkey.json | 5 ++++- src/libresrc/osx/default_hotkey.json | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libresrc/default_hotkey.json b/src/libresrc/default_hotkey.json index d4b0af376a..70ea54bae4 100644 --- a/src/libresrc/default_hotkey.json +++ b/src/libresrc/default_hotkey.json @@ -340,6 +340,9 @@ "video/frame/prev/large" : [ "Alt-Left" ], + "video/pan_reset" : [ + "Ctrl-R" + ], "video/tool/clip" : [ "H" ], @@ -362,4 +365,4 @@ "J" ] } -} \ No newline at end of file +} diff --git a/src/libresrc/osx/default_hotkey.json b/src/libresrc/osx/default_hotkey.json index 829adb88e6..ccebadaaa6 100644 --- a/src/libresrc/osx/default_hotkey.json +++ b/src/libresrc/osx/default_hotkey.json @@ -347,6 +347,9 @@ "video/frame/prev/large" : [ "Alt-Left" ], + "video/pan_reset" : [ + "Ctrl-R" + ], "video/tool/clip" : [ "H" ], From e8a19fd534d25907922d98ccbec4000eea050d6d Mon Sep 17 00:00:00 2001 From: moex3 <46636583+moex3@users.noreply.github.com> Date: Wed, 2 Mar 2022 14:21:23 +0100 Subject: [PATCH 13/25] Revert "Add reset hotkey as Ctrl-R" / Not needed This reverts commit 3d525d9938790211b02a31a16d716498957891fc. The default hotkey is not required. People can just add a custom one from the hotkey settings if they want this. --- src/libresrc/default_hotkey.json | 5 +---- src/libresrc/osx/default_hotkey.json | 3 --- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/libresrc/default_hotkey.json b/src/libresrc/default_hotkey.json index 70ea54bae4..d4b0af376a 100644 --- a/src/libresrc/default_hotkey.json +++ b/src/libresrc/default_hotkey.json @@ -340,9 +340,6 @@ "video/frame/prev/large" : [ "Alt-Left" ], - "video/pan_reset" : [ - "Ctrl-R" - ], "video/tool/clip" : [ "H" ], @@ -365,4 +362,4 @@ "J" ] } -} +} \ No newline at end of file diff --git a/src/libresrc/osx/default_hotkey.json b/src/libresrc/osx/default_hotkey.json index ccebadaaa6..829adb88e6 100644 --- a/src/libresrc/osx/default_hotkey.json +++ b/src/libresrc/osx/default_hotkey.json @@ -347,9 +347,6 @@ "video/frame/prev/large" : [ "Alt-Left" ], - "video/pan_reset" : [ - "Ctrl-R" - ], "video/tool/clip" : [ "H" ], From 66e0a1dc37acba61abeeeb164289e6800cbf45dd Mon Sep 17 00:00:00 2001 From: Sodra Date: Wed, 2 Mar 2022 18:24:17 -0800 Subject: [PATCH 14/25] Added option to enable video panning --- src/libresrc/default_config.json | 3 ++- src/preferences.cpp | 3 +++ src/video_display.cpp | 28 ++++++++++++++++++++-------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/libresrc/default_config.json b/src/libresrc/default_config.json index 3ea90c8de6..a4acf8591f 100644 --- a/src/libresrc/default_config.json +++ b/src/libresrc/default_config.json @@ -619,6 +619,7 @@ "Fast Jump Step" : 10, "Show Keyframes" : true }, - "Subtitle Sync" : true + "Subtitle Sync" : true, + "Video Pan": false } } diff --git a/src/preferences.cpp b/src/preferences.cpp index 79b5b2b932..2cc606f7ce 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -455,6 +455,9 @@ void Advanced_Video(wxTreebook *book, Preferences *parent) { wxArrayString sp_choice = to_wx(SubtitlesProviderFactory::GetClasses()); p->OptionChoice(expert, _("Subtitles provider"), sp_choice, "Subtitle/Provider"); + + p->OptionChoice(expert, _("Video Panning"), "Video/Video Pan"); + #ifdef WITH_AVISYNTH auto avisynth = p->PageSizer("Avisynth"); diff --git a/src/video_display.cpp b/src/video_display.cpp index 282d6a58cb..785f729193 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -391,18 +391,30 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) { last_mouse_pos = mouse_pos = event.GetPosition(); - if (event.GetButton() == wxMOUSE_BTN_MIDDLE) { - if ((panning = event.ButtonDown())) + ///if video pan + bool videoPan = OPT_GET("Video/Video Pan")->GetBool(); + + if (videoPan){ + if (event.GetButton() == wxMOUSE_BTN_MIDDLE) { + if ((panning = event.ButtonDown())) + pan_last_pos = event.GetPosition(); + } + if (panning && event.Dragging()) { + pan_x += event.GetX() - pan_last_pos.X(); + pan_y += event.GetY() - pan_last_pos.Y(); pan_last_pos = event.GetPosition(); - } - if (panning && event.Dragging()) { - pan_x += event.GetX() - pan_last_pos.X(); - pan_y += event.GetY() - pan_last_pos.Y(); - pan_last_pos = event.GetPosition(); - PositionVideo(); + PositionVideo(); + } + } + else if ((pan_x != 0 || pan_y != 0) && !videoPan) + { + pan_x = pan_y = 0; + PositionVideo(); } + /// + if (tool) tool->OnMouseEvent(event); } From 7bdad6829d0047d0c278fdf4a6d9ded7611e0421 Mon Sep 17 00:00:00 2001 From: Sodra Date: Wed, 2 Mar 2022 18:36:38 -0800 Subject: [PATCH 15/25] Fix video panning option. Oops teehee ptep~ --- src/preferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preferences.cpp b/src/preferences.cpp index 2cc606f7ce..acba50602a 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -456,7 +456,7 @@ void Advanced_Video(wxTreebook *book, Preferences *parent) { wxArrayString sp_choice = to_wx(SubtitlesProviderFactory::GetClasses()); p->OptionChoice(expert, _("Subtitles provider"), sp_choice, "Subtitle/Provider"); - p->OptionChoice(expert, _("Video Panning"), "Video/Video Pan"); + p->OptionAdd(expert, _("Video Panning"), "Video/Video Pan"); #ifdef WITH_AVISYNTH From 3308161b212b2c5b0717ac36a4028364aefb3881 Mon Sep 17 00:00:00 2001 From: Sodra Date: Wed, 2 Mar 2022 19:02:21 -0800 Subject: [PATCH 16/25] Fixing zoom when panning is off --- src/video_display.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 785f729193..d87ed64c2c 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -426,9 +426,10 @@ void VideoDisplay::OnMouseLeave(wxMouseEvent& event) { } void VideoDisplay::OnMouseWheel(wxMouseEvent& event) { + bool videoPan = OPT_GET("Video/Video Pan")->GetBool(); if (int wheel = event.GetWheelRotation()) { if (ForwardMouseWheelEvent(this, event)) - if (event.ControlDown()) + if (event.ControlDown() || !videoPan) SetWindowZoom(windowZoomValue + .125 * (wheel / event.GetWheelDelta())); else SetVideoZoom(wheel / event.GetWheelDelta()); From 527b838ff9efc69c2cdf2196cf79d8d0093596fb Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Sun, 10 Jul 2022 22:57:55 +0200 Subject: [PATCH 17/25] Also add Video Pan option on OSX --- src/libresrc/osx/default_config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libresrc/osx/default_config.json b/src/libresrc/osx/default_config.json index 4d55817884..8fa3b70f98 100644 --- a/src/libresrc/osx/default_config.json +++ b/src/libresrc/osx/default_config.json @@ -619,6 +619,7 @@ "Fast Jump Step" : 10, "Show Keyframes" : true }, - "Subtitle Sync" : true + "Subtitle Sync" : true, + "Video Pan": false } } From 6287089ef2c2c3573328a89452b76f1f830ed118 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Mon, 11 Jul 2022 18:51:33 +0200 Subject: [PATCH 18/25] Add option toggling behaviour of Ctrl+Zoom --- src/libresrc/default_config.json | 3 ++- src/libresrc/osx/default_config.json | 3 ++- src/preferences.cpp | 2 ++ src/video_display.cpp | 8 +++++--- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/libresrc/default_config.json b/src/libresrc/default_config.json index a4acf8591f..ed0fcca904 100644 --- a/src/libresrc/default_config.json +++ b/src/libresrc/default_config.json @@ -620,6 +620,7 @@ "Show Keyframes" : true }, "Subtitle Sync" : true, - "Video Pan": false + "Video Pan": false, + "Default to Video Zoom": false } } diff --git a/src/libresrc/osx/default_config.json b/src/libresrc/osx/default_config.json index 8fa3b70f98..d4d3ffb03e 100644 --- a/src/libresrc/osx/default_config.json +++ b/src/libresrc/osx/default_config.json @@ -620,6 +620,7 @@ "Show Keyframes" : true }, "Subtitle Sync" : true, - "Video Pan": false + "Video Pan": false, + "Default to Video Zoom": false } } diff --git a/src/preferences.cpp b/src/preferences.cpp index acba50602a..d3ed3a8346 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -457,6 +457,8 @@ void Advanced_Video(wxTreebook *book, Preferences *parent) { p->OptionChoice(expert, _("Subtitles provider"), sp_choice, "Subtitle/Provider"); p->OptionAdd(expert, _("Video Panning"), "Video/Video Pan"); + p->OptionAdd(expert, _("Default to Video Zoom"), "Video/Default to Video Zoom") + ->SetToolTip("Reverses the behavior of Ctrl while scrolling the video display. If not set, scrolling will default to UI zoom and Ctrl+scrolling will zoom the video. If set, this will be reversed."); #ifdef WITH_AVISYNTH diff --git a/src/video_display.cpp b/src/video_display.cpp index d87ed64c2c..ad93480a1e 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -428,11 +428,13 @@ void VideoDisplay::OnMouseLeave(wxMouseEvent& event) { void VideoDisplay::OnMouseWheel(wxMouseEvent& event) { bool videoPan = OPT_GET("Video/Video Pan")->GetBool(); if (int wheel = event.GetWheelRotation()) { - if (ForwardMouseWheelEvent(this, event)) - if (event.ControlDown() || !videoPan) + if (ForwardMouseWheelEvent(this, event)) { + if (!videoPan || (event.ControlDown() == OPT_GET("Video/Default to Video Zoom")->GetBool())) { SetWindowZoom(windowZoomValue + .125 * (wheel / event.GetWheelDelta())); - else + } else { SetVideoZoom(wheel / event.GetWheelDelta()); + } + } } } From 935d5464c4b1712af9a27b08fdee7aa1c28dc113 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Mon, 1 Aug 2022 21:21:24 +0200 Subject: [PATCH 19/25] Add options to commit or reverse video zoom --- src/libresrc/default_config.json | 2 ++ src/libresrc/osx/default_config.json | 2 ++ src/preferences.cpp | 3 +++ src/video_display.cpp | 5 ++++- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libresrc/default_config.json b/src/libresrc/default_config.json index ed0fcca904..66b12418a5 100644 --- a/src/libresrc/default_config.json +++ b/src/libresrc/default_config.json @@ -592,6 +592,8 @@ }, "Video" : { + "Disable Scroll Zoom" : false, + "Reverse Zoom" : false, "Default Zoom" : 7, "Detached" : { "Enabled" : false, diff --git a/src/libresrc/osx/default_config.json b/src/libresrc/osx/default_config.json index d4d3ffb03e..9e4960a624 100644 --- a/src/libresrc/osx/default_config.json +++ b/src/libresrc/osx/default_config.json @@ -592,6 +592,8 @@ }, "Video" : { + "Disable Scroll Zoom" : false, + "Reverse Zoom" : false, "Default Zoom" : 7, "Detached" : { "Enabled" : false, diff --git a/src/preferences.cpp b/src/preferences.cpp index d3ed3a8346..f7390e1e12 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -176,6 +176,9 @@ void Video(wxTreebook *book, Preferences *parent) { p->CellSkip(general); p->OptionAdd(general, _("Automatically open audio when opening video"), "Video/Open Audio"); p->CellSkip(general); + p->OptionAdd(general, _("Disable zooming with scroll bar"), "Video/Disable Scroll Zoom") + ->SetToolTip("Makes the scroll bar not zoom the video. Useful when using a track pad that often scrolls accidentally."); + p->OptionAdd(general, _("Reverse zoom direction"), "Video/Reverse Zoom"); const wxString czoom_arr[24] = { "12.5%", "25%", "37.5%", "50%", "62.5%", "75%", "87.5%", "100%", "112.5%", "125%", "137.5%", "150%", "162.5%", "175%", "187.5%", "200%", "212.5%", "225%", "237.5%", "250%", "262.5%", "275%", "287.5%", "300%" }; wxArrayString choice_zoom(24, czoom_arr); diff --git a/src/video_display.cpp b/src/video_display.cpp index ad93480a1e..dae5e8d879 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -428,7 +428,10 @@ void VideoDisplay::OnMouseLeave(wxMouseEvent& event) { void VideoDisplay::OnMouseWheel(wxMouseEvent& event) { bool videoPan = OPT_GET("Video/Video Pan")->GetBool(); if (int wheel = event.GetWheelRotation()) { - if (ForwardMouseWheelEvent(this, event)) { + if (ForwardMouseWheelEvent(this, event) && !OPT_GET("Video/Disable Scroll Zoom")->GetBool()) { + if (OPT_GET("Video/Reverse Zoom")->GetBool()) { + wheel = -wheel; + } if (!videoPan || (event.ControlDown() == OPT_GET("Video/Default to Video Zoom")->GetBool())) { SetWindowZoom(windowZoomValue + .125 * (wheel / event.GetWheelDelta())); } else { From d673f0ad1289b1b242ce29b0a8bad650aa047681 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Tue, 23 Aug 2022 04:44:42 +0200 Subject: [PATCH 20/25] video zoom: Fix aspect ratio forcing Do this by partially reverting the changes to UpdateSize in favor of just multiplying by videoZoomValue *after* setting all the window sizes. --- src/video_display.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index dae5e8d879..b63a2158c8 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -342,7 +342,9 @@ void VideoDisplay::UpdateSize() { if (!provider || !IsShownOnScreen()) return; videoSize.Set(provider->GetWidth(), provider->GetHeight()); - videoSize *= videoZoomValue * windowZoomValue; + videoSize *= windowZoomValue; + if (con->videoController->GetAspectRatioType() != AspectRatio::Default) + videoSize.SetWidth(videoSize.GetHeight() * con->videoController->GetAspectRatioValue()); wxEventBlocker blocker(this); if (freeSize) { @@ -357,12 +359,12 @@ void VideoDisplay::UpdateSize() { SetClientSize(oldClientSize + (top->GetSize() - oldSize)); } else { - wxSize newSize = wxSize(provider->GetWidth(), provider->GetHeight()) * windowZoomValue / scale_factor; - SetMinClientSize(newSize); - SetMaxClientSize(newSize); + SetMinClientSize(videoSize / scale_factor); + SetMaxClientSize(videoSize / scale_factor); GetGrandParent()->Layout(); } + videoSize *= videoZoomValue; PositionVideo(); } @@ -496,7 +498,10 @@ void VideoDisplay::SetVideoZoom(int step) { int pixelChangeW = std::lround(videoSize.GetWidth() * (newVideoZoom / videoZoomValue - 1.0)); int pixelChangeH = std::lround(videoSize.GetHeight() * (newVideoZoom / videoZoomValue - 1.0)); - pan_x -= pixelChangeW * (mp.X() / videoSize.GetWidth()); + AsyncVideoProvider *provider = con->project->VideoProvider(); + double arfactor = (double) provider->GetHeight() * (double) videoSize.GetWidth() / (double) provider->GetWidth() / (double) videoSize.GetHeight(); + + pan_x -= pixelChangeW * (mp.X() / videoSize.GetWidth() * arfactor); pan_y -= pixelChangeH * (mp.Y() / videoSize.GetHeight()); videoZoomValue = newVideoZoom; From c85e5d2d7f8edecbb04c46dda8f6101f645b6e63 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Tue, 11 Oct 2022 15:15:40 +0200 Subject: [PATCH 21/25] video zoom: Fix visual tools with DPI scaling --- src/video_display.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index b63a2158c8..2d64315755 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -216,11 +216,11 @@ void VideoDisplay::DoRender() try { int client_w, client_h; GetClientSize(&client_w, &client_h); - E(glViewport(0, 0, client_w, client_h)); + E(glViewport(0, 0, client_w * scale_factor, client_h * scale_factor)); E(glMatrixMode(GL_PROJECTION)); E(glLoadIdentity()); - E(glOrtho(0.0f, client_w / scale_factor, client_h / scale_factor, 0.0f, -1000.0f, 1000.0f)); + E(glOrtho(0.0f, client_w, client_h, 0.0f, -1000.0f, 1000.0f)); if (OPT_GET("Video/Overscan Mask")->GetBool()) { double ar = con->videoController->GetAspectRatioValue(); From 7eb7eb72b45c16a86f9d68f6970472e8f8426f3c Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Tue, 11 Oct 2022 18:31:46 +0200 Subject: [PATCH 22/25] video zoom: Fix detached video with DPI scaling --- src/video_display.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 2d64315755..c394886e3a 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -295,9 +295,11 @@ void VideoDisplay::PositionVideo() { int client_w, client_h; GetClientSize(&client_w, &client_h); + client_w *= scale_factor; + client_h *= scale_factor; viewport_left = 0; - viewport_bottom = client_h * scale_factor - videoSize.GetHeight(); + viewport_bottom = client_h - videoSize.GetHeight(); viewport_top = 0; viewport_width = videoSize.GetWidth(); viewport_height = videoSize.GetHeight(); @@ -330,7 +332,7 @@ void VideoDisplay::PositionVideo() { viewport_bottom -= pan_y; if (tool) { - tool->SetClientSize(client_w * scale_factor, client_h * scale_factor); + tool->SetClientSize(client_w, client_h); tool->SetDisplayArea(viewport_left / scale_factor, viewport_top / scale_factor, viewport_width / scale_factor, viewport_height / scale_factor); } @@ -377,7 +379,7 @@ void VideoDisplay::OnSizeEvent(wxSizeEvent &event) { /* If the video is moving, we only need to update the size in this case */ else if (videoSize.GetWidth() == 0 && videoSize.GetHeight() == 0) videoSize = GetClientSize() * videoZoomValue * scale_factor; - windowZoomValue = double(GetClientSize().GetHeight()) / con->project->VideoProvider()->GetHeight(); + windowZoomValue = double(GetClientSize().GetHeight() * scale_factor) / con->project->VideoProvider()->GetHeight(); zoomBox->ChangeValue(fmt_wx("%g%%", windowZoomValue * 100.)); con->ass->Properties.video_zoom = windowZoomValue; UpdateSize(); From 7ab5bf0f96b82f689e83085d42b49458c4eaef82 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Wed, 2 Nov 2022 23:07:55 +0100 Subject: [PATCH 23/25] video zoom: Fix crash on windows when making detached video too small --- src/video_display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index c394886e3a..c6a4359cbd 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -220,7 +220,7 @@ void VideoDisplay::DoRender() try { E(glMatrixMode(GL_PROJECTION)); E(glLoadIdentity()); - E(glOrtho(0.0f, client_w, client_h, 0.0f, -1000.0f, 1000.0f)); + E(glOrtho(0.0f, std::max(client_w, 1), std::max(client_h, 1), 0.0f, -1000.0f, 1000.0f)); if (OPT_GET("Video/Overscan Mask")->GetBool()) { double ar = con->videoController->GetAspectRatioValue(); From 1593b9d7dfa4d5cdbe054c66ca336945160d107f Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Thu, 17 Nov 2022 17:29:18 +0100 Subject: [PATCH 24/25] Remove "Video Panning" option It's probably stable enough at this point, and hiding it behind an option just creates more confusion than it prevents. --- src/libresrc/default_config.json | 1 - src/libresrc/osx/default_config.json | 1 - src/preferences.cpp | 7 ++----- src/video_display.cpp | 31 +++++++++------------------- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/libresrc/default_config.json b/src/libresrc/default_config.json index 66b12418a5..14ce090a57 100644 --- a/src/libresrc/default_config.json +++ b/src/libresrc/default_config.json @@ -622,7 +622,6 @@ "Show Keyframes" : true }, "Subtitle Sync" : true, - "Video Pan": false, "Default to Video Zoom": false } } diff --git a/src/libresrc/osx/default_config.json b/src/libresrc/osx/default_config.json index 9e4960a624..bae06dbe96 100644 --- a/src/libresrc/osx/default_config.json +++ b/src/libresrc/osx/default_config.json @@ -622,7 +622,6 @@ "Show Keyframes" : true }, "Subtitle Sync" : true, - "Video Pan": false, "Default to Video Zoom": false } } diff --git a/src/preferences.cpp b/src/preferences.cpp index f7390e1e12..fd19478216 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -175,7 +175,8 @@ void Video(wxTreebook *book, Preferences *parent) { p->OptionAdd(general, _("Seek video to line start on selection change"), "Video/Subtitle Sync"); p->CellSkip(general); p->OptionAdd(general, _("Automatically open audio when opening video"), "Video/Open Audio"); - p->CellSkip(general); + p->OptionAdd(general, _("Default to Video Zoom"), "Video/Default to Video Zoom") + ->SetToolTip("Reverses the behavior of Ctrl while scrolling the video display. If not set, scrolling will default to UI zoom and Ctrl+scrolling will zoom the video. If set, this will be reversed."); p->OptionAdd(general, _("Disable zooming with scroll bar"), "Video/Disable Scroll Zoom") ->SetToolTip("Makes the scroll bar not zoom the video. Useful when using a track pad that often scrolls accidentally."); p->OptionAdd(general, _("Reverse zoom direction"), "Video/Reverse Zoom"); @@ -459,10 +460,6 @@ void Advanced_Video(wxTreebook *book, Preferences *parent) { wxArrayString sp_choice = to_wx(SubtitlesProviderFactory::GetClasses()); p->OptionChoice(expert, _("Subtitles provider"), sp_choice, "Subtitle/Provider"); - p->OptionAdd(expert, _("Video Panning"), "Video/Video Pan"); - p->OptionAdd(expert, _("Default to Video Zoom"), "Video/Default to Video Zoom") - ->SetToolTip("Reverses the behavior of Ctrl while scrolling the video display. If not set, scrolling will default to UI zoom and Ctrl+scrolling will zoom the video. If set, this will be reversed."); - #ifdef WITH_AVISYNTH auto avisynth = p->PageSizer("Avisynth"); diff --git a/src/video_display.cpp b/src/video_display.cpp index c6a4359cbd..7c5d290b53 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -395,27 +395,17 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) { last_mouse_pos = mouse_pos = event.GetPosition(); - ///if video pan - bool videoPan = OPT_GET("Video/Video Pan")->GetBool(); - - if (videoPan){ - if (event.GetButton() == wxMOUSE_BTN_MIDDLE) { - if ((panning = event.ButtonDown())) - pan_last_pos = event.GetPosition(); - } - if (panning && event.Dragging()) { - pan_x += event.GetX() - pan_last_pos.X(); - pan_y += event.GetY() - pan_last_pos.Y(); + if (event.GetButton() == wxMOUSE_BTN_MIDDLE) { + if ((panning = event.ButtonDown())) pan_last_pos = event.GetPosition(); - - PositionVideo(); - } - } - else if ((pan_x != 0 || pan_y != 0) && !videoPan) - { - pan_x = pan_y = 0; - PositionVideo(); } + if (panning && event.Dragging()) { + pan_x += event.GetX() - pan_last_pos.X(); + pan_y += event.GetY() - pan_last_pos.Y(); + pan_last_pos = event.GetPosition(); + + PositionVideo(); + } /// @@ -430,13 +420,12 @@ void VideoDisplay::OnMouseLeave(wxMouseEvent& event) { } void VideoDisplay::OnMouseWheel(wxMouseEvent& event) { - bool videoPan = OPT_GET("Video/Video Pan")->GetBool(); if (int wheel = event.GetWheelRotation()) { if (ForwardMouseWheelEvent(this, event) && !OPT_GET("Video/Disable Scroll Zoom")->GetBool()) { if (OPT_GET("Video/Reverse Zoom")->GetBool()) { wheel = -wheel; } - if (!videoPan || (event.ControlDown() == OPT_GET("Video/Default to Video Zoom")->GetBool())) { + if (event.ControlDown() == OPT_GET("Video/Default to Video Zoom")->GetBool()) { SetWindowZoom(windowZoomValue + .125 * (wheel / event.GetWheelDelta())); } else { SetVideoZoom(wheel / event.GetWheelDelta()); From 0d6fc11031fe33f35c5a6d0fd394de6c475136c2 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Fri, 20 Jan 2023 00:18:51 +0100 Subject: [PATCH 25/25] video zoom: Fix zoom when script_res != video_res --- src/video_display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_display.cpp b/src/video_display.cpp index 7c5d290b53..36271e3d24 100644 --- a/src/video_display.cpp +++ b/src/video_display.cpp @@ -483,7 +483,7 @@ void VideoDisplay::SetVideoZoom(int step) { } // Mouse coordinates, relative to the video, at the current zoom level - Vector2D mp = GetMousePosition() * videoZoomValue * windowZoomValue; + Vector2D mp = last_mouse_pos - Vector2D(viewport_left, viewport_top) / scale_factor; // The video size will change by this many pixels int pixelChangeW = std::lround(videoSize.GetWidth() * (newVideoZoom / videoZoomValue - 1.0));