Make video zoom different from preview window zoom

This commit is contained in:
moex3 2021-04-21 00:19:51 +02:00 committed by Sodra
parent 70ddf3c7f5
commit 4f6836da9c
5 changed files with 74 additions and 48 deletions

View File

@ -669,7 +669,7 @@ public:
void operator()(agi::Context *c) override { void operator()(agi::Context *c) override {
c->videoController->Stop(); c->videoController->Stop();
c->videoDisplay->SetZoom(1.); c->videoDisplay->SetWindowZoom(1.);
} }
}; };
@ -700,7 +700,7 @@ public:
void operator()(agi::Context *c) override { void operator()(agi::Context *c) override {
c->videoController->Stop(); c->videoController->Stop();
c->videoDisplay->SetZoom(2.); c->videoDisplay->SetWindowZoom(2.);
} }
}; };
@ -718,7 +718,7 @@ public:
void operator()(agi::Context *c) override { void operator()(agi::Context *c) override {
c->videoController->Stop(); 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") STR_HELP("Zoom video in")
void operator()(agi::Context *c) override { 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") STR_HELP("Zoom video out")
void operator()(agi::Context *c) override { void operator()(agi::Context *c) override {
c->videoDisplay->SetZoom(c->videoDisplay->GetZoom() - .125); c->videoDisplay->SetWindowZoom(c->videoDisplay->GetZoom() - .125);
} }
}; };
} }

View File

@ -276,9 +276,9 @@ void FrameMain::OnVideoOpen(AsyncVideoProvider *provider) {
double zoom = context->videoDisplay->GetZoom(); double zoom = context->videoDisplay->GetZoom();
wxSize windowSize = GetSize(); wxSize windowSize = GetSize();
if (vidx*3*zoom > windowSize.GetX()*4 || vidy*4*zoom > windowSize.GetY()*6) 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) 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); SetDisplayMode(1,-1);

View File

@ -220,7 +220,7 @@ void Project::LoadUnloadFiles(ProjectProperties properties) {
vc->SetAspectRatio(properties.ar_value); vc->SetAspectRatio(properties.ar_value);
else else
vc->SetAspectRatio(ar_mode); vc->SetAspectRatio(ar_mode);
context->videoDisplay->SetZoom(properties.video_zoom); context->videoDisplay->SetWindowZoom(properties.video_zoom);
} }
} }

View File

