From 9d27335d7d3f86029eebe26977c356766a1cd109 Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Sun, 7 Jan 2024 23:39:58 +0100 Subject: [PATCH] New Double clic action in Player window, Display window or background --- src/OutputPreviewWindow.cpp | 26 +++++--- src/SourceControlWindow.cpp | 111 ++++++++++++++++++++--------------- src/SourceControlWindow.h | 5 ++ src/UserInterfaceManager.cpp | 66 +++++++++++++-------- 4 files changed, 131 insertions(+), 77 deletions(-) diff --git a/src/OutputPreviewWindow.cpp b/src/OutputPreviewWindow.cpp index a61db6a..8d8a843 100644 --- a/src/OutputPreviewWindow.cpp +++ b/src/OutputPreviewWindow.cpp @@ -471,17 +471,29 @@ void OutputPreviewWindow::Render() ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.f); ImGui::Image((void*)(intptr_t)output->texture(), imagesize); ImGui::PopStyleVar(); - // mouse over the image - if ( ImGui::IsItemHovered() ) { - // show magnifying glass if active - if (magnifying_glass) - DrawInspector(output->texture(), imagesize, imagesize, draw_pos); - } // disable magnifying glass if window is deactivated - if ( g.NavWindow != g.CurrentWindow ) + if (g.NavWindow != g.CurrentWindow) magnifying_glass = false; + // handle mouse clic and hovering on image + const ImRect bb(draw_pos, draw_pos + imagesize); + const ImGuiID id = ImGui::GetCurrentWindow()->GetID("##output-texture"); + bool hovered, held; + bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, + ImGuiButtonFlags_PressedOnClick); + // toggle preview on double clic + if (pressed) { + // trigger to show preview (will be ignored if not double clic) + UserInterface::manager().show_preview = UserInterface::PREVIEW_OUTPUT; + // cancel the button behavior to let window move on drag + ImGui::SetActiveID(0, ImGui::GetCurrentWindow()); + ImGui::SetHoveredID(0); + } + // show magnifying glass if active and mouse hovering + else if (hovered && magnifying_glass) + DrawInspector(output->texture(), imagesize, imagesize, draw_pos); + /// /// Icons overlays /// diff --git a/src/SourceControlWindow.cpp b/src/SourceControlWindow.cpp index db9e861..6911ae9 100644 --- a/src/SourceControlWindow.cpp +++ b/src/SourceControlWindow.cpp @@ -47,8 +47,6 @@ #define CHECKER_RESOLUTION 6000 class Stream *checker_background_ = new Stream; -void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider = false, bool withinspector = false); -ImRect DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_inspector); SourceControlWindow::SourceControlWindow() : WorkspaceWindow("SourceController"), @@ -1043,72 +1041,67 @@ void DrawInspector(uint texture, ImVec2 texturesize, ImVec2 cropsize, ImVec2 ori } } -void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider, bool withinspector) +void SourceControlWindow::DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider, bool withinspector) { - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - - // pre-draw background with checkerboard pattern - ImGui::Image((void*)(uintptr_t) checker_background_->texture(), framesize, - ImVec2(0,0), ImVec2(framesize.x/CHECKER_RESOLUTION, framesize.y/CHECKER_RESOLUTION)); - - // get back to top image corner to draw - ImGui::SetCursorScreenPos(top_image); - - // info on source - CloneSource *cloned = dynamic_cast(s); + if (!s) + return; // 100% opacity for the image (ensure true colors) ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.f); - // draw pre and post-processed parts if necessary - if (s->imageProcessingEnabled() || s->textureTransformed() || cloned != nullptr) { + // pre-draw background with checkerboard pattern + ImGui::Image((void*)(uintptr_t) checker_background_->texture(), framesize, + ImVec2(0,0), ImVec2(framesize.x/CHECKER_RESOLUTION, framesize.y/CHECKER_RESOLUTION)); + // get back to top image corner after draw + ImGui::SetCursorScreenPos(top_image); + // pre-calculate cropping areas of source and cropped rendering area + const glm::vec4 _crop = s->frame()->projectionArea(); + const ImVec2 _cropsize = framesize * ImVec2(0.5f * (_crop[1] - _crop[0]), + 0.5f * (_crop[2] - _crop[3])); + const ImVec2 _croptop = framesize * ImVec2(0.5f * (1.f + _crop[0]), + 0.5f * (1.f - _crop[2]) ); + + // pre-calculate slider coordinates in rendering area + ImVec2 slider = framesize * ImVec2(Settings::application.widget.media_player_slider,1.f); + + // draw pre and post-processed parts if necessary + if (s->imageProcessingEnabled() || + s->textureTransformed() || + s->icon() == glm::ivec2(ICON_SOURCE_CLONE)) + { // // LEFT of slider : original texture // - ImVec2 slider = framesize * ImVec2(Settings::application.widget.media_player_slider,1.f); ImGui::Image((void*)(uintptr_t) s->texture(), slider, ImVec2(0.f,0.f), ImVec2(Settings::application.widget.media_player_slider,1.f)); - if ( withinspector && ImGui::IsItemHovered() ) - DrawInspector(s->texture(), framesize, framesize, top_image); // // RIGHT of slider : post-processed image (after crop and color correction) // - glm::vec4 _crop = s->frame()->projectionArea(); - ImVec2 cropsize = ImVec2(0.5f * (_crop[1] - _crop[0]), - 0.5f * (_crop[2] - _crop[3])); - ImVec2 croptop = ImVec2(0.5f * (1.f + _crop[0]), - 0.5f * (1.f - _crop[2]) ); - cropsize = framesize * cropsize; - croptop = framesize * croptop; - // no overlap of slider with cropped area - if (slider.x < croptop.x) { + if (slider.x < _croptop.x) { // draw cropped area - ImGui::SetCursorScreenPos( top_image + croptop ); - ImGui::Image((void*)(uintptr_t) s->frame()->texture(), cropsize, ImVec2(0.f, 0.f), ImVec2(1.f,1.f)); - if ( withinspector && ImGui::IsItemHovered() ) - DrawInspector(s->frame()->texture(), framesize, cropsize, top_image + croptop); + ImGui::SetCursorScreenPos( top_image + _croptop ); + ImGui::Image((void*)(uintptr_t) s->frame()->texture(), _cropsize, ImVec2(0.f, 0.f), ImVec2(1.f,1.f)); } // overlap of slider with cropped area (horizontally) - else if (slider.x < croptop.x + cropsize.x ) { + else if (slider.x < _croptop.x + _cropsize.x ) { // compute slider ratio of cropped area - float cropped_slider = (slider.x - croptop.x) / cropsize.x; + float cropped_slider = (slider.x - _croptop.x) / _cropsize.x; // top x moves with slider - ImGui::SetCursorScreenPos( top_image + ImVec2(slider.x, croptop.y) ); + ImGui::SetCursorScreenPos( top_image + ImVec2(slider.x, _croptop.y) ); // size is reduced by slider - ImGui::Image((void*)(uintptr_t) s->frame()->texture(), cropsize * ImVec2(1.f -cropped_slider, 1.f), ImVec2(cropped_slider, 0.f), ImVec2(1.f,1.f)); - if ( withinspector && ImGui::IsItemHovered() ) - DrawInspector(s->frame()->texture(), framesize, cropsize, top_image + croptop); + ImGui::Image((void*)(uintptr_t) s->frame()->texture(), _cropsize * ImVec2(1.f -cropped_slider, 1.f), ImVec2(cropped_slider, 0.f), ImVec2(1.f,1.f)); } // else : no render of cropped area + // + // SLIDER + // + ImDrawList* draw_list = ImGui::GetWindowDrawList(); ImU32 slider_color = ImGui::GetColorU32(ImGuiCol_NavWindowingHighlight); - if (withslider) + if (withslider && !withinspector) { - // - // SLIDER - // // user input : move slider horizontally ImGui::SetCursorScreenPos(top_image + ImVec2(- 20.f, 0.5f * framesize.y - 20.0f)); ImGuiToolkit::InvisibleSliderFloat("#media_player_slider2", &Settings::application.widget.media_player_slider, 0.f, 1.f, ImVec2(framesize.x + 40.f, 40.0f) ); @@ -1125,15 +1118,41 @@ void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider, } // no post-processed to show: draw simple texture else { - ImGui::Image((void*)(uintptr_t) s->texture(), framesize); - if ( withinspector && ImGui::IsItemHovered() ) - DrawInspector(s->texture(), framesize, framesize, top_image); + ImGui::Image((void *) (uintptr_t) s->texture(), framesize); + slider = framesize; } + // + // Handle mouse clic and hovering on image + // + const ImRect bb(top_image, top_image + framesize); + const ImGuiID id = ImGui::GetCurrentWindow()->GetID("##source-texture"); + bool hovered, held; + bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_PressedOnClick); + // toggle preview on double clic + if (pressed) { + // trigger to show preview (will be ignored if not double clic) + UserInterface::manager().show_preview = UserInterface::PREVIEW_SOURCE; + // cancel the button behavior to let window move on drag + ImGui::SetActiveID(0, ImGui::GetCurrentWindow()); + ImGui::SetHoveredID(0); + } + // show magnifying glass if hovering and inspector is active + else if (hovered && withinspector) { + // different texture to show depending on mouse position of slider + if (ImGui::IsMouseHoveringRect(top_image, top_image + slider)) + // inspector over left side of slider + DrawInspector(s->texture(), framesize, framesize, top_image); + else + // inspector over right side of slider + DrawInspector(s->frame()->texture(), framesize, _cropsize, top_image + _croptop); + } + + // pop ImGuiStyleVar_Alpha ImGui::PopStyleVar(); } -ImRect DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_inspector) +ImRect SourceControlWindow::DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_inspector) { /// /// Centered frame diff --git a/src/SourceControlWindow.h b/src/SourceControlWindow.h index ba711a3..1cfd4a0 100644 --- a/src/SourceControlWindow.h +++ b/src/SourceControlWindow.h @@ -2,6 +2,7 @@ #define SOURCECONTROLWINDOW_H struct ImVec2; +struct ImRect; #include "SourceList.h" #include "InfoVisitor.h" @@ -55,6 +56,10 @@ class SourceControlWindow : public WorkspaceWindow float mediaplayer_timeline_zoom_; void RenderMediaPlayer(MediaSource *ms); + // draw methods + void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider = false, bool withinspector = false); + ImRect DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_inspector); + // magnifying glass bool magnifying_glass; diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index 0471174..76984a8 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -640,10 +640,18 @@ void UserInterface::handleMouse() if ( ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) ) { - // if double clic action of view didn't succeed + // if double clic event was not used in view if ( !Mixer::manager().view()->doubleclic(mousepos) ) { - // display current source in left panel /or/ hide left panel if no current source - navigator.showPannelSource( Mixer::manager().indexCurrentSource() ); + int i = Mixer::manager().indexCurrentSource(); + // if no current source + if (i<0){ + // hide left pannel & toggle clear workspace + navigator.discardPannel(); + WorkspaceWindow::toggleClearRestoreWorkspace(); + } + else + // display current source in left panel /or/ hide left panel if no current source + navigator.showPannelSource( Mixer::manager().indexCurrentSource() ); } } @@ -1316,8 +1324,8 @@ void UserInterface::RenderPreview() _framebuffer = Mixer::manager().session()->frame(); else if (show_preview == PREVIEW_SOURCE) { _framebuffer = sourcecontrol.renderedFramebuffer(); - if ( _framebuffer == nullptr && Mixer::manager().currentSource() != nullptr) { - _framebuffer = Mixer::manager().currentSource()->frame(); + if (_framebuffer == nullptr && Mixer::manager().currentSource() != nullptr) { + _framebuffer = Mixer::manager().currentSource()->frame(); } } @@ -1326,8 +1334,7 @@ void UserInterface::RenderPreview() ImGui::OpenPopup("##RENDERPREVIEW"); _inspector = false; _sustain = false; - } - else + } else show_preview = PREVIEW_NONE; } @@ -1351,26 +1358,37 @@ void UserInterface::RenderPreview() ImGui::Image((void*)(intptr_t)_framebuffer->texture(), imagesize); ImGui::PopStyleVar(); - if ( ImGui::IsMouseClicked(ImGuiMouseButton_Left) ) { - // show inspector on mouse clic in - if ( ImGui::IsItemHovered() ) - _inspector = !_inspector; - // close view on mouse clic outside - else if (!_sustain) - show_preview = PREVIEW_NONE; - } - // draw inspector (magnifying glass) - if ( _inspector && ImGui::IsItemHovered() ) + // closing icon in top left corner + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); + ImGui::SetCursorScreenPos(draw_pos + ImVec2(IMGUI_SAME_LINE, IMGUI_SAME_LINE)); + if (ImGuiToolkit::IconButton(ICON_FA_TIMES, "Close preview")) + show_preview = PREVIEW_NONE; + ImGui::PopFont(); + + // handle mouse clic and hovering on image + const ImRect bb(draw_pos, draw_pos + imagesize); + const ImGuiID id = ImGui::GetCurrentWindow()->GetID("##preview-texture"); + bool hovered, held; + bool pressed = ImGui::ButtonBehavior(bb, + id, + &hovered, + &held, + ImGuiButtonFlags_PressedOnClick); + // toggle inspector on mouse clic + if (pressed) + _inspector = !_inspector; + // draw inspector (magnifying glass) on mouse hovering + if (hovered & _inspector) DrawInspector(_framebuffer->texture(), imagesize, imagesize, draw_pos); - // closing icon - ImGui::SetCursorScreenPos(draw_pos + ImVec2(IMGUI_SAME_LINE, IMGUI_SAME_LINE)); - ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); - if ( ImGuiToolkit::IconButton(ICON_FA_TIMES, "Close preview") ) + // close view on mouse clic outside + // and ignore show_preview on single clic + if (!hovered + && !_sustain + && !ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) + && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { show_preview = PREVIEW_NONE; - if ( ImGui::IsItemHovered() ) - _inspector = false; - ImGui::PopFont(); + } } // local keyboard handler (because focus is captured by modal dialog)