diff --git a/src/DisplaysView.cpp b/src/DisplaysView.cpp index d6e5adf..8855ca1 100644 --- a/src/DisplaysView.cpp +++ b/src/DisplaysView.cpp @@ -34,7 +34,6 @@ #include "Source.h" #include "Settings.h" #include "PickingVisitor.h" -#include "DrawVisitor.h" #include "Decorations.h" #include "UserInterfaceManager.h" #include "BoundingBoxVisitor.h" @@ -113,7 +112,7 @@ DisplaysView::DisplaysView() : View(DISPLAYS) output_overlays_->setActive(1); output_mode_->setActive(0); output_monitor_ = ""; - update_pending_ = false; + draw_pending_ = false; // display actions : 0 = move output, 1 paint, 2 erase display_action_ = 0; @@ -131,7 +130,6 @@ void DisplaysView::update(float dt) if (render) output_render_->setTextureIndex( render->texture() ); - // // prevent invalid scaling // float s = CLAMP(scene.root()->scale_.x, DISPLAYS_MIN_SCALE, DISPLAYS_MAX_SCALE); // scene.root()->scale_.x = s; @@ -220,59 +218,108 @@ int DisplaysView::size () void DisplaysView::draw() { -// g_printerr("DisplaysView::draw()\n"); - + // update visible flag output_render_->visible_ = !Settings::application.render.disabled; output_visible_->visible_ = Settings::application.render.disabled; + if (output_render_->visible_) { + // rendering of framebuffer in window + if (Settings::application.windows[1].scaled) { + output_render_->scale_ = glm::vec3(1.f, 1.f, 1.f); + } + else { + FrameBuffer *output = Mixer::manager().session()->frame(); + if (output){ + float out_ar = output_->scale_.x / output_->scale_.y; + if (output->aspectRatio() < out_ar) + output_render_->scale_ = glm::vec3(output->aspectRatio() / out_ar, 1.f, 1.f); + else + output_render_->scale_ = glm::vec3(1.f, out_ar / output->aspectRatio(), 1.f); + } + } + } + + // Window overlay + if ( Settings::application.windows[1].fullscreen ) { + // output overlay for fullscreen + output_mode_->setActive( 1 ); + + glm::ivec4 rect = Rendering::manager().monitors()[Settings::application.windows[1].monitor]; + glm::vec2 TopLeft = glm::vec2(rect.x * DISPLAYS_UNIT, -rect.y * DISPLAYS_UNIT); + TopLeft = Rendering::manager().project(glm::vec3(TopLeft, 0.f), scene.root()->transform_, false); + ImGui::SetNextWindowPos( ImVec2( TopLeft.x, TopLeft.y), ImGuiCond_Always); + + glm::vec2 BottomRight = glm::vec2( (rect.x + rect.p) * DISPLAYS_UNIT, -(rect.y + rect.q) * DISPLAYS_UNIT); + BottomRight = Rendering::manager().project(glm::vec3(BottomRight, 0.f), scene.root()->transform_, false); + ImGui::SetNextWindowSize( ImVec2( BottomRight.x - TopLeft.x, BottomRight.y - TopLeft.y), ImGuiCond_Always); + + ImGui::SetNextWindowBgAlpha(0.0f); // Transparent background + if (ImGui::Begin("InfoOutputFullscreen", NULL, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing)) + { + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRectFilled(ImVec2(TopLeft.x, TopLeft.y + 4), ImVec2(BottomRight.x, TopLeft.y + ImGui::GetTextLineHeightWithSpacing()), IMGUI_COLOR_OVERLAY); + + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_MONO); + ImGui::TextColored(ImVec4(COLOR_FRAME_LIGHT, 1.0f), ICON_FA_TV " %s %d x %d px", Settings::application.windows[1].monitor.c_str(), rect.p, rect.q); + ImGui::PopFont(); + + ImGui::End(); + } + + } + else { + // output overlay for window + output_mode_->setActive( 0 ); + + glm::vec2 TopLeft = glm::vec2(Settings::application.windows[1].x * DISPLAYS_UNIT, -Settings::application.windows[1].y * DISPLAYS_UNIT); + TopLeft = Rendering::manager().project(glm::vec3(TopLeft, 0.f), scene.root()->transform_, false); + ImGui::SetNextWindowPos( ImVec2( TopLeft.x, TopLeft.y), ImGuiCond_Always); + + glm::vec2 BottomRight = glm::vec2( (Settings::application.windows[1].x + Settings::application.windows[1].w) * DISPLAYS_UNIT, + -(Settings::application.windows[1].y + Settings::application.windows[1].h) * DISPLAYS_UNIT); + BottomRight = Rendering::manager().project(glm::vec3(BottomRight, 0.f), scene.root()->transform_, false); + ImGui::SetNextWindowSize( ImVec2( BottomRight.x - TopLeft.x, BottomRight.y - TopLeft.y), ImGuiCond_Always); + + ImGui::SetNextWindowBgAlpha(0.0f); // Transparent background + if (ImGui::Begin("InfoOutputWindow", NULL, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing)) + { + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRectFilled(ImVec2(TopLeft.x, TopLeft.y + 4), ImVec2(BottomRight.x, TopLeft.y + ImGui::GetTextLineHeightWithSpacing()), IMGUI_COLOR_OVERLAY); + + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_MONO); + ImGui::TextColored(ImVec4(COLOR_FRAME_LIGHT, 1.0f), ICON_FA_WINDOW_RESTORE " (%d,%d) %d x %d px", Settings::application.windows[1].x, Settings::application.windows[1].y, + Settings::application.windows[1].w, Settings::application.windows[1].h); + ImGui::PopFont(); + + ImGui::End(); + } + } // if user is not manipulating output frame // update the output frame to match the window dimensions - if (!current_action_ongoing_ && !update_pending_) { + if (!current_action_ongoing_ && !draw_pending_) { // TODO Mutex for multithread access with changed flag - if ( Settings::application.windows[1].fullscreen ) { - // output overlay for fullscreen - output_mode_->setActive( 1 ); - glm::ivec4 rect = Rendering::manager().monitors()[Settings::application.windows[1].monitor]; output_->scale_.x = rect.p * 0.5f * DISPLAYS_UNIT; output_->scale_.y = rect.q * 0.5f * DISPLAYS_UNIT; output_->translation_.x = rect.x * DISPLAYS_UNIT + output_->scale_.x; output_->translation_.y = -rect.y * DISPLAYS_UNIT - output_->scale_.y; - } else { - // output overlay for window - output_mode_->setActive( 0 ); - output_->scale_.x = Settings::application.windows[1].w * 0.5f * DISPLAYS_UNIT; output_->scale_.y = Settings::application.windows[1].h * 0.5f * DISPLAYS_UNIT; output_->translation_.x = Settings::application.windows[1].x * DISPLAYS_UNIT + output_->scale_.x; output_->translation_.y = -Settings::application.windows[1].y * DISPLAYS_UNIT - output_->scale_.y; } - } - // rendering of framebuffer in window - if (Settings::application.windows[1].scaled) { - output_render_->scale_ = glm::vec3(1.f, 1.f, 1.f); - } - else { - FrameBuffer *output = Mixer::manager().session()->frame(); - if (output){ - float out_ar = output_->scale_.x / output_->scale_.y; - if (output->aspectRatio() < out_ar) - output_render_->scale_ = glm::vec3(output->aspectRatio() / out_ar, 1.f, 1.f); - else - output_render_->scale_ = glm::vec3(1.f, out_ar / output->aspectRatio(), 1.f); - } - } // main call to draw the view View::draw(); - update_pending_ = false; // // Render the UI // if (output_render_ != nullptr){ @@ -287,31 +334,28 @@ void DisplaysView::draw() // | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings // | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus )) // { - -// // style grey -// ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(COLOR_MONITOR, 1.0f)); // 1 +// // colors for UI +// ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.0f)); // 1 // ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f)); // ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.f)); // ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.24f, 0.24f, 0.24f, 0.46f)); // ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.85f, 0.85f, 0.85f, 0.86f)); // ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImVec4(0.95f, 0.95f, 0.95f, 1.00f)); // ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.00f, 0.00f, 0.00f, 0.00f)); -// ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.24f, 0.24f, 0.24f, 0.46f)); +// ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.4f, 0.4f, 0.4f, 0.56f)); // ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.36f, 0.36f, 0.36f, 0.9f)); // ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.36f, 0.36f, 0.36f, 0.5f)); // ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.88f, 0.88f, 0.88f, 0.73f)); // ImGui::PushStyleColor(ImGuiCol_Tab, ImVec4(0.83f, 0.83f, 0.84f, 0.78f)); -// ImGui::PushStyleColor(ImGuiCol_TabHovered, ImVec4(0.53f, 0.53f, 0.53f, 0.60f)); +// ImGui::PushStyleColor(ImGuiCol_TabHovered, ImVec4(0.43f, 0.43f, 0.43f, 0.60f)); // ImGui::PushStyleColor(ImGuiCol_TabActive, ImVec4(0.40f, 0.40f, 0.40f, 1.00f)); // 14 colors -// // GUI for drawing - // // select cursor // static bool on = true; -// ImGui::SameLine(0, 60); // on = display_action_ == 0; // if (ImGuiToolkit::ButtonToggle(ICON_FA_MOUSE_POINTER, &on)) { // output_selected_=true; +// output_overlays_->setActive(1); // display_action_ = 0; // } @@ -319,6 +363,7 @@ void DisplaysView::draw() // on = display_action_ == 1; // if (ImGuiToolkit::ButtonToggle(ICON_FA_PAINT_BRUSH, &on)) { // output_selected_=false; +// output_overlays_->setActive(0); // display_action_ = 1; // } @@ -326,6 +371,7 @@ void DisplaysView::draw() // on = display_action_ == 2; // if (ImGuiToolkit::ButtonToggle(ICON_FA_ERASER, &on)) { // output_selected_=false; +// output_overlays_->setActive(0); // display_action_ = 2; // } @@ -466,17 +512,6 @@ void DisplaysView::draw() ImGui::MenuItem( ICON_FA_EXPAND_ARROWS_ALT " Scaled", nullptr, &Settings::application.windows[1].scaled ); - if (ImGui::MenuItem( ICON_FA_VECTOR_SQUARE " Reset" )){ - // reset resolution to 1:1 - glm::ivec4 rect = outputCoordinates(); - rect.p = Mixer::manager().session()->frame()->width(); - rect.q = Mixer::manager().session()->frame()->height(); - Rendering::manager().outputWindow().setCoordinates( rect ); - // reset attributes - Settings::application.windows[1].scaled = false; - Rendering::manager().outputWindow().exitFullscreen(); - } - ImGui::Separator(); bool _windowed = !Settings::application.windows[1].fullscreen; if (ImGui::MenuItem( ICON_FA_WINDOW_RESTORE " Window", nullptr, &_windowed)){ @@ -484,6 +519,30 @@ void DisplaysView::draw() // not fullscreen on a monitor output_monitor_ = ""; } + + if (ImGui::MenuItem( ICON_FA_LAPTOP " Reset size", nullptr, false, _windowed )){ + // reset resolution to 1:1 + glm::ivec4 rect = outputCoordinates(); + rect.p = Mixer::manager().session()->frame()->width(); + rect.q = Mixer::manager().session()->frame()->height(); + Rendering::manager().outputWindow().setCoordinates( rect ); + } + + if (ImGui::MenuItem( ICON_FA_EXPAND " Fit all screens", nullptr, false, _windowed )){ + + glm::ivec4 rect (INT_MAX, INT_MAX, 0, 0); + std::map _monitors = Rendering::manager().monitors(); + for (auto monitor_iter = _monitors.begin(); + monitor_iter != _monitors.end(); ++monitor_iter) { + rect.x = MIN(rect.x, monitor_iter->second.x); + rect.y = MIN(rect.y, monitor_iter->second.y); + rect.p = MAX(rect.p, monitor_iter->second.x+monitor_iter->second.p); + rect.q = MAX(rect.q, monitor_iter->second.y+monitor_iter->second.q); + } + Rendering::manager().outputWindow().setCoordinates( rect ); + } + + ImGui::Separator(); int index = 1; std::map _monitors = Rendering::manager().monitors(); for (auto monitor_iter = _monitors.begin(); @@ -501,6 +560,7 @@ void DisplaysView::draw() ImGui::EndPopup(); } + draw_pending_ = false; } std::pair DisplaysView::pick(glm::vec2 P) @@ -583,7 +643,9 @@ void DisplaysView::terminate(bool force) // terminated current_action_ = ""; current_action_ongoing_ = false; - update_pending_ = true; + + // prevent next draw + draw_pending_ = true; } } @@ -755,14 +817,54 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa } -void DisplaysView::arrow (glm::vec2 movement) +bool DisplaysView::doubleclic (glm::vec2 P) { - static float accumulator = 0.f; - accumulator += dt_; - - glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); - glm::vec3 gl_Position_to = Rendering::manager().unProject(movement, scene.root()->transform_); - glm::vec3 gl_delta = gl_Position_to - gl_Position_from; + if ( pick(P).first != nullptr) { + Rendering::manager().outputWindow().show(); + return true; + } + return false; +} + +void DisplaysView::arrow (glm::vec2 movement) +{ + // grab only works on selected output if not fullscreen + if (output_selected_ && !Settings::application.windows[1].fullscreen) { + + // operate in pixel coordinates + static glm::vec2 p; + + // initiate movement (only once) + if (!current_action_ongoing_) { + + // initial position + p.x = (output_->translation_.x - output_->scale_.x) / DISPLAYS_UNIT; + p.y = (output_->translation_.y + output_->scale_.y) / - DISPLAYS_UNIT; + + // initiate (terminated at key release) + current_action_ongoing_ = true; + } + + // add movement vector to position (pixel precision) + p += movement ; //* (dt_ * 0.5f); + + // discretized translation with ALT + if (UserInterface::manager().altModifier()) { + glm::vec2 q; + q.x = ROUND(p.x, 0.05f); // 20 pix precision + q.y = ROUND(p.y, 0.05f); + // convert back to output-frame coordinates + output_->translation_.x = (q.x * DISPLAYS_UNIT) + output_->scale_.x; + output_->translation_.y = (q.y * - DISPLAYS_UNIT) - output_->scale_.y; + } + else + { + // convert back to output-frame coordinates + output_->translation_.x = (p.x * DISPLAYS_UNIT) + output_->scale_.x; + output_->translation_.y = (p.y * - DISPLAYS_UNIT) - output_->scale_.y; + } + + } } diff --git a/src/DisplaysView.h b/src/DisplaysView.h index 439a20e..52cb1f9 100644 --- a/src/DisplaysView.h +++ b/src/DisplaysView.h @@ -24,6 +24,7 @@ public: void terminate (bool force = false) override; Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair pick) override; void arrow (glm::vec2) override; + bool doubleclic (glm::vec2) override; glm::ivec4 outputCoordinates() const; std::string outputFullscreenMonitor() const; @@ -44,7 +45,7 @@ private: bool output_selected_; bool show_output_menu_; int display_action_; - bool update_pending_; + bool draw_pending_; std::string output_monitor_; }; diff --git a/src/RenderingManager.cpp b/src/RenderingManager.cpp index ca6c48a..ec7cd9a 100644 --- a/src/RenderingManager.cpp +++ b/src/RenderingManager.cpp @@ -810,8 +810,8 @@ void RenderingWindow::changeFullscreen_() void RenderingWindow::setCoordinates(glm::ivec4 rect) { - glfwSetWindowPos( window_, rect.x, rect.y); glfwSetWindowSize( window_, rect.p, rect.q); + glfwSetWindowPos( window_, rect.x, rect.y); } int RenderingWindow::width() @@ -861,10 +861,8 @@ bool RenderingWindow::init(int index, GLFWwindow *share) if (master_ != nullptr) { // special window type for output - glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); -// glfwSetWindowAttrib( window_, GLFW_DECORATED, GLFW_FALSE); -// glfwSetWindowAttrib( window_, GLFW_RESIZABLE, GLFW_FALSE); + glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); } // create the window diff --git a/src/TextureView.cpp b/src/TextureView.cpp index e700501..e6d4638 100644 --- a/src/TextureView.cpp +++ b/src/TextureView.cpp @@ -571,7 +571,7 @@ void TextureView::draw() { // style grey - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(COLOR_APPEARANCE_LIGHT, 1.0f)); // 1 + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.0f)); // 1 ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.f)); ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.24f, 0.24f, 0.24f, 0.46f)); diff --git a/src/TransitionView.cpp b/src/TransitionView.cpp index acd242a..d1ed4dd 100644 --- a/src/TransitionView.cpp +++ b/src/TransitionView.cpp @@ -437,6 +437,12 @@ View::Cursor TransitionView::grab (Source *s, glm::vec2 from, glm::vec2 to, std: return Cursor(Cursor_ResizeEW, info.str() ); } +bool TransitionView::doubleclic (glm::vec2 ) +{ + Mixer::manager().setView(View::MIXING); + return true; +} + void TransitionView::arrow (glm::vec2 movement) { Source *s = Mixer::manager().currentSource(); diff --git a/src/TransitionView.h b/src/TransitionView.h index 40c6391..cc09b5c 100644 --- a/src/TransitionView.h +++ b/src/TransitionView.h @@ -18,6 +18,7 @@ public: std::pair pick(glm::vec2 P) override; Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair pick) override; + bool doubleclic (glm::vec2) override; void arrow (glm::vec2) override; Cursor drag (glm::vec2, glm::vec2) override; diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index b93dd14..02bf24c 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -595,12 +595,9 @@ void UserInterface::handleMouse() if ( ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) ) { - // double clic in Transition view means quit - if (Settings::application.current_view == View::TRANSITION) { - Mixer::manager().setView(View::MIXING); - } - // double clic in other views means toggle pannel - else { + // if double clic action of view didn't succeed + if ( !Mixer::manager().view()->doubleclic(mousepos) ) { + // default behavior : if (navigator.pannelVisible()) // discard current to select front most source // (because single clic maintains same source active) @@ -676,9 +673,11 @@ void UserInterface::handleMouse() } else { // cancel all operations on view when interacting on GUI + if (mousedown || view_drag) + Mixer::manager().view()->terminate(); + view_drag = nullptr; mousedown = false; - Mixer::manager().view()->terminate(); } @@ -4312,7 +4311,7 @@ void OutputPreview::Render() h += (Settings::application.accept_connections ? 1.f : 0.f); draw_list->AddRectFilled(draw_pos, ImVec2(draw_pos.x + imagesize.x, draw_pos.y + h * r), IMGUI_COLOR_OVERLAY); ImGui::SetCursorScreenPos(draw_pos); - ImGui::Text(" " ICON_FA_TV " %d x %d px, %.d fps", output->width(), output->height(), int(Mixer::manager().fps()) ); + ImGui::Text(" " ICON_FA_LAPTOP " %d x %d px, %.d fps", output->width(), output->height(), int(Mixer::manager().fps()) ); if (Settings::application.accept_connections) ImGui::Text( " " ICON_FA_SHARE_ALT_SQUARE " Available as %s (%ld peer connected)", Connection::manager().info().name.c_str(), diff --git a/src/View.h b/src/View.h index 9b18141..c73c4a7 100644 --- a/src/View.h +++ b/src/View.h @@ -86,6 +86,11 @@ public: return Cursor (); } + // test mouse over provided a point in screen coordinates + virtual bool doubleclic (glm::vec2) { + return false; + } + // left-right [-1 1] and up-down [1 -1] action from arrow keys virtual void arrow (glm::vec2) {}