@ -82,19 +82,20 @@ VideoDisplay::VideoDisplay(wxToolBar *toolbar, bool freeSize, wxComboBox *zoomBo
: wxGLCanvas(parent, -1, attribList) : wxGLCanvas(parent, -1, attribList)
, autohideTools(OPT_GET("Tool/Visual/Autohide")) , autohideTools(OPT_GET("Tool/Visual/Autohide"))
, con(c) , con(c)
, zoomValue(OPT_GET("Video/Default Zoom")->GetInt() * .125 + .125) , windowZoomValue(OPT_GET("Video/Default Zoom")->GetInt() * .125 + .125)
, videoZoomValue(1)
, toolBar(toolbar) , toolBar(toolbar)
, zoomBox(zoomBox) , zoomBox(zoomBox)
, freeSize(freeSize) , freeSize(freeSize)
, retina_helper(agi::make_unique<RetinaHelper>(this)) , retina_helper(agi::make_unique<RetinaHelper>(this))
, scale_factor(retina_helper->GetScaleFactor()) , scale_factor(retina_helper->GetScaleFactor())
, scale_factor_connection(retina_helper->AddScaleFactorListener([=](int new_scale_factor) { , 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; 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_COMBOBOX, &VideoDisplay::SetZoomFromBox, this);
zoomBox->Bind(wxEVT_TEXT_ENTER, &VideoDisplay::SetZoomFromBoxText, this); zoomBox->Bind(wxEVT_TEXT_ENTER, &VideoDisplay::SetZoomFromBoxText, this);
@ -193,11 +194,14 @@ void VideoDisplay::Render() try {
PositionVideo(); PositionVideo();
videoOut->Render(viewport_left, viewport_bottom, viewport_width, viewport_height); 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(glMatrixMode(GL_PROJECTION));
E(glLoadIdentity()); 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()) { if (OPT_GET("Video/Overscan Mask")->GetBool()) {
double ar = con->videoController->GetAspectRatioValue(); double ar = con->videoController->GetAspectRatioValue();
@ -274,7 +278,7 @@ void VideoDisplay::PositionVideo() {
GetClientSize(&client_w, &client_h); GetClientSize(&client_w, &client_h);
viewport_left = 0; 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_top = 0;
viewport_width = videoSize.GetWidth(); viewport_width = videoSize.GetWidth();
viewport_height = videoSize.GetHeight(); viewport_height = videoSize.GetHeight();
@ -284,27 +288,26 @@ void VideoDisplay::PositionVideo() {
int vidH = provider->GetHeight(); int vidH = provider->GetHeight();
AspectRatio arType = con->videoController->GetAspectRatioType(); 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(); double videoAr = arType == AspectRatio::Default ? double(vidW) / vidH : con->videoController->GetAspectRatioValue();
// Window is wider than video, blackbox left/right // Window is wider than video, blackbox left/right
if (displayAr - videoAr > 0.01) { if (displayAr - videoAr > 0.01) {
int delta = viewport_width - videoAr * viewport_height; int delta = client_w - videoAr * client_h;
viewport_left = delta / 2; viewport_left = delta / 2;
viewport_width -= delta;
} }
// Video is wider than window, blackbox top/bottom // Video is wider than window, blackbox top/bottom
else if (videoAr - displayAr > 0.01) { 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_top = viewport_bottom = delta / 2;
viewport_height -= delta; viewport_height -= delta;
viewport_width = viewport_height * videoAr;
} }
} }
viewport_left += pan_x; viewport_left += pan_x;
viewport_top += pan_y; viewport_top += pan_y;
viewport_bottom -= pan_y; viewport_bottom -= pan_y;
viewport_bottom_end = std::min(viewport_bottom_end, 0);
if (tool) { if (tool) {
tool->SetClientSize(client_w * scale_factor, client_h * scale_factor); tool->SetClientSize(client_w * scale_factor, client_h * scale_factor);
@ -319,9 +322,7 @@ void VideoDisplay::UpdateSize() {
if (!provider || !IsShownOnScreen()) return; if (!provider || !IsShownOnScreen()) return;
videoSize.Set(provider->GetWidth(), provider->GetHeight()); videoSize.Set(provider->GetWidth(), provider->GetHeight());
videoSize *= zoomValue; videoSize *= videoZoomValue * windowZoomValue;
if (con->videoController->GetAspectRatioType() != AspectRatio::Default)
videoSize.SetWidth(videoSize.GetHeight() * con->videoController->GetAspectRatioValue());
wxEventBlocker blocker(this); wxEventBlocker blocker(this);
if (freeSize) { if (freeSize) {
@ -329,13 +330,15 @@ void VideoDisplay::UpdateSize() {
while (!top->IsTopLevel()) top = top->GetParent(); while (!top->IsTopLevel()) top = top->GetParent();
wxSize cs = GetClientSize(); wxSize cs = GetClientSize();
float csAr = (float)cs.GetWidth() / (float)cs.GetHeight();
wxSize oldSize = top->GetSize(); 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); SetClientSize(cs + top->GetSize() - oldSize);
} }
else { else {
SetMinClientSize(videoSize / scale_factor); wxSize newSize = wxSize(provider->GetWidth(), provider->GetHeight()) * windowZoomValue / scale_factor;
SetMaxClientSize(videoSize / scale_factor); SetMinClientSize(newSize);
SetMaxClientSize(newSize);
GetGrandParent()->Layout(); GetGrandParent()->Layout();
} }
@ -345,11 +348,16 @@ void VideoDisplay::UpdateSize() {
void VideoDisplay::OnSizeEvent(wxSizeEvent &event) { void VideoDisplay::OnSizeEvent(wxSizeEvent &event) {
if (freeSize) { if (freeSize) {
videoSize = GetClientSize() * scale_factor; /* If the video is not moved */
PositionVideo(); if (videoZoomValue == 1.0f && pan_x == 0 && pan_y == 0)
zoomValue = double(viewport_height) / con->project->VideoProvider()->GetHeight(); videoSize = GetClientSize() * scale_factor;
zoomBox->ChangeValue(fmt_wx("%g%%", zoomValue * 100.)); /* If the video is moving, we only need to update the size in this case */
con->ass->Properties.video_zoom = zoomValue; 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 { else {
PositionVideo(); PositionVideo();
@ -387,7 +395,10 @@ void VideoDisplay::OnMouseLeave(wxMouseEvent& event) {
void VideoDisplay::OnMouseWheel(wxMouseEvent& event) { void VideoDisplay::OnMouseWheel(wxMouseEvent& event) {
if (int wheel = event.GetWheelRotation()) { if (int wheel = event.GetWheelRotation()) {
if (ForwardMouseWheelEvent(this, event)) 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()));
} }
} }
@ -403,28 +414,42 @@ void VideoDisplay::OnKeyDown(wxKeyEvent &event) {
void VideoDisplay::ResetPan() { void VideoDisplay::ResetPan() {
pan_x = pan_y = 0; pan_x = pan_y = 0;
videoZoomValue = 1;
UpdateSize();
PositionVideo(); PositionVideo();
} }
void VideoDisplay::SetZoom(double value) { void VideoDisplay::SetWindowZoom(double value) {
if (value == 0) return; if (value == 0) return;
value = std::max(value, .125); value = std::max(value, .125);
pan_x *= value / zoomValue; pan_x *= value / windowZoomValue;
pan_y *= value / zoomValue; pan_y *= value / windowZoomValue;
zoomValue = value; windowZoomValue = value;
size_t selIndex = zoomValue / .125 - 1; size_t selIndex = windowZoomValue / .125 - 1;
if (selIndex < zoomBox->GetCount()) if (selIndex < zoomBox->GetCount())
zoomBox->SetSelection(selIndex); zoomBox->SetSelection(selIndex);
zoomBox->ChangeValue(fmt_wx("%g%%", zoomValue * 100.)); zoomBox->ChangeValue(fmt_wx("%g%%", windowZoomValue * 100.));
con->ass->Properties.video_zoom = zoomValue; 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(); UpdateSize();
} }
void VideoDisplay::SetZoomFromBox(wxCommandEvent &) { void VideoDisplay::SetZoomFromBox(wxCommandEvent &) {
int sel = zoomBox->GetSelection(); int sel = zoomBox->GetSelection();
if (sel != wxNOT_FOUND) { if (sel != wxNOT_FOUND) {
zoomValue = (sel + 1) * .125; windowZoomValue = (sel + 1) * .125;
con->ass->Properties.video_zoom = zoomValue; con->ass->Properties.video_zoom = windowZoomValue;
UpdateSize(); UpdateSize();
} }
} }
@ -436,7 +461,7 @@ void VideoDisplay::SetZoomFromBoxText(wxCommandEvent &) {
double value; double value;
if (strValue.ToDouble(&value)) if (strValue.ToDouble(&value))
SetZoom(value / 100.); SetWindowZoom(value / 100.);
} }
void VideoDisplay::SetTool(std::unique_ptr<VisualToolBase> new_tool) { void VideoDisplay::SetTool(std::unique_ptr<VisualToolBase> new_tool) {

View File

@ -79,15 +79,15 @@ class VideoDisplay final : public wxGLCanvas {
int viewport_width = 0; int viewport_width = 0;
/// Screen pixels between the bottom of the canvas and the bottom of the video; used for glViewport /// Screen pixels between the bottom of the canvas and the bottom of the video; used for glViewport
int viewport_bottom = 0; 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 /// Screen pixels between the bottom of the canvas and the top of the video; used for coordinate space conversion
int viewport_top = 0; int viewport_top = 0;
/// The height of the video in screen pixels /// The height of the video in screen pixels
int viewport_height = 0; int viewport_height = 0;
/// The current zoom level, where 1.0 = 100% /// The current window zoom level, where 1.0 = 100%
double zoomValue; 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 /// The last position of the mouse, when dragging
Vector2D pan_last_pos; Vector2D pan_last_pos;
@ -167,9 +167,10 @@ public:
/// @brief Set the zoom level /// @brief Set the zoom level
/// @param value The new 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 /// @brief Get the current zoom level
double GetZoom() const { return zoomValue; } double GetZoom() const { return windowZoomValue; }
/// @brief Reset the video pan /// @brief Reset the video pan
void ResetPan(); void ResetPan();