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:
itsmattkc
2020-09-06 17:40:14 +10:00
6 changed files with 228 additions and 16 deletions
+4 -3
View File
@@ -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);
}
}
+134 -7
View File
@@ -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);
+77 -4
View File
@@ -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:
+7 -1
View File
@@ -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);
+5
View File
@@ -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
+1 -1
View File
@@ -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