Merge branch 'issue_70' of https://github.com/ThomasWilshaw/olive into ThomasWilshaw-issue_70
# Conflicts: # app/widget/viewer/viewerwindow.cpp
This commit is contained in:
@@ -75,7 +75,8 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
connect(display_widget_, &ViewerDisplayWidget::CursorColor, this, &ViewerWidget::CursorColor);
|
||||
connect(display_widget_, &ViewerDisplayWidget::ColorProcessorChanged, this, &ViewerWidget::ColorProcessorChanged);
|
||||
connect(display_widget_, &ViewerDisplayWidget::ColorManagerChanged, this, &ViewerWidget::ColorManagerChanged);
|
||||
connect(sizer_, &ViewerSizer::RequestMatrix, display_widget_, &ViewerDisplayWidget::SetMatrix);
|
||||
connect(sizer_, &ViewerSizer::RequestMatrix, display_widget_, &ViewerDisplayWidget::SetMatrixZoom);
|
||||
connect(sizer_, &ViewerSizer::IsZoomed, display_widget_, &ViewerDisplayWidget::IsZoomed);
|
||||
sizer_->SetWidget(display_widget_);
|
||||
|
||||
// Create waveform view when audio is connected and video isn't
|
||||
@@ -289,9 +290,9 @@ void ViewerWidget::SetColorMenuEnabled(bool enabled)
|
||||
|
||||
void ViewerWidget::SetMatrix(const QMatrix4x4 &mat)
|
||||
{
|
||||
display_widget_->SetMatrix(mat);
|
||||
display_widget_->SetMatrixZoom(mat);
|
||||
foreach (ViewerWindow* vw, windows_) {
|
||||
vw->display_widget()->SetMatrix(mat);
|
||||
vw->display_widget()->SetMatrixZoom(mat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "render/backend/opengl/openglrenderfunctions.h"
|
||||
#include "render/backend/opengl/openglshader.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "core.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -44,8 +45,13 @@ ViewerDisplayWidget::ViewerDisplayWidget(QWidget *parent) :
|
||||
gizmos_(nullptr),
|
||||
gizmo_click_(false),
|
||||
last_loaded_buffer_(nullptr),
|
||||
zoomed_(false),
|
||||
hand_tool_clicked_(false),
|
||||
deinterlace_(false)
|
||||
{
|
||||
connect(Core::instance(), &Core::ToolChanged, this, &ViewerDisplayWidget::ToolChanged);
|
||||
// Initilises hand_tool_ based on currently selected tool.
|
||||
ToolChanged(Core::instance()->tool());
|
||||
}
|
||||
|
||||
ViewerDisplayWidget::~ViewerDisplayWidget()
|
||||
@@ -53,12 +59,55 @@ ViewerDisplayWidget::~ViewerDisplayWidget()
|
||||
ContextCleanup();
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::SetMatrix(const QMatrix4x4 &mat)
|
||||
void ViewerDisplayWidget::SetMatrixTranslate(const QMatrix4x4 &mat)
|
||||
{
|
||||
matrix_ = mat;
|
||||
translate_matrix_ = mat;
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::SetMatrixZoom(const QMatrix4x4 &mat)
|
||||
{
|
||||
scale_matrix_ = mat;
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::IsZoomed(bool flag)
|
||||
{
|
||||
zoomed_ = flag;
|
||||
// If the image is smaller than the container widget we reset the translation.
|
||||
if (!flag) {
|
||||
QMatrix4x4 mat; // defaults to identity matrix.
|
||||
SetMatrixTranslate(mat);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::ToolChanged(Tool::Item tool)
|
||||
{
|
||||
if (tool == Tool::kHand) {
|
||||
hand_tool_ = true;
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
} else {
|
||||
hand_tool_ = false;
|
||||
unsetCursor();
|
||||
}
|
||||
}
|
||||
|
||||
QMatrix4x4 ViewerDisplayWidget::GetCompleteMatrix()
|
||||
{
|
||||
QMatrix4x4 mat;
|
||||
// Images is scaled, then translated.
|
||||
return translate_matrix_ * scale_matrix_ * mat;
|
||||
}
|
||||
|
||||
QMatrix4x4 ViewerDisplayWidget::GetCompleteMatrixFlippedYTranslation() {
|
||||
QMatrix4x4 mat;
|
||||
// Image is scaled, then translated.
|
||||
mat = translate_matrix_ * scale_matrix_ * mat;
|
||||
// Y translation is flipped for OpenGL usage
|
||||
*(mat.data() + 13) = *(mat.data() + 13) * -1.0f;
|
||||
return mat;
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::SetSignalCursorColorEnabled(bool e)
|
||||
{
|
||||
signal_cursor_color_ = e;
|
||||
@@ -139,15 +188,61 @@ FramePtr ViewerDisplayWidget::last_loaded_buffer() const
|
||||
return last_loaded_buffer_;
|
||||
}
|
||||
|
||||
QTransform ViewerDisplayWidget::GenerateWorldTransform()
|
||||
{
|
||||
/*
|
||||
* Get matrix elements (roughly) as below in column major order
|
||||
*
|
||||
* | Sx 0 0 Tx |
|
||||
* | 0 Sy 0 Ty |
|
||||
* | 0 0 Sz Tz |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
float *data = GetCompleteMatrix().data();
|
||||
QTransform world;
|
||||
// Move corner of canvas to correct point
|
||||
world.translate(width() * 0.5 - width() * *(data)*0.5, height() * 0.5 - height() * *(data + 5) * 0.5);
|
||||
// Scale
|
||||
world.scale(*(data), *(data + 5));
|
||||
// Translate for mouse movement
|
||||
world.translate(*(data + 12) * width() * 0.5 / *(data), *(data + 13) * height() * 0.5 / *(data + 5));
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
QPoint ViewerDisplayWidget::TransformViewerSpaceToBufferSpace(QPoint pos)
|
||||
{
|
||||
/*
|
||||
* Inversion will only fail if the viewer has been scaled by 0 in any direction
|
||||
* which I think should never happen.
|
||||
*/
|
||||
return pos * GenerateWorldTransform().inverted();
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (gizmos_
|
||||
&& gizmos_->GizmoPress(gizmo_db_, event->pos(), QVector2D(GetTexturePosition(size())), size())) {
|
||||
if (event->button() == Qt::LeftButton && gizmos_
|
||||
&& gizmos_->GizmoPress(gizmo_db_, TransformViewerSpaceToBufferSpace(event->pos()),
|
||||
QVector2D(GetTexturePosition(size())), size())) {
|
||||
gizmo_click_ = true;
|
||||
gizmo_drag_time_ = GetGizmoTime();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset translation.
|
||||
if (event->button() == Qt::MiddleButton && event->modifiers() & Qt::ControlModifier) {
|
||||
QMatrix4x4 mat; // Identity matrix
|
||||
SetMatrixTranslate(mat);
|
||||
return;
|
||||
}
|
||||
|
||||
// If translation is enabled get current position in preperation for move event.
|
||||
if ((event->button() == Qt::MiddleButton || hand_tool_) && zoomed_) {
|
||||
position_ = event->pos();
|
||||
if (hand_tool_) hand_tool_clicked_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
QOpenGLWidget::mousePressEvent(event);
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
@@ -157,8 +252,28 @@ void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
// Only allow translation if the image is larger than the container widget
|
||||
if ((event->buttons() & Qt::MiddleButton || hand_tool_clicked_) && zoomed_) {
|
||||
QPointF delta = event->pos() - position_;
|
||||
// Scale delta to widget size
|
||||
delta.setX(2 * delta.x() / width());
|
||||
delta.setY(2 * delta.y() / height());
|
||||
|
||||
QMatrix4x4 mat;
|
||||
mat = GetMatrixTranslate();
|
||||
|
||||
mat.translate(delta.x(), delta.y());
|
||||
SetMatrixTranslate(mat);
|
||||
|
||||
// Get new start position
|
||||
position_ = event-> pos();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gizmo_click_) {
|
||||
gizmos_->GizmoMove(event->pos(), QVector2D(GetTexturePosition(size())), gizmo_drag_time_);
|
||||
gizmos_->GizmoMove(TransformViewerSpaceToBufferSpace(event->pos()),
|
||||
QVector2D(GetTexturePosition(size())), gizmo_drag_time_);
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,7 +287,7 @@ void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
static_cast<float>(event->y()) / static_cast<float>(height()) * 2.0f - 1.0f,
|
||||
0);
|
||||
|
||||
pixel_pos = pixel_pos * matrix_.inverted();
|
||||
pixel_pos = GetCompleteMatrix().inverted() * pixel_pos;
|
||||
|
||||
int frame_x = qRound((pixel_pos.x() + 1.0f) * 0.5f * last_loaded_buffer_->width());
|
||||
int frame_y = qRound((pixel_pos.y() + 1.0f) * 0.5f * last_loaded_buffer_->height());
|
||||
@@ -194,9 +309,16 @@ void ViewerDisplayWidget::mouseReleaseEvent(QMouseEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
hand_tool_clicked_ = false;
|
||||
|
||||
QOpenGLWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
QMatrix4x4 ViewerDisplayWidget::GetMatrixTranslate()
|
||||
{
|
||||
return translate_matrix_;
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::initializeGL()
|
||||
{
|
||||
ManagedDisplayWidget::initializeGL();
|
||||
@@ -226,13 +348,15 @@ void ViewerDisplayWidget::paintGL()
|
||||
color_service()->pipeline()->release();
|
||||
|
||||
// Blit using the color service
|
||||
color_service()->ProcessOpenGL(true, matrix_);
|
||||
color_service()->ProcessOpenGL(true, GetCompleteMatrixFlippedYTranslation());
|
||||
|
||||
// Release retrieved texture
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
}
|
||||
|
||||
QTransform world = GenerateWorldTransform();
|
||||
|
||||
// Draw gizmos if we have any
|
||||
if (gizmos_) {
|
||||
GizmoTraverser gt(QSize(gizmo_params_.width(), gizmo_params_.height()));
|
||||
@@ -242,12 +366,15 @@ void ViewerDisplayWidget::paintGL()
|
||||
gizmo_db_ = gt.GenerateDatabase(gizmos_, TimeRange(node_time, node_time));
|
||||
|
||||
QPainter p(this);
|
||||
p.setWorldTransform(world);
|
||||
gizmos_->DrawGizmos(gizmo_db_, &p, QVector2D(GetTexturePosition(size())), size());
|
||||
}
|
||||
|
||||
// Draw action/title safe areas
|
||||
if (safe_margin_.is_enabled()) {
|
||||
QPainter p(this);
|
||||
p.setWorldTransform(world);
|
||||
|
||||
p.setPen(Qt::lightGray);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "render/backend/opengl/opengltexture.h"
|
||||
#include "render/color.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "tool/tool.h"
|
||||
#include "viewersafemargininfo.h"
|
||||
#include "widget/manageddisplay/manageddisplay.h"
|
||||
#include "widget/timetarget/timetarget.h"
|
||||
@@ -66,7 +67,22 @@ public:
|
||||
|
||||
virtual ~ViewerDisplayWidget() override;
|
||||
|
||||
const QMatrix4x4& GetMatrix();
|
||||
/**
|
||||
* @brief Return the translation only matrix.
|
||||
*/
|
||||
QMatrix4x4 GetMatrixTranslate();
|
||||
|
||||
/**
|
||||
* @brief Return the complete translation and scale matrix
|
||||
* This must be used if you want the entire transformation pipeline (scale and translate).
|
||||
*/
|
||||
QMatrix4x4 GetCompleteMatrix();
|
||||
|
||||
/**
|
||||
* @brief Return the complete translation and scale matrix but with the Y translation flipped
|
||||
* as OpenGL stores textures "upside down".
|
||||
*/
|
||||
QMatrix4x4 GetCompleteMatrixFlippedYTranslation();
|
||||
|
||||
const ViewerSafeMarginInfo& GetSafeMargin() const;
|
||||
void SetSafeMargins(const ViewerSafeMarginInfo& safe_margin);
|
||||
@@ -77,6 +93,18 @@ public:
|
||||
|
||||
FramePtr last_loaded_buffer() const;
|
||||
|
||||
/**
|
||||
* @brief Return a QTransform that contains all the scale and translation data (inc. mouse drags)
|
||||
* that can be used to set the world transform for a QPainter.
|
||||
*/
|
||||
QTransform GenerateWorldTransform();
|
||||
|
||||
/**
|
||||
* @brief Transform a point from viewer space to the buffer space.
|
||||
* Multiplies by the inverted transform matrix to undo the scaling and translation.
|
||||
*/
|
||||
QPoint TransformViewerSpaceToBufferSpace(QPoint pos);
|
||||
|
||||
bool IsDeinterlacing() const
|
||||
{
|
||||
return deinterlace_;
|
||||
@@ -88,7 +116,12 @@ public slots:
|
||||
*
|
||||
* Set this if you want the drawing to pass through some sort of transform (most of the time you won't want this).
|
||||
*/
|
||||
void SetMatrix(const QMatrix4x4& mat);
|
||||
void SetMatrixTranslate(const QMatrix4x4& mat);
|
||||
|
||||
/**
|
||||
* @brief Set the scale matrix.
|
||||
*/
|
||||
void SetMatrixZoom(const QMatrix4x4& mat);
|
||||
|
||||
/**
|
||||
* @brief Enables or disables whether this color at the cursor should be emitted
|
||||
@@ -107,6 +140,19 @@ public slots:
|
||||
*/
|
||||
void SetImage(FramePtr in_buffer);
|
||||
|
||||
/**
|
||||
* @brief Set zoomed_ flag if the viewersizer has zoomed the image to be larger than the widget.
|
||||
*
|
||||
* If the image is smaller than the widget the translation is reset so the image is centered.
|
||||
*/
|
||||
void IsZoomed(bool flag);
|
||||
|
||||
/**
|
||||
* @brief Changes the pointer type if the tool is changed to the hand tool. Otherwise resets the pointer to it's
|
||||
* normal type.
|
||||
*/
|
||||
void ToolChanged(Tool::Item tool);
|
||||
|
||||
/**
|
||||
* @brief Enables/disables a basic deinterlace on the viewer
|
||||
*/
|
||||
@@ -166,9 +212,16 @@ private:
|
||||
OpenGLTexture texture_;
|
||||
|
||||
/**
|
||||
* @brief Drawing matrix (defaults to identity)
|
||||
* @brief Translation only matrix (defaults to identity).
|
||||
*/
|
||||
QMatrix4x4 matrix_;
|
||||
QMatrix4x4 translate_matrix_;
|
||||
|
||||
/**
|
||||
* @breif Scale only matrix.
|
||||
*/
|
||||
QMatrix4x4 scale_matrix_;
|
||||
|
||||
|
||||
|
||||
bool signal_cursor_color_;
|
||||
|
||||
@@ -184,6 +237,26 @@ private:
|
||||
|
||||
FramePtr last_loaded_buffer_;
|
||||
|
||||
/**
|
||||
* @brief Tells us if the image is zoomed in to be larger than the container widget.
|
||||
*/
|
||||
bool zoomed_;
|
||||
|
||||
/**
|
||||
* @brief Position of mouse to calculate delta from.
|
||||
*/
|
||||
QPoint position_;
|
||||
|
||||
/**
|
||||
* @brief Set if the hand tool is selected.
|
||||
*/
|
||||
bool hand_tool_;
|
||||
|
||||
/**
|
||||
* @brief Set if the hand tool is selected and viewer is clicked.
|
||||
*/
|
||||
bool hand_tool_clicked_;
|
||||
|
||||
bool deinterlace_;
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -110,11 +110,15 @@ void ViewerSizer::UpdateSize()
|
||||
// This container is taller than the image, scale by width
|
||||
child_size = QSize(width(), qRound(child_size.width() / sequence_aspect_ratio));
|
||||
}
|
||||
emit IsZoomed(false);
|
||||
|
||||
} else {
|
||||
|
||||
float x_scale = 1.0f;
|
||||
float y_scale = 1.0f;
|
||||
// Translation is only active if the image is bigger then the widget
|
||||
// See ViewerDisplayWidget::SetZoomData
|
||||
bool zoomed_in = false;
|
||||
|
||||
int zoomed_width = qRound(width_ * static_cast<double>(zoom_) * 0.01);
|
||||
int zoomed_height = qRound(height_ * static_cast<double>(zoom_) * 0.01);
|
||||
@@ -122,18 +126,20 @@ void ViewerSizer::UpdateSize()
|
||||
if (zoomed_width > width()) {
|
||||
x_scale = static_cast<double>(zoomed_width) / static_cast<double>(width());
|
||||
zoomed_width = width();
|
||||
zoomed_in = true;
|
||||
}
|
||||
|
||||
if (zoomed_height > height()) {
|
||||
y_scale = static_cast<double>(zoomed_height) / static_cast<double>(height());
|
||||
zoomed_height = height();
|
||||
zoomed_in = true;
|
||||
}
|
||||
|
||||
// Rather than make a huge surface, we still crop at our width/height and then signal a matrix
|
||||
child_matrix.scale(x_scale, y_scale, 1.0F);
|
||||
|
||||
child_size = QSize(zoomed_width, zoomed_height);
|
||||
|
||||
emit IsZoomed(zoomed_in);
|
||||
}
|
||||
|
||||
widget_->resize(child_size);
|
||||
|
||||
@@ -72,6 +72,11 @@ public:
|
||||
signals:
|
||||
void RequestMatrix(const QMatrix4x4& matrix);
|
||||
|
||||
/**
|
||||
* @brief Tells the viewerdisplay widget if the image is enlarged to be bigger than the widget or not.
|
||||
*/
|
||||
void IsZoomed(bool flag);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Listen for resize events to ensure the child widget remains correctly sized
|
||||
|
||||
@@ -137,7 +137,7 @@ void ViewerWindow::UpdateMatrix()
|
||||
mat.scale(1.0f, window_ar / image_ar, 1.0f);
|
||||
}
|
||||
|
||||
display_widget_->SetMatrix(mat);
|
||||
display_widget_->SetMatrixZoom(mat);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Reference in New Issue
Block a user