mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-15 04:09:59 +01:00
New Distortion of output window in Displays view
Allows shape distortion of output rendering (e.g. for perspective correction of projection), added Grid snap cursor support in Displays view
This commit is contained in:
@@ -40,10 +40,12 @@
|
|||||||
#include "Source.h"
|
#include "Source.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "PickingVisitor.h"
|
#include "PickingVisitor.h"
|
||||||
|
#include "DrawVisitor.h"
|
||||||
#include "Decorations.h"
|
#include "Decorations.h"
|
||||||
#include "UserInterfaceManager.h"
|
#include "UserInterfaceManager.h"
|
||||||
#include "BoundingBoxVisitor.h"
|
#include "BoundingBoxVisitor.h"
|
||||||
#include "RenderingManager.h"
|
#include "RenderingManager.h"
|
||||||
|
#include "MousePointer.h"
|
||||||
|
|
||||||
#include "DisplaysView.h"
|
#include "DisplaysView.h"
|
||||||
|
|
||||||
@@ -78,7 +80,7 @@ DisplaysView::DisplaysView() : View(DISPLAYS)
|
|||||||
for (auto w = windows_.begin(); w != windows_.end(); ++w){
|
for (auto w = windows_.begin(); w != windows_.end(); ++w){
|
||||||
|
|
||||||
// surface & buffer for render
|
// surface & buffer for render
|
||||||
w->output_render_ = new Surface;
|
w->output_render_ = new MeshSurface;
|
||||||
w->renderbuffer_ = new FrameBuffer(1024, 1024);
|
w->renderbuffer_ = new FrameBuffer(1024, 1024);
|
||||||
|
|
||||||
// root node
|
// root node
|
||||||
@@ -123,9 +125,9 @@ DisplaysView::DisplaysView() : View(DISPLAYS)
|
|||||||
w->mode_ = new Switch;
|
w->mode_ = new Switch;
|
||||||
g->attach(w->mode_);
|
g->attach(w->mode_);
|
||||||
// mode_ [0] is for WINDOWED
|
// mode_ [0] is for WINDOWED
|
||||||
w->handles_ = new Handles(Handles::SCALE);
|
w->resize_ = new Handles(Handles::SCALE);
|
||||||
w->handles_->color = glm::vec4( COLOR_WINDOW, 1.f );
|
w->resize_->color = glm::vec4( COLOR_WINDOW, 1.f );
|
||||||
w->mode_->attach(w->handles_);
|
w->mode_->attach(w->resize_);
|
||||||
// mode_ [1] is for FULLSCREEN
|
// mode_ [1] is for FULLSCREEN
|
||||||
w->fullscreen_ = new Symbol(Symbol::TELEVISION);
|
w->fullscreen_ = new Symbol(Symbol::TELEVISION);
|
||||||
w->fullscreen_->scale_ = glm::vec3(2.f, 2.f, 1.f);
|
w->fullscreen_->scale_ = glm::vec3(2.f, 2.f, 1.f);
|
||||||
@@ -134,12 +136,27 @@ DisplaysView::DisplaysView() : View(DISPLAYS)
|
|||||||
// Output frame
|
// Output frame
|
||||||
w->output_group_ = new Group;
|
w->output_group_ = new Group;
|
||||||
w->root_->attach(w->output_group_);
|
w->root_->attach(w->output_group_);
|
||||||
w->output_frame_ = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE);
|
w->output_handles_[0] = new Handles(Handles::NODE_LOWER_LEFT);
|
||||||
w->output_frame_->color = glm::vec4( COLOR_FRAME, 1.f );
|
w->output_handles_[0]->color = glm::vec4( COLOR_FRAME, 1.f );
|
||||||
w->output_group_->attach(w->output_frame_);
|
w->output_group_->attach(w->output_handles_[0]);
|
||||||
w->output_handles_ = new Handles(Handles::RESIZE);
|
w->output_handles_[1] = new Handles(Handles::NODE_UPPER_LEFT);
|
||||||
w->output_handles_->color = glm::vec4( COLOR_FRAME, 1.f );
|
w->output_handles_[1]->color = glm::vec4( COLOR_FRAME, 1.f );
|
||||||
w->output_group_->attach(w->output_handles_);
|
w->output_group_->attach(w->output_handles_[1]);
|
||||||
|
w->output_handles_[2] = new Handles(Handles::NODE_LOWER_RIGHT);
|
||||||
|
w->output_handles_[2]->color = glm::vec4( COLOR_FRAME, 1.f );
|
||||||
|
w->output_group_->attach(w->output_handles_[2]);
|
||||||
|
w->output_handles_[3] = new Handles(Handles::NODE_UPPER_RIGHT);
|
||||||
|
w->output_handles_[3]->color = glm::vec4( COLOR_FRAME, 1.f );
|
||||||
|
w->output_group_->attach(w->output_handles_[3]);
|
||||||
|
std::vector<glm::vec2> path;
|
||||||
|
path.push_back(glm::vec2(-1.f, -1.f));
|
||||||
|
path.push_back(glm::vec2(-1.f, 1.f));
|
||||||
|
path.push_back(glm::vec2( 1.f, 1.f));
|
||||||
|
path.push_back(glm::vec2( 1.f, -1.f));
|
||||||
|
w->output_lines_ = new LineLoop(path, 2.f);
|
||||||
|
w->output_lines_->shader()->color = glm::vec4(COLOR_FRAME, 0.96f);
|
||||||
|
w->output_group_->attach(w->output_lines_);
|
||||||
|
|
||||||
// default to not active & window overlay frame
|
// default to not active & window overlay frame
|
||||||
w->output_group_->visible_ = false;
|
w->output_group_->visible_ = false;
|
||||||
w->overlays_->setActive(0);
|
w->overlays_->setActive(0);
|
||||||
@@ -153,6 +170,17 @@ DisplaysView::DisplaysView() : View(DISPLAYS)
|
|||||||
current_output_status_ = new Group;
|
current_output_status_ = new Group;
|
||||||
draw_pending_ = false;
|
draw_pending_ = false;
|
||||||
output_ar = 1.f;
|
output_ar = 1.f;
|
||||||
|
|
||||||
|
// grid is attached to a transform group
|
||||||
|
// to adapt to windows geometry; see adaptGridToWindow()
|
||||||
|
gridroot_ = new Group;
|
||||||
|
gridroot_->visible_ = false;
|
||||||
|
scene.root()->attach(gridroot_);
|
||||||
|
|
||||||
|
// replace grid with appropriate one
|
||||||
|
if (grid) delete grid;
|
||||||
|
grid = new TranslationGrid(gridroot_);
|
||||||
|
grid->root()->visible_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplaysView::update(float dt)
|
void DisplaysView::update(float dt)
|
||||||
@@ -164,49 +192,97 @@ void DisplaysView::update(float dt)
|
|||||||
|
|
||||||
// update rendering of render frame
|
// update rendering of render frame
|
||||||
for (int i = 0; i < MAX_OUTPUT_WINDOW; ++i) {
|
for (int i = 0; i < MAX_OUTPUT_WINDOW; ++i) {
|
||||||
windows_[i].output_render_->setTextureIndex( Rendering::manager().outputWindow(i).texture() );
|
|
||||||
|
|
||||||
// update visible flag
|
// ensure to update texture index
|
||||||
windows_[i].root_->visible_ = i < Settings::application.num_output_windows;
|
windows_[i].output_render_->setTextureIndex(
|
||||||
windows_[i].icon_->visible_ = Settings::application.render.disabled;
|
Rendering::manager().outputWindow(i).texture());
|
||||||
|
|
||||||
// Rendering of output is scaled to content and manipulated by output frame
|
// avoid busy update
|
||||||
if (Settings::application.windows[i+1].scaled) {
|
if (windows_[i].need_update_) {
|
||||||
windows_[i].output_render_->scale_ = windows_[i].output_group_->scale_;
|
--windows_[i].need_update_;
|
||||||
windows_[i].output_render_->translation_ = windows_[i].output_group_->translation_;
|
|
||||||
// show output frame
|
|
||||||
windows_[i].output_group_->visible_ = true;
|
|
||||||
}
|
|
||||||
// Rendering of output is adjusted to match aspect ratio of framebuffer
|
|
||||||
else {
|
|
||||||
float out_ar = windows_[i].root_->scale_.x / windows_[i].root_->scale_.y;
|
|
||||||
if (output_ar < out_ar)
|
|
||||||
windows_[i].output_render_->scale_ = glm::vec3(output_ar / out_ar, 1.f, 1.f);
|
|
||||||
else
|
|
||||||
windows_[i].output_render_->scale_ = glm::vec3(1.f, out_ar / output_ar, 1.f);
|
|
||||||
// reset translation
|
|
||||||
windows_[i].output_render_->translation_ = glm::vec3(0.f);
|
|
||||||
// do not show output frame
|
|
||||||
windows_[i].output_group_->visible_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( current_window_ == i ) {
|
// update visible flag
|
||||||
windows_[i].overlays_->setActive(1);
|
windows_[i].root_->visible_ = i < Settings::application.num_output_windows;
|
||||||
windows_[i].output_handles_->visible_ = true;
|
windows_[i].icon_->visible_ = Settings::application.render.disabled;
|
||||||
windows_[i].output_frame_->color = glm::vec4( COLOR_FRAME, 1.f );
|
|
||||||
windows_[i].title_->shader()->color = glm::vec4( COLOR_WINDOW, 1.f );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
windows_[i].overlays_->setActive(0);
|
|
||||||
windows_[i].output_handles_->visible_ = false;
|
|
||||||
windows_[i].output_frame_->color = glm::vec4( COLOR_FRAME, 0.3f );
|
|
||||||
windows_[i].title_->shader()->color = glm::vec4( COLOR_WINDOW, 0.8f );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Rendering of output is distorted with custom fit
|
||||||
|
if (Settings::application.windows[i+1].custom) {
|
||||||
|
|
||||||
|
// reset scale
|
||||||
|
windows_[i].output_render_->scale_ = glm::vec3(1.f);
|
||||||
|
|
||||||
|
// update node distortion
|
||||||
|
windows_[i].output_group_->data_ = Settings::application.windows[i + 1].nodes;
|
||||||
|
for (int k = 0; k < 4; ++k) {
|
||||||
|
windows_[i].output_handles_[k]->translation_.x
|
||||||
|
= windows_[i].output_group_->data_[k].x;
|
||||||
|
windows_[i].output_handles_[k]->translation_.y
|
||||||
|
= windows_[i].output_group_->data_[k].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the shape of the distorted outline
|
||||||
|
std::vector<glm::vec2> path;
|
||||||
|
path.push_back(glm::vec2(-1.f, -1.f) + glm::vec2(windows_[i].output_handles_[0]->translation_));
|
||||||
|
path.push_back(glm::vec2(-1.f, 1.f) + glm::vec2(windows_[i].output_handles_[1]->translation_));
|
||||||
|
path.push_back(glm::vec2( 1.f, 1.f) + glm::vec2(windows_[i].output_handles_[3]->translation_));
|
||||||
|
path.push_back(glm::vec2( 1.f, -1.f) + glm::vec2(windows_[i].output_handles_[2]->translation_));
|
||||||
|
windows_[i].output_lines_->changePath(path);
|
||||||
|
|
||||||
|
// apply nodes distortion
|
||||||
|
ImageShader *is = dynamic_cast<ImageShader*>(windows_[i].output_render_->shader());
|
||||||
|
is->iNodes = windows_[i].output_group_->data_;
|
||||||
|
|
||||||
|
// show output frame
|
||||||
|
windows_[i].output_group_->visible_ = true;
|
||||||
|
}
|
||||||
|
// Rendering of output is adjusted to match aspect ratio of framebuffer
|
||||||
|
else {
|
||||||
|
// apply scaling
|
||||||
|
float out_ar = windows_[i].root_->scale_.x / windows_[i].root_->scale_.y;
|
||||||
|
if (output_ar < out_ar)
|
||||||
|
windows_[i].output_render_->scale_ = glm::vec3(output_ar / out_ar, 1.f, 1.f);
|
||||||
|
else
|
||||||
|
windows_[i].output_render_->scale_ = glm::vec3(1.f, out_ar / output_ar, 1.f);
|
||||||
|
|
||||||
|
// reset nodes distortion
|
||||||
|
ImageShader *is = dynamic_cast<ImageShader*>(windows_[i].output_render_->shader());
|
||||||
|
is->iNodes = glm::zero<glm::mat4>();
|
||||||
|
|
||||||
|
// do not show output frame
|
||||||
|
windows_[i].output_group_->visible_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight current window
|
||||||
|
if ( current_window_ == i ) {
|
||||||
|
windows_[i].overlays_->setActive(1);
|
||||||
|
for (int k = 0; k < 4; ++k)
|
||||||
|
windows_[i].output_handles_[k]->visible_ = true;
|
||||||
|
windows_[i].output_lines_->shader()->color = glm::vec4( COLOR_FRAME, 0.96f );
|
||||||
|
windows_[i].title_->shader()->color = glm::vec4( COLOR_WINDOW, 1.f );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
windows_[i].overlays_->setActive(0);
|
||||||
|
for (int k = 0; k < 4; ++k)
|
||||||
|
windows_[i].output_handles_[k]->visible_ = false;
|
||||||
|
windows_[i].output_lines_->shader()->color = glm::vec4( COLOR_FRAME, 0.3f );
|
||||||
|
windows_[i].title_->shader()->color = glm::vec4( COLOR_WINDOW, 0.8f );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output_ar = Mixer::manager().session()->frame()->aspectRatio();
|
output_ar = Mixer::manager().session()->frame()->aspectRatio();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a more complete update is requested
|
||||||
|
if (View::need_deep_update_ > 0) {
|
||||||
|
// change grid color
|
||||||
|
ImVec4 c = ImGuiToolkit::HighlightColor();
|
||||||
|
grid->setColor( glm::vec4(c.x, c.y, c.z, 0.3) );
|
||||||
|
|
||||||
|
// force update
|
||||||
|
for (int i = 0; i < MAX_OUTPUT_WINDOW; ++i)
|
||||||
|
++windows_[i].need_update_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -310,6 +386,42 @@ int DisplaysView::size ()
|
|||||||
return (int) ( sqrt(z) * 100.f);
|
return (int) ( sqrt(z) * 100.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DisplaysView::adaptGridToWindow(int w)
|
||||||
|
{
|
||||||
|
// reset by default
|
||||||
|
gridroot_->scale_ = glm::vec3(1.f);
|
||||||
|
gridroot_->translation_ = glm::vec3(0.f);
|
||||||
|
grid->setAspectRatio(1.f);
|
||||||
|
|
||||||
|
// adapt grid scaling to given window if parameter is given
|
||||||
|
if (w > -1) {
|
||||||
|
gridroot_->scale_.x = windows_[w].root_->scale_.x;
|
||||||
|
gridroot_->scale_.y = windows_[w].root_->scale_.y;
|
||||||
|
gridroot_->translation_.x = windows_[w].root_->translation_.x;
|
||||||
|
gridroot_->translation_.y = windows_[w].root_->translation_.y;
|
||||||
|
|
||||||
|
if (!Settings::application.proportional_grid)
|
||||||
|
grid->setAspectRatio((float) windows_[w].root_->scale_.y / windows_[w].root_->scale_.x);
|
||||||
|
|
||||||
|
}
|
||||||
|
// set grid aspect ratio to display size otherwise
|
||||||
|
else if (current_window_ > -1) {
|
||||||
|
|
||||||
|
if (Settings::application.proportional_grid) {
|
||||||
|
std::string m = Rendering::manager()
|
||||||
|
.monitorNameAt(Settings::application.windows[current_window_ + 1].x,
|
||||||
|
Settings::application.windows[current_window_ + 1].y);
|
||||||
|
glm::ivec4 rect = Rendering::manager().monitors()[m];
|
||||||
|
|
||||||
|
gridroot_->translation_.x = rect.x * DISPLAYS_UNIT;
|
||||||
|
gridroot_->translation_.y = rect.y * -DISPLAYS_UNIT;
|
||||||
|
gridroot_->scale_.x = rect.p * 0.5f * DISPLAYS_UNIT;
|
||||||
|
gridroot_->scale_.y = rect.q * 0.5f * DISPLAYS_UNIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DisplaysView::draw()
|
void DisplaysView::draw()
|
||||||
{
|
{
|
||||||
// White ballance color button
|
// White ballance color button
|
||||||
@@ -419,14 +531,19 @@ void DisplaysView::draw()
|
|||||||
windows_[i].title_->translation_.y = 1.f + windows_[i].title_->scale_.y;
|
windows_[i].title_->translation_.y = 1.f + windows_[i].title_->scale_.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
windows_[i].output_group_->scale_ = Settings::application.windows[i+1].scale;
|
|
||||||
windows_[i].output_group_->translation_ = Settings::application.windows[i+1].translation;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// main call to draw the view
|
// main call to draw the view
|
||||||
View::draw();
|
View::draw();
|
||||||
|
|
||||||
|
// Display grid in overlay
|
||||||
|
if (grid->active() && current_action_ongoing_) {
|
||||||
|
const glm::mat4 projection = Rendering::manager().Projection();
|
||||||
|
DrawVisitor draw_grid(grid->root(), projection, true);
|
||||||
|
scene.accept(draw_grid);
|
||||||
|
}
|
||||||
|
|
||||||
// display interface
|
// display interface
|
||||||
// Locate window at upper left corner
|
// Locate window at upper left corner
|
||||||
glm::vec2 P = glm::vec2(0.01f, 0.01 );
|
glm::vec2 P = glm::vec2(0.01f, 0.01 );
|
||||||
@@ -463,6 +580,7 @@ void DisplaysView::draw()
|
|||||||
if (ImGuiToolkit::IconButton(18, 4, "More windows")) {
|
if (ImGuiToolkit::IconButton(18, 4, "More windows")) {
|
||||||
++Settings::application.num_output_windows;
|
++Settings::application.num_output_windows;
|
||||||
current_window_ = Settings::application.num_output_windows-1;
|
current_window_ = Settings::application.num_output_windows-1;
|
||||||
|
windows_[current_window_].need_update_ += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -488,10 +606,12 @@ void DisplaysView::draw()
|
|||||||
|
|
||||||
// Output options
|
// Output options
|
||||||
ImGui::SameLine(0, 2.f * g.Style.FramePadding.x);
|
ImGui::SameLine(0, 2.f * g.Style.FramePadding.x);
|
||||||
ImGuiToolkit::ButtonIconToggle(9,5, &Settings::application.windows[1+current_window_].scaled, "Custom fit");
|
if ( ImGuiToolkit::ButtonIconToggle(9,5, &Settings::application.windows[1+current_window_].custom, "Custom fit") )
|
||||||
|
++windows_[current_window_].need_update_;
|
||||||
|
|
||||||
ImGui::SameLine(0, g.Style.FramePadding.x);
|
ImGui::SameLine(0, g.Style.FramePadding.x);
|
||||||
ImGuiToolkit::ButtonIconToggle(11,1, &Settings::application.windows[1+current_window_].show_pattern, "Test pattern");
|
if ( ImGuiToolkit::ButtonIconToggle(11,1, &Settings::application.windows[1+current_window_].show_pattern, "Test pattern") )
|
||||||
|
++windows_[current_window_].need_update_;
|
||||||
|
|
||||||
ImGui::SameLine(0, 1.5f * g.Style.FramePadding.x);
|
ImGui::SameLine(0, 1.5f * g.Style.FramePadding.x);
|
||||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||||
@@ -548,7 +668,6 @@ void DisplaysView::draw()
|
|||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ImGui::PopStyleColor(8);
|
ImGui::PopStyleColor(8);
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
@@ -584,6 +703,7 @@ void DisplaysView::draw()
|
|||||||
if (ImGui::MenuItem( menutext.c_str(), nullptr, _fullscreen )){
|
if (ImGui::MenuItem( menutext.c_str(), nullptr, _fullscreen )){
|
||||||
windows_[current_window_].monitor_ = monitor_iter->first;
|
windows_[current_window_].monitor_ = monitor_iter->first;
|
||||||
Rendering::manager().outputWindow(current_window_).setFullscreen( windows_[current_window_].monitor_ );
|
Rendering::manager().outputWindow(current_window_).setFullscreen( windows_[current_window_].monitor_ );
|
||||||
|
windows_[current_window_].need_update_ += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,16 +713,17 @@ void DisplaysView::draw()
|
|||||||
Rendering::manager().outputWindow(current_window_).exitFullscreen();
|
Rendering::manager().outputWindow(current_window_).exitFullscreen();
|
||||||
// not fullscreen on a monitor
|
// not fullscreen on a monitor
|
||||||
windows_[current_window_].monitor_ = "";
|
windows_[current_window_].monitor_ = "";
|
||||||
|
windows_[current_window_].need_update_ += 2;
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
bool _borderless = !Settings::application.windows[current_window_+1].decorated;
|
bool _borderless = !Settings::application.windows[current_window_+1].decorated;
|
||||||
if (ImGui::MenuItem( ICON_FA_SQUARE_FULL " Borderless", nullptr, &_borderless, _windowed)){
|
if (ImGui::MenuItem( ICON_FA_SQUARE_FULL " Borderless", nullptr, &_borderless, _windowed)){
|
||||||
Rendering::manager().outputWindow(current_window_).setDecoration(!_borderless);
|
Rendering::manager().outputWindow(current_window_).setDecoration(!_borderless);
|
||||||
|
++windows_[current_window_].need_update_;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem( ICON_FA_EXPAND " Fit all Displays", nullptr, false, _windowed )){
|
if (ImGui::MenuItem( ICON_FA_EXPAND " Fit all Displays", nullptr, false, _windowed )){
|
||||||
|
|
||||||
Rendering::manager().outputWindow(current_window_).setDecoration(false);
|
Rendering::manager().outputWindow(current_window_).setDecoration(false);
|
||||||
glm::ivec4 rect (INT_MAX, INT_MAX, 0, 0);
|
glm::ivec4 rect (INT_MAX, INT_MAX, 0, 0);
|
||||||
std::map<std::string, glm::ivec4> _monitors = Rendering::manager().monitors();
|
std::map<std::string, glm::ivec4> _monitors = Rendering::manager().monitors();
|
||||||
@@ -614,6 +735,7 @@ void DisplaysView::draw()
|
|||||||
rect.q = MAX(rect.q, monitor_iter->second.y+monitor_iter->second.q);
|
rect.q = MAX(rect.q, monitor_iter->second.y+monitor_iter->second.q);
|
||||||
}
|
}
|
||||||
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
||||||
|
windows_[current_window_].need_update_ += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem( ICON_FA_EXPAND_ALT " Restore aspect ratio" , nullptr, false, _windowed )){
|
if (ImGui::MenuItem( ICON_FA_EXPAND_ALT " Restore aspect ratio" , nullptr, false, _windowed )){
|
||||||
@@ -625,6 +747,7 @@ void DisplaysView::draw()
|
|||||||
else
|
else
|
||||||
rect.q = rect.p / ar;
|
rect.q = rect.p / ar;
|
||||||
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
||||||
|
windows_[current_window_].need_update_ += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem( ICON_FA_RULER_COMBINED " Rescale to pixel size", nullptr, false, _windowed )){
|
if (ImGui::MenuItem( ICON_FA_RULER_COMBINED " Rescale to pixel size", nullptr, false, _windowed )){
|
||||||
@@ -633,6 +756,7 @@ void DisplaysView::draw()
|
|||||||
rect.p = Mixer::manager().session()->frame()->width();
|
rect.p = Mixer::manager().session()->frame()->width();
|
||||||
rect.q = Mixer::manager().session()->frame()->height();
|
rect.q = Mixer::manager().session()->frame()->height();
|
||||||
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
||||||
|
windows_[current_window_].need_update_ += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
@@ -642,24 +766,21 @@ void DisplaysView::draw()
|
|||||||
rect.q = Mixer::manager().session()->frame()->height();
|
rect.q = Mixer::manager().session()->frame()->height();
|
||||||
Rendering::manager().outputWindow(current_window_).setDecoration(true);
|
Rendering::manager().outputWindow(current_window_).setDecoration(true);
|
||||||
Settings::application.windows[1+current_window_].show_pattern = false;
|
Settings::application.windows[1+current_window_].show_pattern = false;
|
||||||
Settings::application.windows[1+current_window_].scaled = false;
|
Settings::application.windows[1+current_window_].custom = false;
|
||||||
Settings::application.windows[1+current_window_].scale = glm::vec3(1.f);
|
|
||||||
Settings::application.windows[1+current_window_].translation = glm::vec3(0.f);
|
|
||||||
Settings::application.windows[1+current_window_].whitebalance = glm::vec4(1.f, 1.f, 1.f, 0.5f);
|
Settings::application.windows[1+current_window_].whitebalance = glm::vec4(1.f, 1.f, 1.f, 0.5f);
|
||||||
if (Settings::application.windows[current_window_+1].fullscreen)
|
if (Settings::application.windows[current_window_+1].fullscreen)
|
||||||
Rendering::manager().outputWindow(current_window_).exitFullscreen();
|
Rendering::manager().outputWindow(current_window_).exitFullscreen();
|
||||||
else
|
else
|
||||||
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
||||||
|
windows_[current_window_].need_update_ += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Settings::application.windows[current_window_+1].scaled ) {
|
if ( Settings::application.windows[current_window_+1].custom ) {
|
||||||
ImGui::PopStyleColor(1);
|
ImGui::PopStyleColor(1);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(COLOR_FRAME, 1.f));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(COLOR_FRAME, 1.f));
|
||||||
|
if ( ImGui::MenuItem( ICON_FA_VECTOR_SQUARE " Reset custom fit") )
|
||||||
if ( ImGui::MenuItem( ICON_FA_VECTOR_SQUARE " Reset custom fit") ) {
|
Settings::application.windows[current_window_+1].nodes = glm::zero<glm::mat4>();
|
||||||
Settings::application.windows[1+current_window_].scale = glm::vec3(1.f);
|
windows_[current_window_].need_update_ += 2;
|
||||||
Settings::application.windows[1+current_window_].translation = glm::vec3(0.f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopStyleColor(2);
|
ImGui::PopStyleColor(2);
|
||||||
@@ -692,11 +813,19 @@ std::pair<Node *, glm::vec2> DisplaysView::pick(glm::vec2 P)
|
|||||||
show_window_menu_ = true;
|
show_window_menu_ = true;
|
||||||
|
|
||||||
// activate / deactivate window if clic on any element of it
|
// activate / deactivate window if clic on any element of it
|
||||||
if ( (pick.first == windows_[i].surface_) ||
|
if ((pick.first == windows_[i].surface_) ||
|
||||||
(pick.first == windows_[i].handles_) ||
|
(pick.first == windows_[i].resize_) ||
|
||||||
(pick.first == windows_[i].output_handles_) ||
|
(pick.first == windows_[i].menu_) ) {
|
||||||
(pick.first == windows_[i].menu_) ) {
|
|
||||||
current_window_ = i;
|
current_window_ = i;
|
||||||
|
adaptGridToWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pick.first == windows_[i].output_handles_[0]) ||
|
||||||
|
(pick.first == windows_[i].output_handles_[1]) ||
|
||||||
|
(pick.first == windows_[i].output_handles_[2]) ||
|
||||||
|
(pick.first == windows_[i].output_handles_[3]) ) {
|
||||||
|
current_window_ = i;
|
||||||
|
adaptGridToWindow(current_window_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,6 +833,10 @@ std::pair<Node *, glm::vec2> DisplaysView::pick(glm::vec2 P)
|
|||||||
if (current_window_ < 0)
|
if (current_window_ < 0)
|
||||||
pick.first = nullptr;
|
pick.first = nullptr;
|
||||||
|
|
||||||
|
// request update
|
||||||
|
for (int i = 0; i < MAX_OUTPUT_WINDOW; ++i)
|
||||||
|
++windows_[i].need_update_;
|
||||||
|
|
||||||
return pick;
|
return pick;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -725,20 +858,22 @@ void DisplaysView::select(glm::vec2 A, glm::vec2 B)
|
|||||||
// TODO Multiple window selection?
|
// TODO Multiple window selection?
|
||||||
|
|
||||||
if (!pv.empty()) {
|
if (!pv.empty()) {
|
||||||
|
|
||||||
// find which window was picked
|
// find which window was picked
|
||||||
auto itp = pv.rbegin();
|
auto itp = pv.rbegin();
|
||||||
for (; itp != pv.rend(); ++itp){
|
for (; itp != pv.rend(); ++itp){
|
||||||
// search for WindowPreview
|
// search for WindowPreview
|
||||||
auto w = std::find_if(windows_.begin(), windows_.end(), WindowPreview::hasNode(itp->first));
|
auto w = std::find_if(windows_.begin(), windows_.end(), WindowPreview::hasNode(itp->first));
|
||||||
if (w != windows_.end())
|
if (w != windows_.end()) {
|
||||||
// set current
|
// set current
|
||||||
current_window_ = (int) std::distance(windows_.begin(), w);
|
current_window_ = (int) std::distance(windows_.begin(), w);
|
||||||
|
++windows_[current_window_].need_update_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _prev_mouse_pointer = 0;
|
||||||
|
|
||||||
void DisplaysView::initiate()
|
void DisplaysView::initiate()
|
||||||
{
|
{
|
||||||
// initiate pending action
|
// initiate pending action
|
||||||
@@ -756,6 +891,7 @@ void DisplaysView::initiate()
|
|||||||
// initiated
|
// initiated
|
||||||
current_action_ = "";
|
current_action_ = "";
|
||||||
current_action_ongoing_ = true;
|
current_action_ongoing_ = true;
|
||||||
|
++windows_[current_window_].need_update_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,21 +916,24 @@ void DisplaysView::terminate(bool force)
|
|||||||
GlmToolkit::AxisAlignedBoundingBox _bb;
|
GlmToolkit::AxisAlignedBoundingBox _bb;
|
||||||
_bb.extend(glm::vec3(-1.f, -1.f, 0.f));
|
_bb.extend(glm::vec3(-1.f, -1.f, 0.f));
|
||||||
_bb.extend(glm::vec3(1.f, 1.f, 0.f));
|
_bb.extend(glm::vec3(1.f, 1.f, 0.f));
|
||||||
GlmToolkit::AxisAlignedBoundingBox output_bb = _bb.transformed( windows_[current_window_].output_group_->transform_ );
|
|
||||||
_bb = _bb.scaled(glm::vec3(0.9f));
|
_bb = _bb.scaled(glm::vec3(0.9f));
|
||||||
if ( !_bb.intersect(output_bb) || output_bb.area() < 0.1f ) {
|
GlmToolkit::AxisAlignedBoundingBox output_bb;
|
||||||
|
output_bb.extend(glm::vec3(-1.f, -1.f, 0.f)
|
||||||
|
+ windows_[current_window_].output_handles_[0]->translation_);
|
||||||
|
output_bb.extend(glm::vec3(-1.f, 1.f, 0.f)
|
||||||
|
+ windows_[current_window_].output_handles_[1]->translation_);
|
||||||
|
output_bb.extend(glm::vec3(1.f, -1.f, 0.f)
|
||||||
|
+ windows_[current_window_].output_handles_[2]->translation_);
|
||||||
|
output_bb.extend(glm::vec3(1.f, 1.f, 0.f)
|
||||||
|
+ windows_[current_window_].output_handles_[3]->translation_);
|
||||||
|
if (!_bb.intersect(output_bb) || output_bb.area() < 0.05f) {
|
||||||
// No intersection of output bounding box with window area : revert to previous
|
// No intersection of output bounding box with window area : revert to previous
|
||||||
windows_[current_window_].output_group_->scale_ = Settings::application.windows[current_window_+1].scale;
|
Settings::application.windows[current_window_ + 1].nodes = current_output_status_->data_;
|
||||||
windows_[current_window_].output_group_->translation_ = Settings::application.windows[current_window_+1].translation;
|
Log::Notify("Custom window output area outside window or too small");
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Apply output area recentering to actual output window
|
|
||||||
Settings::application.windows[current_window_+1].scale = windows_[current_window_].output_group_->scale_;
|
|
||||||
Settings::application.windows[current_window_+1].translation = windows_[current_window_].output_group_->translation_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset overlay of grab corner
|
// ensures update
|
||||||
windows_[current_window_].output_handles_->overlayActiveCorner(glm::vec2(0.f));
|
++windows_[current_window_].need_update_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// terminated
|
// terminated
|
||||||
@@ -811,8 +950,8 @@ glm::ivec4 DisplaysView::windowCoordinates(int index) const
|
|||||||
{
|
{
|
||||||
glm::ivec4 rect;
|
glm::ivec4 rect;
|
||||||
|
|
||||||
rect.x = (windows_[index].root_->translation_.x - windows_[index].root_->scale_.x) / DISPLAYS_UNIT;
|
rect.x = ceil( (windows_[index].root_->translation_.x - windows_[index].root_->scale_.x) / DISPLAYS_UNIT );
|
||||||
rect.y = (windows_[index].root_->translation_.y + windows_[index].root_->scale_.y) / - DISPLAYS_UNIT;
|
rect.y = ceil( (windows_[index].root_->translation_.y + windows_[index].root_->scale_.y) / - DISPLAYS_UNIT );
|
||||||
rect.p = 2.f * windows_[index].root_->scale_.x / DISPLAYS_UNIT;
|
rect.p = 2.f * windows_[index].root_->scale_.x / DISPLAYS_UNIT;
|
||||||
rect.q = 2.f * windows_[index].root_->scale_.y / DISPLAYS_UNIT;
|
rect.q = 2.f * windows_[index].root_->scale_.y / DISPLAYS_UNIT;
|
||||||
|
|
||||||
@@ -835,73 +974,71 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa
|
|||||||
glm::vec3 scene_translation = scene_to - scene_from;
|
glm::vec3 scene_translation = scene_to - scene_from;
|
||||||
|
|
||||||
// a window is currently selected
|
// a window is currently selected
|
||||||
if ( current_window_ > -1 ) {
|
if (current_window_ > -1) {
|
||||||
|
|
||||||
|
// which window is grabbed ?
|
||||||
|
Group *w = windows_[current_window_].root_;
|
||||||
|
|
||||||
|
// which handle is grabbed ?
|
||||||
|
size_t picked_handle_ = 4;
|
||||||
|
if (pick.first == windows_[current_window_].output_handles_[0])
|
||||||
|
picked_handle_ = 0;
|
||||||
|
else if (pick.first == windows_[current_window_].output_handles_[1])
|
||||||
|
picked_handle_ = 1;
|
||||||
|
else if (pick.first == windows_[current_window_].output_handles_[2])
|
||||||
|
picked_handle_ = 2;
|
||||||
|
else if (pick.first == windows_[current_window_].output_handles_[3])
|
||||||
|
picked_handle_ = 3;
|
||||||
|
|
||||||
// Grab handles of the output frame to adjust
|
// Grab handles of the output frame to adjust
|
||||||
if ( pick.first == windows_[current_window_].output_handles_ ) {
|
if (picked_handle_ < 4) {
|
||||||
|
|
||||||
// which corner was picked ?
|
// which corner was picked ?
|
||||||
glm::vec2 corner = glm::round(pick.second);
|
glm::vec2 corner = glm::round(pick.second);
|
||||||
// inform on which corner should be overlayed (opposite)
|
|
||||||
windows_[current_window_].output_handles_->overlayActiveCorner(-corner);
|
|
||||||
|
|
||||||
// transform from center to corner
|
// transform from center to corner
|
||||||
glm::mat4 T = GlmToolkit::transform(glm::vec3(corner.x, corner.y, 0.f), glm::vec3(0.f, 0.f, 0.f),
|
glm::mat4 T = GlmToolkit::transform(glm::vec3(corner.x, corner.y, 0.f), glm::vec3(0.f, 0.f, 0.f),
|
||||||
glm::vec3(1.f, 1.f, 1.f));
|
glm::vec3(1.f, 1.f, 1.f));
|
||||||
|
|
||||||
glm::mat4 root_to_corner_transform = T * glm::inverse(current_output_status_->transform_);
|
glm::mat4 root_to_corner_transform = T * glm::inverse(current_output_status_->transform_);
|
||||||
glm::mat4 corner_to_root_transform = glm::inverse(root_to_corner_transform);
|
glm::mat4 corner_to_root_transform = glm::inverse(root_to_corner_transform);
|
||||||
|
|
||||||
// transformation from scene to corner:
|
// transformation from scene to corner:
|
||||||
glm::mat4 scene_to_corner_transform = root_to_corner_transform * glm::inverse( current_window_status_->transform_);
|
glm::mat4 scene_to_corner_transform = root_to_corner_transform * glm::inverse( current_window_status_->transform_);
|
||||||
|
|
||||||
// compute cursor movement in corner reference frame
|
// compute cursor movement in corner reference frame
|
||||||
glm::vec4 corner_from = scene_to_corner_transform * glm::vec4( scene_from, 1.f );
|
glm::vec4 corner_from = scene_to_corner_transform * glm::vec4( scene_from, 1.f );
|
||||||
glm::vec4 corner_to = scene_to_corner_transform * glm::vec4( scene_to, 1.f );
|
glm::vec4 corner_to = scene_to_corner_transform * glm::vec4( scene_to, 1.f );
|
||||||
|
// get stored status
|
||||||
|
glm::vec3 node_pos = glm::vec3(current_output_status_->data_[picked_handle_].x,
|
||||||
|
current_output_status_->data_[picked_handle_].y,
|
||||||
|
0.f);
|
||||||
|
// Compute target coordinates of manipulated handle into CORNER reference frame
|
||||||
|
node_pos = root_to_corner_transform * glm::vec4(node_pos, 1.f);
|
||||||
|
// apply translation of target in CORNER
|
||||||
|
node_pos = glm::translate(glm::identity<glm::mat4>(), glm::vec3(corner_to - corner_from)) * glm::vec4(node_pos, 1.f);
|
||||||
|
// snap handle coordinates to grid (if active)
|
||||||
|
if ( grid->active() )
|
||||||
|
node_pos = grid->snap(node_pos);
|
||||||
|
// Diagonal SCALING with SHIFT
|
||||||
|
if (UserInterface::manager().shiftModifier())
|
||||||
|
node_pos.y = (corner.x * corner.y) * node_pos.x;
|
||||||
|
// Compute handle coordinates back in ROOT reference frame
|
||||||
|
node_pos = corner_to_root_transform * glm::vec4(node_pos, 1.f);
|
||||||
|
|
||||||
// operation of scaling in corner reference frame
|
// apply to output
|
||||||
glm::vec3 corner_scaling = glm::vec3(corner_to) / glm::vec3(corner_from);
|
Settings::application.windows[current_window_+1].nodes[picked_handle_].x = node_pos.x;
|
||||||
|
Settings::application.windows[current_window_+1].nodes[picked_handle_].y = node_pos.y;
|
||||||
|
|
||||||
// proportional SCALING with SHIFT
|
// show cursor hand
|
||||||
if (UserInterface::manager().shiftModifier()) {
|
ret.type = Cursor_Hand;
|
||||||
// calculate proportional scaling factor
|
// show info depending on corner picked
|
||||||
float factor = glm::length( glm::vec2( corner_to ) ) / glm::length( glm::vec2( corner_from ) );
|
if (picked_handle_ == 0)
|
||||||
// scale node
|
info << "Bottom-left";
|
||||||
windows_[current_window_].output_group_->scale_ = current_output_status_->scale_ * glm::vec3(factor, factor, 1.f);
|
else if (picked_handle_ == 1)
|
||||||
}
|
info << "Top-left";
|
||||||
// non-proportional CORNER RESIZE (normal case)
|
else if (picked_handle_ == 3)
|
||||||
else {
|
info << "Top-right";
|
||||||
// scale node
|
else
|
||||||
windows_[current_window_].output_group_->scale_ = current_output_status_->scale_ * corner_scaling;
|
info << "Bottom-right";
|
||||||
}
|
node_pos.x *= (float) Settings::application.windows[current_window_ + 1].w;
|
||||||
|
node_pos.y *= -1.f * (float) Settings::application.windows[current_window_ + 1].h;
|
||||||
// update corner scaling to apply to center coordinates
|
info << " +(" << std::fixed << std::setprecision(0) << node_pos.x << "," << node_pos.y << ")";
|
||||||
corner_scaling = windows_[current_window_].output_group_->scale_ / current_output_status_->scale_;
|
|
||||||
|
|
||||||
// TRANSLATION CORNER
|
|
||||||
// convert source position in corner reference frame
|
|
||||||
glm::vec4 center = root_to_corner_transform * glm::vec4( current_output_status_->translation_, 1.f);
|
|
||||||
// transform source center (in corner reference frame)
|
|
||||||
center = glm::scale(glm::identity<glm::mat4>(), corner_scaling) * center;
|
|
||||||
// convert center back into scene reference frame
|
|
||||||
center = corner_to_root_transform * center;
|
|
||||||
// apply to node
|
|
||||||
windows_[current_window_].output_group_->translation_ = glm::vec3(center);
|
|
||||||
|
|
||||||
// discretized scaling with ALT
|
|
||||||
if (UserInterface::manager().altModifier()) {
|
|
||||||
windows_[current_window_].output_group_->scale_ = glm::round( windows_[current_window_].output_group_->scale_ * 20.f) * 0.05f;
|
|
||||||
windows_[current_window_].output_group_->translation_ = glm::round( windows_[current_window_].output_group_->translation_ * 20.f) * 0.05f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// show cursor depending on diagonal (corner picked)
|
|
||||||
T = glm::rotate(glm::identity<glm::mat4>(), current_output_status_->rotation_.z, glm::vec3(0.f, 0.f, 1.f));
|
|
||||||
T = glm::scale(T, current_output_status_->scale_);
|
|
||||||
corner = T * glm::vec4( corner, 0.f, 0.f );
|
|
||||||
ret.type = corner.x * corner.y > 0.f ? Cursor_ResizeNESW : Cursor_ResizeNWSE;
|
|
||||||
|
|
||||||
info << "Output resized " << std::fixed << std::setprecision(1) << 100.f * windows_[current_window_].output_group_->scale_.x;
|
|
||||||
info << " x " << 100.f * windows_[current_window_].output_group_->scale_.y << " %";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab window not fullscreen : move or resizes
|
// grab window not fullscreen : move or resizes
|
||||||
@@ -911,23 +1048,29 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa
|
|||||||
if ( pick.first == windows_[current_window_].surface_ ){
|
if ( pick.first == windows_[current_window_].surface_ ){
|
||||||
|
|
||||||
// apply translation
|
// apply translation
|
||||||
windows_[current_window_].root_->translation_ = current_window_status_->translation_ + scene_translation;
|
w->translation_ = current_window_status_->translation_ + scene_translation;
|
||||||
glm::ivec4 r = windowCoordinates(current_window_);
|
|
||||||
|
|
||||||
// discretized translation with ALT
|
// snap coordinates to grid (if active)
|
||||||
if (UserInterface::manager().altModifier()) {
|
if (grid->active()) {
|
||||||
r.x = ROUND(r.x, 0.01f);
|
// get top left corner
|
||||||
r.y = ROUND(r.y, 0.01f);
|
glm::vec2 sc = glm::vec2(w->scale_) * glm::vec2(1.f, -1.f);
|
||||||
windows_[current_window_].root_->translation_.x = (r.x * DISPLAYS_UNIT) + windows_[current_window_].root_->scale_.x;
|
glm::vec2 top_left = glm::vec2(w->translation_) - sc;
|
||||||
windows_[current_window_].root_->translation_.y = (r.y * - DISPLAYS_UNIT) - windows_[current_window_].root_->scale_.y;
|
top_left -= glm::vec2(gridroot_->translation_);
|
||||||
|
// snap to grid
|
||||||
|
top_left = grid->snap(top_left / glm::vec2(gridroot_->scale_))
|
||||||
|
* glm::vec2(gridroot_->scale_);
|
||||||
|
top_left += glm::vec2(gridroot_->translation_);
|
||||||
|
// revert to center coordinates
|
||||||
|
w->translation_ = glm::vec3(top_left, 0.f) + glm::vec3(sc, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show move cursor
|
// Show move cursor
|
||||||
ret.type = Cursor_ResizeAll;
|
ret.type = Cursor_ResizeAll;
|
||||||
|
glm::ivec4 r = windowCoordinates(current_window_);
|
||||||
info << "Window position " << r.x << ", " << r.y << " px";
|
info << "Window position " << r.x << ", " << r.y << " px";
|
||||||
}
|
}
|
||||||
// grab handle to resize
|
// grab handle to resize
|
||||||
else if ( pick.first == windows_[current_window_].handles_ ){
|
else if ( pick.first == windows_[current_window_].resize_ ){
|
||||||
|
|
||||||
// which corner was picked ?
|
// which corner was picked ?
|
||||||
glm::vec2 corner = glm::round(pick.second);
|
glm::vec2 corner = glm::round(pick.second);
|
||||||
@@ -942,7 +1085,8 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa
|
|||||||
|
|
||||||
// compute cursor movement in corner reference frame
|
// compute cursor movement in corner reference frame
|
||||||
glm::vec4 corner_from = scene_to_corner_transform * glm::vec4( scene_from, 1.f );
|
glm::vec4 corner_from = scene_to_corner_transform * glm::vec4( scene_from, 1.f );
|
||||||
glm::vec4 corner_to = scene_to_corner_transform * glm::vec4( scene_to, 1.f );
|
glm::vec4 corner_to = scene_to_corner_transform * glm::vec4(scene_to, 1.f);
|
||||||
|
|
||||||
|
|
||||||
// operation of scaling in corner reference frame
|
// operation of scaling in corner reference frame
|
||||||
glm::vec3 corner_scaling = glm::vec3(corner_to) / glm::vec3(corner_from);
|
glm::vec3 corner_scaling = glm::vec3(corner_to) / glm::vec3(corner_from);
|
||||||
@@ -952,30 +1096,16 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa
|
|||||||
// proportional SCALING with SHIFT
|
// proportional SCALING with SHIFT
|
||||||
if (UserInterface::manager().shiftModifier()) {
|
if (UserInterface::manager().shiftModifier()) {
|
||||||
// calculate proportional scaling factor
|
// calculate proportional scaling factor
|
||||||
float factor = glm::length( glm::vec2( corner_to ) ) / glm::length( glm::vec2( corner_from ) );
|
float factor = glm::length(glm::vec2(corner_to)) / glm::length(glm::vec2(corner_from));
|
||||||
// scale node
|
w->scale_ = current_window_status_->scale_ * glm::vec3(factor, factor, 1.f);
|
||||||
windows_[current_window_].root_->scale_ = current_window_status_->scale_ * glm::vec3(factor, factor, 1.f);
|
|
||||||
}
|
}
|
||||||
// non-proportional CORNER RESIZE (normal case)
|
// non-proportional CORNER RESIZE (normal case)
|
||||||
else {
|
else {
|
||||||
// scale node
|
w->scale_ = current_window_status_->scale_ * corner_scaling;
|
||||||
windows_[current_window_].root_->scale_ = current_window_status_->scale_ * corner_scaling;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// discretized scaling with ALT
|
|
||||||
if (UserInterface::manager().altModifier()) {
|
|
||||||
// calculate ratio of scaling modulo the output resolution
|
|
||||||
glm::vec3 outputsize = windows_[current_window_].root_->scale_ / DISPLAYS_UNIT;
|
|
||||||
glm::vec3 framesize = Mixer::manager().session()->frame()->resolution();
|
|
||||||
glm::vec3 ra = outputsize / framesize;
|
|
||||||
ra.x = ROUND(ra.x, 20.f);
|
|
||||||
ra.y = ROUND(ra.y, 20.f);
|
|
||||||
outputsize = ra * framesize;
|
|
||||||
windows_[current_window_].root_->scale_.x = outputsize.x * DISPLAYS_UNIT;
|
|
||||||
windows_[current_window_].root_->scale_.y = outputsize.y * DISPLAYS_UNIT;
|
|
||||||
}
|
|
||||||
// update corner scaling to apply to center coordinates
|
// update corner scaling to apply to center coordinates
|
||||||
corner_scaling = windows_[current_window_].root_->scale_ / current_window_status_->scale_;
|
corner_scaling = w->scale_ / current_window_status_->scale_;
|
||||||
|
|
||||||
// TRANSLATION CORNER
|
// TRANSLATION CORNER
|
||||||
// convert source position in corner reference frame
|
// convert source position in corner reference frame
|
||||||
@@ -985,10 +1115,28 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa
|
|||||||
// convert center back into scene reference frame
|
// convert center back into scene reference frame
|
||||||
center = corner_to_scene_transform * center;
|
center = corner_to_scene_transform * center;
|
||||||
// apply to node
|
// apply to node
|
||||||
windows_[current_window_].root_->translation_ = glm::vec3(center);
|
w->translation_ = glm::vec3(center);
|
||||||
|
|
||||||
|
// snap coordinates to grid (if active)
|
||||||
|
if (grid->active()) {
|
||||||
|
// get bottom right corner
|
||||||
|
glm::vec2 sc = glm::vec2(w->scale_) * glm::vec2(1.f, -1.f);
|
||||||
|
glm::vec2 bottom_right = glm::vec2(w->translation_) + sc;
|
||||||
|
bottom_right -= glm::vec2(gridroot_->translation_);
|
||||||
|
// snap corner to grid
|
||||||
|
bottom_right = grid->snap(bottom_right / glm::vec2(gridroot_->scale_))
|
||||||
|
* glm::vec2(gridroot_->scale_);
|
||||||
|
bottom_right += glm::vec2(gridroot_->translation_);
|
||||||
|
// recalculate center coordinates and scale
|
||||||
|
sc = glm::vec2(current_window_status_->scale_) * glm::vec2(1.f, -1.f);
|
||||||
|
glm::vec2 top_left = glm::vec2(current_window_status_->translation_) - sc;
|
||||||
|
glm::vec2 middle = top_left + (bottom_right - top_left) * 0.5f;
|
||||||
|
w->translation_ = glm::vec3(middle, 0.f);
|
||||||
|
w->scale_ = glm::vec3((bottom_right - top_left) * glm::vec2(0.5f, -0.5f), 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
// rescale title bar
|
// rescale title bar
|
||||||
windows_[current_window_].title_->scale_.y = WINDOW_TITLEBAR_HEIGHT / windows_[current_window_].root_->scale_.y;
|
windows_[current_window_].title_->scale_.y = WINDOW_TITLEBAR_HEIGHT / w->scale_.y;
|
||||||
windows_[current_window_].title_->translation_.y = 1.f + windows_[current_window_].title_->scale_.y;
|
windows_[current_window_].title_->translation_.y = 1.f + windows_[current_window_].title_->scale_.y;
|
||||||
|
|
||||||
// show cursor
|
// show cursor
|
||||||
@@ -1017,10 +1165,10 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa
|
|||||||
&& scene_to.y > r.y && scene_to.y < r.y + r.q) {
|
&& scene_to.y > r.y && scene_to.y < r.y + r.q) {
|
||||||
|
|
||||||
// show output frame on top of that monitor
|
// show output frame on top of that monitor
|
||||||
windows_[current_window_].root_->scale_.x = r.p * 0.5f * DISPLAYS_UNIT;
|
w->scale_.x = r.p * 0.5f * DISPLAYS_UNIT;
|
||||||
windows_[current_window_].root_->scale_.y = r.q * 0.5f * DISPLAYS_UNIT;
|
w->scale_.y = r.q * 0.5f * DISPLAYS_UNIT;
|
||||||
windows_[current_window_].root_->translation_.x = r.x * DISPLAYS_UNIT + windows_[current_window_].root_->scale_.x;
|
w->translation_.x = r.x * DISPLAYS_UNIT + w->scale_.x;
|
||||||
windows_[current_window_].root_->translation_.y = -r.y * DISPLAYS_UNIT - windows_[current_window_].root_->scale_.y;
|
w->translation_.y = -r.y * DISPLAYS_UNIT - w->scale_.y;
|
||||||
|
|
||||||
// remember the output monitor selected
|
// remember the output monitor selected
|
||||||
windows_[current_window_].monitor_ = monitor_iter->first;
|
windows_[current_window_].monitor_ = monitor_iter->first;
|
||||||
@@ -1033,6 +1181,9 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// request update
|
||||||
|
++windows_[current_window_].need_update_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update cursor
|
// update cursor
|
||||||
@@ -1121,7 +1272,7 @@ View::Cursor DisplaysView::grab (Source *, glm::vec2 from, glm::vec2 to, std::pa
|
|||||||
|
|
||||||
bool DisplaysView::doubleclic (glm::vec2 P)
|
bool DisplaysView::doubleclic (glm::vec2 P)
|
||||||
{
|
{
|
||||||
// TODO find which window?
|
// bring window forward
|
||||||
if ( pick(P).first != nullptr) {
|
if ( pick(P).first != nullptr) {
|
||||||
Rendering::manager().outputWindow(current_window_).show();
|
Rendering::manager().outputWindow(current_window_).show();
|
||||||
return true;
|
return true;
|
||||||
@@ -1130,58 +1281,82 @@ bool DisplaysView::doubleclic (glm::vec2 P)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_DURATION 1000.f
|
#define TIME_STEP 500
|
||||||
#define MIN_SPEED_D 0.1f
|
|
||||||
#define MAX_SPEED_D 2.f
|
|
||||||
|
|
||||||
void DisplaysView::arrow (glm::vec2 movement)
|
void DisplaysView::arrow (glm::vec2 movement)
|
||||||
{
|
{
|
||||||
static float _duration = 0.f;
|
static uint _time = 0;
|
||||||
|
static glm::vec2 _from(0.f);
|
||||||
|
static glm::vec2 _displacement(0.f);
|
||||||
|
|
||||||
// grab only works on current window if not fullscreen
|
// grab only works on current window if not fullscreen
|
||||||
if (current_window_ > -1 && !Settings::application.windows[current_window_+1].fullscreen) {
|
if (current_window_ > -1 && !Settings::application.windows[current_window_+1].fullscreen) {
|
||||||
|
|
||||||
// operate in pixel coordinates
|
// first time pressed: initialize and initiate
|
||||||
static glm::vec2 p;
|
|
||||||
|
|
||||||
// initiate movement (only once)
|
|
||||||
if (!current_action_ongoing_) {
|
if (!current_action_ongoing_) {
|
||||||
|
if (UserInterface::manager().altModifier() || Settings::application.mouse_pointer_lock)
|
||||||
|
MousePointer::manager().setActiveMode(Pointer::POINTER_GRID);
|
||||||
|
else
|
||||||
|
MousePointer::manager().setActiveMode(Pointer::POINTER_DEFAULT);
|
||||||
|
|
||||||
// initial position
|
// reset
|
||||||
p.x = (windows_[current_window_].root_->translation_.x - windows_[current_window_].root_->scale_.x) / DISPLAYS_UNIT;
|
_time = 0;
|
||||||
p.y = (windows_[current_window_].root_->translation_.y + windows_[current_window_].root_->scale_.y) / - DISPLAYS_UNIT;
|
_displacement = glm::vec2(0.f);
|
||||||
|
|
||||||
// initiate (terminated at key release)
|
// initiate view action and store status
|
||||||
current_action_ongoing_ = true;
|
initiate();
|
||||||
_duration = 0.f;
|
|
||||||
|
// get coordinates of window and set this as start of mouse position
|
||||||
|
_from = glm::vec2(
|
||||||
|
Rendering::manager().project(windows_[current_window_].root_->translation_,
|
||||||
|
scene.root()->transform_));
|
||||||
|
// Initiate mouse pointer action
|
||||||
|
MousePointer::manager().active()->initiate(_from);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add movement vector to position (pixel precision)
|
// if initialized
|
||||||
_duration += dt_;
|
if (current_action_ongoing_) {
|
||||||
const float speed = MIN_SPEED_D + (MAX_SPEED_D - MIN_SPEED_D) * glm::min(1.f,_duration / MAX_DURATION);
|
// move on first press, and then every TIME_STEP milisecond
|
||||||
p += movement * dt_ * speed; //* (dt_ * 0.5f);
|
if (_time < 1 || _time > TIME_STEP) {
|
||||||
|
_time = 0;
|
||||||
|
|
||||||
// discretized translation with ALT
|
// move by step size if grid is active
|
||||||
if (UserInterface::manager().altModifier()) {
|
if (MousePointer::manager().activeMode() == Pointer::POINTER_GRID) {
|
||||||
glm::vec2 q;
|
// calculate step size in monitor coordinates (simulate mouse movement)
|
||||||
q.x = ROUND(p.x, 0.05f); // 20 pix precision
|
glm::vec2 step = grid->step() * glm::vec2(gridroot_->scale_);
|
||||||
q.y = ROUND(p.y, 0.05f);
|
step = glm::vec2(Rendering::manager().project(glm::vec3(step.x, -step.y, 0.f),
|
||||||
// convert back to output-frame coordinates
|
scene.root()->transform_));
|
||||||
windows_[current_window_].root_->translation_.x = (q.x * DISPLAYS_UNIT) + windows_[current_window_].root_->scale_.x;
|
step -= glm::vec2(Rendering::manager().project(glm::vec3(0.f),
|
||||||
windows_[current_window_].root_->translation_.y = (q.y * - DISPLAYS_UNIT) - windows_[current_window_].root_->scale_.y;
|
scene.root()->transform_));
|
||||||
}
|
// multiply movement by step size
|
||||||
else
|
movement *= step;
|
||||||
{
|
}
|
||||||
// convert back to output-frame coordinates
|
|
||||||
windows_[current_window_].root_->translation_.x = (p.x * DISPLAYS_UNIT) + windows_[current_window_].root_->scale_.x;
|
|
||||||
windows_[current_window_].root_->translation_.y = (p.y * - DISPLAYS_UNIT) - windows_[current_window_].root_->scale_.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// increment displacement by movement
|
||||||
|
_displacement += movement;
|
||||||
|
|
||||||
|
// update mouse pointer action
|
||||||
|
MousePointer::manager().active()->update(_from + _displacement, dt_ / 1000.f);
|
||||||
|
|
||||||
|
// simulate mouse grab
|
||||||
|
grab(nullptr, _from, MousePointer::manager().active()->target(),
|
||||||
|
std::make_pair(windows_[current_window_].surface_, glm::vec2(0.f) ) );
|
||||||
|
}
|
||||||
|
// draw mouse pointer effect
|
||||||
|
MousePointer::manager().active()->draw();
|
||||||
|
// increment time counter
|
||||||
|
_time += static_cast<uint>(dt_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// reset
|
||||||
|
_from = glm::vec2(0.f);
|
||||||
|
_displacement = glm::vec2(0.f);
|
||||||
|
terminate(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool WindowPreview::hasNode::operator()(const WindowPreview &elem) const
|
bool WindowPreview::hasNode::operator()(const WindowPreview &elem) const
|
||||||
{
|
{
|
||||||
if (_n)
|
if (_n)
|
||||||
|
|||||||
@@ -9,19 +9,20 @@ struct WindowPreview
|
|||||||
class FrameBuffer *renderbuffer_;
|
class FrameBuffer *renderbuffer_;
|
||||||
class ImageFilteringShader *shader_;
|
class ImageFilteringShader *shader_;
|
||||||
class FrameBufferSurface *surface_;
|
class FrameBufferSurface *surface_;
|
||||||
Surface *output_render_;
|
class MeshSurface *output_render_;
|
||||||
Group *root_;
|
Group *root_;
|
||||||
Group *output_group_;
|
Group *output_group_;
|
||||||
Frame *output_frame_;
|
class LineLoop *output_lines_;
|
||||||
Handles *output_handles_;
|
Handles *output_handles_[4];
|
||||||
Switch *overlays_;
|
Switch *overlays_;
|
||||||
Switch *mode_;
|
Switch *mode_;
|
||||||
Handles *handles_;
|
Handles *resize_;
|
||||||
Handles *menu_;
|
Handles *menu_;
|
||||||
Handles *icon_;
|
Handles *icon_;
|
||||||
Surface *title_;
|
Surface *title_;
|
||||||
Symbol *fullscreen_;
|
Symbol *fullscreen_;
|
||||||
std::string monitor_;
|
std::string monitor_;
|
||||||
|
int need_update_;
|
||||||
|
|
||||||
WindowPreview() {
|
WindowPreview() {
|
||||||
renderbuffer_ = nullptr;
|
renderbuffer_ = nullptr;
|
||||||
@@ -30,15 +31,19 @@ struct WindowPreview
|
|||||||
output_render_ = nullptr;
|
output_render_ = nullptr;
|
||||||
root_ = nullptr;
|
root_ = nullptr;
|
||||||
output_group_ = nullptr;
|
output_group_ = nullptr;
|
||||||
output_handles_ = nullptr;
|
output_handles_[0] = nullptr;
|
||||||
|
output_handles_[1] = nullptr;
|
||||||
|
output_handles_[2] = nullptr;
|
||||||
|
output_handles_[3] = nullptr;
|
||||||
overlays_ = nullptr;
|
overlays_ = nullptr;
|
||||||
mode_ = nullptr;
|
mode_ = nullptr;
|
||||||
handles_ = nullptr;
|
resize_ = nullptr;
|
||||||
menu_ = nullptr;
|
menu_ = nullptr;
|
||||||
icon_ = nullptr;
|
icon_ = nullptr;
|
||||||
title_ = nullptr;
|
title_ = nullptr;
|
||||||
fullscreen_ = nullptr;
|
fullscreen_ = nullptr;
|
||||||
monitor_ = "";
|
monitor_ = "";
|
||||||
|
need_update_ = 2;
|
||||||
}
|
}
|
||||||
~WindowPreview();
|
~WindowPreview();
|
||||||
|
|
||||||
@@ -89,8 +94,8 @@ private:
|
|||||||
Group *current_output_status_;
|
Group *current_output_status_;
|
||||||
bool show_window_menu_;
|
bool show_window_menu_;
|
||||||
|
|
||||||
|
Group *gridroot_;
|
||||||
// bool get_UV_window_render_from_pick(const glm::vec3 &pos, glm::vec2 *uv);
|
void adaptGridToWindow(int w = -1);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public:
|
|||||||
Surface(Shader *s = new ImageShader);
|
Surface(Shader *s = new ImageShader);
|
||||||
virtual ~Surface();
|
virtual ~Surface();
|
||||||
|
|
||||||
void init () override;
|
virtual void init () override;
|
||||||
void draw (glm::mat4 modelview, glm::mat4 projection) override;
|
void draw (glm::mat4 modelview, glm::mat4 projection) override;
|
||||||
void accept (Visitor& v) override;
|
void accept (Visitor& v) override;
|
||||||
|
|
||||||
@@ -36,7 +36,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
uint textureindex_;
|
uint textureindex_;
|
||||||
bool mirror_;
|
bool mirror_;
|
||||||
void generate_mesh(size_t w, size_t h);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MeshSurface : public Surface {
|
class MeshSurface : public Surface {
|
||||||
@@ -44,7 +43,7 @@ class MeshSurface : public Surface {
|
|||||||
public:
|
public:
|
||||||
MeshSurface(Shader *s = new ImageShader);
|
MeshSurface(Shader *s = new ImageShader);
|
||||||
|
|
||||||
void init () override;
|
virtual void init () override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void generate_mesh(size_t w, size_t h);
|
void generate_mesh(size_t w, size_t h);
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
#include "UserInterfaceManager.h"
|
#include "UserInterfaceManager.h"
|
||||||
#include "ControlManager.h"
|
#include "ControlManager.h"
|
||||||
#include "ImageFilter.h"
|
#include "ImageFilter.h"
|
||||||
|
#include "Primitives.h"
|
||||||
|
|
||||||
#include "RenderingManager.h"
|
#include "RenderingManager.h"
|
||||||
|
|
||||||
@@ -265,6 +266,10 @@ GLFWmonitor *Rendering::monitorAt(int x, int y)
|
|||||||
return mo;
|
return mo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Rendering::monitorNameAt(int x, int y)
|
||||||
|
{
|
||||||
|
return glfwGetMonitorName(monitorAt(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
GLFWmonitor *Rendering::monitorNamed(const std::string &name)
|
GLFWmonitor *Rendering::monitorNamed(const std::string &name)
|
||||||
{
|
{
|
||||||
@@ -696,24 +701,18 @@ bool Rendering::shouldHaveEnoughMemory(glm::vec3 resolution, int flags)
|
|||||||
|
|
||||||
|
|
||||||
// custom surface with a new VAO
|
// custom surface with a new VAO
|
||||||
class WindowSurface : public Primitive {
|
class WindowSurface : public MeshSurface
|
||||||
|
|
||||||
public:
|
|
||||||
WindowSurface(Shader *s = new ImageShader);
|
|
||||||
};
|
|
||||||
|
|
||||||
WindowSurface::WindowSurface(Shader *s) : Primitive(s)
|
|
||||||
{
|
{
|
||||||
points_ = std::vector<glm::vec3> { glm::vec3( -1.f, -1.f, 0.f ), glm::vec3( -1.f, 1.f, 0.f ),
|
public:
|
||||||
glm::vec3( 1.f, -1.f, 0.f ), glm::vec3( 1.f, 1.f, 0.f ) };
|
WindowSurface(Shader *s = new ImageShader)
|
||||||
colors_ = std::vector<glm::vec4> { glm::vec4( 1.f, 1.f, 1.f , 1.f ), glm::vec4( 1.f, 1.f, 1.f, 1.f ),
|
: MeshSurface(s)
|
||||||
glm::vec4( 1.f, 1.f, 1.f, 1.f ), glm::vec4( 1.f, 1.f, 1.f, 1.f ) };
|
{}
|
||||||
texCoords_ = std::vector<glm::vec2> { glm::vec2( 0.f, 1.f ), glm::vec2( 0.f, 0.f ),
|
void init () override
|
||||||
glm::vec2( 1.f, 1.f ), glm::vec2( 1.f, 0.f ) };
|
{
|
||||||
indices_ = std::vector<uint> { 0, 1, 2, 3 };
|
generate_mesh(32, 32);
|
||||||
drawMode_ = GL_TRIANGLE_STRIP;
|
Primitive::init();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
RenderingWindow::RenderingWindow() : window_(NULL), master_(NULL),
|
RenderingWindow::RenderingWindow() : window_(NULL), master_(NULL),
|
||||||
index_(-1), dpi_scale_(1.f), textureid_(0), fbo_(0), surface_(nullptr), request_change_fullscreen_(false)
|
index_(-1), dpi_scale_(1.f), textureid_(0), fbo_(0), surface_(nullptr), request_change_fullscreen_(false)
|
||||||
@@ -1177,12 +1176,20 @@ bool RenderingWindow::draw(FrameBuffer *fb)
|
|||||||
shader_->uniforms_["Green"] = Settings::application.windows[index_].whitebalance.y;
|
shader_->uniforms_["Green"] = Settings::application.windows[index_].whitebalance.y;
|
||||||
shader_->uniforms_["Blue"] = Settings::application.windows[index_].whitebalance.z;
|
shader_->uniforms_["Blue"] = Settings::application.windows[index_].whitebalance.z;
|
||||||
shader_->uniforms_["Temperature"] = Settings::application.windows[index_].whitebalance.w;
|
shader_->uniforms_["Temperature"] = Settings::application.windows[index_].whitebalance.w;
|
||||||
|
|
||||||
|
if (Settings::application.windows[index_].custom)
|
||||||
|
shader_->iNodes = Settings::application.windows[index_].nodes;
|
||||||
|
else
|
||||||
|
shader_->iNodes = glm::zero<glm::mat4>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display option: scaled or corrected aspect ratio
|
// Display option: scaled or corrected aspect ratio
|
||||||
if (Settings::application.windows[index_].scaled) {
|
if (Settings::application.windows[index_].custom) {
|
||||||
surface_->scale_ = Settings::application.windows[index_].scale;
|
// surface_->scale_ = Settings::application.windows[index_].scale;
|
||||||
surface_->translation_ = Settings::application.windows[index_].translation;
|
// surface_->translation_ = Settings::application.windows[index_].translation;
|
||||||
|
|
||||||
|
surface_->scale_ = glm::vec3(1.f);
|
||||||
|
surface_->translation_ = glm::vec3(0.f);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// calculate scaling factor of frame buffer inside window
|
// calculate scaling factor of frame buffer inside window
|
||||||
@@ -1196,7 +1203,7 @@ bool RenderingWindow::draw(FrameBuffer *fb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Display option: draw calibration pattern
|
// Display option: draw calibration pattern
|
||||||
if ( Settings::application.windows[index_].show_pattern) {
|
if (Settings::application.windows[index_].show_pattern) {
|
||||||
// (re) create pattern at frame buffer resolution
|
// (re) create pattern at frame buffer resolution
|
||||||
if ( pattern_->width() != fb->width() || pattern_->height() != fb->height()) {
|
if ( pattern_->width() != fb->width() || pattern_->height() != fb->height()) {
|
||||||
if (GstToolkit::has_feature("frei0r-src-test-pat-b") )
|
if (GstToolkit::has_feature("frei0r-src-test-pat-b") )
|
||||||
@@ -1215,14 +1222,13 @@ bool RenderingWindow::draw(FrameBuffer *fb)
|
|||||||
textureid_ = fb->texture();
|
textureid_ = fb->texture();
|
||||||
|
|
||||||
// actual render of the textured surface
|
// actual render of the textured surface
|
||||||
glBindTexture(GL_TEXTURE_2D, textureid_);
|
|
||||||
static glm::mat4 projection = glm::ortho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f);
|
static glm::mat4 projection = glm::ortho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f);
|
||||||
|
surface_->setTextureIndex(textureid_);
|
||||||
surface_->update(0.f);
|
surface_->update(0.f);
|
||||||
surface_->draw(glm::identity<glm::mat4>(), projection);
|
surface_->draw(glm::identity<glm::mat4>(), projection);
|
||||||
|
|
||||||
// done drawing (unload shader from this glcontext)
|
// done drawing (unload shader from this glcontext)
|
||||||
ShadingProgram::enduse();
|
ShadingProgram::enduse();
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore attribs
|
// restore attribs
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ public:
|
|||||||
inline std::map<std::string, glm::ivec4> monitors() { return monitors_geometry_; }
|
inline std::map<std::string, glm::ivec4> monitors() { return monitors_geometry_; }
|
||||||
// get which monitor contains this point
|
// get which monitor contains this point
|
||||||
GLFWmonitor *monitorAt(int x, int y);
|
GLFWmonitor *monitorAt(int x, int y);
|
||||||
|
std::string monitorNameAt(int x, int y);
|
||||||
// get which monitor has this name
|
// get which monitor has this name
|
||||||
GLFWmonitor *monitorNamed(const std::string &name);
|
GLFWmonitor *monitorNamed(const std::string &name);
|
||||||
|
|
||||||
|
|||||||
@@ -109,17 +109,14 @@ void Settings::Save(uint64_t runtime)
|
|||||||
window->SetAttribute("w", w.w);
|
window->SetAttribute("w", w.w);
|
||||||
window->SetAttribute("h", w.h);
|
window->SetAttribute("h", w.h);
|
||||||
window->SetAttribute("f", w.fullscreen);
|
window->SetAttribute("f", w.fullscreen);
|
||||||
window->SetAttribute("s", w.scaled);
|
window->SetAttribute("s", w.custom);
|
||||||
window->SetAttribute("d", w.decorated);
|
window->SetAttribute("d", w.decorated);
|
||||||
window->SetAttribute("m", w.monitor.c_str());
|
window->SetAttribute("m", w.monitor.c_str());
|
||||||
XMLElement *tmp = xmlDoc.NewElement("whitebalance");
|
XMLElement *tmp = xmlDoc.NewElement("whitebalance");
|
||||||
tmp->InsertEndChild( XMLElementFromGLM(&xmlDoc, w.whitebalance) );
|
tmp->InsertEndChild( XMLElementFromGLM(&xmlDoc, w.whitebalance) );
|
||||||
window->InsertEndChild( tmp );
|
window->InsertEndChild( tmp );
|
||||||
tmp = xmlDoc.NewElement("scale");
|
tmp = xmlDoc.NewElement("nodes");
|
||||||
tmp->InsertEndChild( XMLElementFromGLM(&xmlDoc, w.scale) );
|
tmp->InsertEndChild( XMLElementFromGLM(&xmlDoc, w.nodes) );
|
||||||
window->InsertEndChild( tmp );
|
|
||||||
tmp = xmlDoc.NewElement("translation");
|
|
||||||
tmp->InsertEndChild( XMLElementFromGLM(&xmlDoc, w.translation) );
|
|
||||||
window->InsertEndChild( tmp );
|
window->InsertEndChild( tmp );
|
||||||
windowsNode->InsertEndChild(window);
|
windowsNode->InsertEndChild(window);
|
||||||
}
|
}
|
||||||
@@ -550,7 +547,7 @@ void Settings::Load()
|
|||||||
windowNode->QueryIntAttribute("w", &w.w);
|
windowNode->QueryIntAttribute("w", &w.w);
|
||||||
windowNode->QueryIntAttribute("h", &w.h);
|
windowNode->QueryIntAttribute("h", &w.h);
|
||||||
windowNode->QueryBoolAttribute("f", &w.fullscreen);
|
windowNode->QueryBoolAttribute("f", &w.fullscreen);
|
||||||
windowNode->QueryBoolAttribute("s", &w.scaled);
|
windowNode->QueryBoolAttribute("s", &w.custom);
|
||||||
windowNode->QueryBoolAttribute("d", &w.decorated);
|
windowNode->QueryBoolAttribute("d", &w.decorated);
|
||||||
const char *text = windowNode->Attribute("m");
|
const char *text = windowNode->Attribute("m");
|
||||||
if (text)
|
if (text)
|
||||||
@@ -562,16 +559,36 @@ void Settings::Load()
|
|||||||
w.name = "Output " + std::to_string(i) + " - " APP_NAME;
|
w.name = "Output " + std::to_string(i) + " - " APP_NAME;
|
||||||
else
|
else
|
||||||
w.name = APP_TITLE;
|
w.name = APP_TITLE;
|
||||||
|
// vec4 values for white balance correction
|
||||||
XMLElement *tmp = windowNode->FirstChildElement("whitebalance");
|
XMLElement *tmp = windowNode->FirstChildElement("whitebalance");
|
||||||
if (tmp)
|
if (tmp)
|
||||||
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("vec4"), w.whitebalance);
|
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("vec4"), w.whitebalance);
|
||||||
tmp = windowNode->FirstChildElement("scale");
|
// mat4 values for custom fit distortion
|
||||||
|
w.nodes = glm::zero<glm::mat4>();
|
||||||
|
tmp = windowNode->FirstChildElement("nodes");
|
||||||
if (tmp)
|
if (tmp)
|
||||||
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("vec3"), w.scale);
|
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("mat4"), w.nodes);
|
||||||
tmp = windowNode->FirstChildElement("translation");
|
else {
|
||||||
if (tmp)
|
// backward compatibility
|
||||||
tinyxml2::XMLElementToGLM( tmp->FirstChildElement("vec3"), w.translation);
|
glm::vec3 scale, translation;
|
||||||
|
tmp = windowNode->FirstChildElement("scale");
|
||||||
|
if (tmp) {
|
||||||
|
tinyxml2::XMLElementToGLM(tmp->FirstChildElement("vec3"), scale);
|
||||||
|
tmp = windowNode->FirstChildElement("translation");
|
||||||
|
if (tmp) {
|
||||||
|
tinyxml2::XMLElementToGLM(tmp->FirstChildElement("vec3"), translation);
|
||||||
|
// calculate nodes with scale and translation
|
||||||
|
w.nodes[0].x = 1.f - ( 1.f * scale.x - translation.x );
|
||||||
|
w.nodes[0].y = 1.f - ( 1.f * scale.y - translation.y );
|
||||||
|
w.nodes[1].x = 1.f - ( 1.f * scale.x - translation.x );
|
||||||
|
w.nodes[1].y = -1.f - (-1.f * scale.y - translation.y );
|
||||||
|
w.nodes[2].x = -1.f - (-1.f * scale.x - translation.x );
|
||||||
|
w.nodes[2].y = 1.f - ( 1.f * scale.y - translation.y );
|
||||||
|
w.nodes[3].x = -1.f - (-1.f * scale.x - translation.x );
|
||||||
|
w.nodes[3].y = -1.f - (-1.f * scale.y - translation.y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
application.windows[i] = w;
|
application.windows[i] = w;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
@@ -66,18 +67,17 @@ struct WindowConfig
|
|||||||
std::string name;
|
std::string name;
|
||||||
int x,y,w,h;
|
int x,y,w,h;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool scaled;
|
bool custom;
|
||||||
bool decorated;
|
bool decorated;
|
||||||
std::string monitor;
|
std::string monitor;
|
||||||
bool show_pattern;
|
bool show_pattern;
|
||||||
glm::vec4 whitebalance;
|
glm::vec4 whitebalance;
|
||||||
glm::vec3 scale;
|
glm::mat4 nodes;
|
||||||
glm::vec3 translation;
|
|
||||||
|
|
||||||
WindowConfig() : name(APP_TITLE), x(15), y(15), w(1280), h(720),
|
WindowConfig() : name(APP_TITLE), x(15), y(15), w(1280), h(720),
|
||||||
fullscreen(false), scaled(false), decorated(true),
|
fullscreen(false), custom(false), decorated(true),
|
||||||
monitor(""), show_pattern(false), whitebalance(glm::vec4(1.f, 1.f, 1.f, 0.5f)),
|
monitor(""), show_pattern(false), whitebalance(glm::vec4(1.f, 1.f, 1.f, 0.5f)),
|
||||||
scale(glm::vec3(1.f)), translation(glm::vec3(0.f))
|
nodes(glm::zero<glm::mat4>())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4166,7 +4166,7 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size)
|
|||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImVec2 top = ImGui::GetCursorPos();
|
ImVec2 top = ImGui::GetCursorPos();
|
||||||
bool enabled = Settings::application.current_view < View::TRANSITION;
|
bool enabled = Settings::application.current_view != View::TRANSITION;
|
||||||
///
|
///
|
||||||
/// interactive button of the given size: show menu if clic or mouse over
|
/// interactive button of the given size: show menu if clic or mouse over
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user