colordialog/wheel/gradient: implemented basic UI components for color picking

This commit is contained in:
itsmattkc
2020-04-02 13:02:30 +11:00
parent 3bec108fee
commit f3290003be
27 changed files with 792 additions and 27 deletions
+4
View File
@@ -18,5 +18,9 @@ set(OLIVE_SOURCES
${OLIVE_SOURCES}
dialog/color/colordialog.h
dialog/color/colordialog.cpp
dialog/color/colorpreviewbox.h
dialog/color/colorpreviewbox.cpp
dialog/color/colorvalueswidget.h
dialog/color/colorvalueswidget.cpp
PARENT_SCOPE
)
+52 -6
View File
@@ -4,25 +4,71 @@
#include <QSplitter>
#include <QVBoxLayout>
#include "widget/colorwheel/colorwheelwidget.h"
#include "common/qtutils.h"
ColorDialog::ColorDialog(ColorManager* color_manager, QWidget *parent) :
ColorDialog::ColorDialog(ColorManager* color_manager, Color start, QWidget *parent) :
QDialog(parent),
color_manager_(color_manager)
{
setWindowTitle(tr("Select Color"));
QVBoxLayout* layout = new QVBoxLayout(this);
QSplitter* splitter = new QSplitter(Qt::Horizontal);
layout->addWidget(splitter);
ColorWheelWidget* cww1 = new ColorWheelWidget();
ColorWheelWidget* cww2 = new ColorWheelWidget();
QWidget* wheel_area = new QWidget();
QHBoxLayout* wheel_layout = new QHBoxLayout(wheel_area);
splitter->addWidget(wheel_area);
splitter->addWidget(cww1);
splitter->addWidget(cww2);
color_wheel_ = new ColorWheelGLWidget();
wheel_layout->addWidget(color_wheel_);
hsv_value_gradient_ = new ColorGradientGLWidget(Qt::Vertical);
hsv_value_gradient_->setFixedWidth(QFontMetricsWidth(fontMetrics(), QStringLiteral("HHH")));
wheel_layout->addWidget(hsv_value_gradient_);
ColorValuesWidget* cvw = new ColorValuesWidget();
splitter->addWidget(cvw);
connect(color_wheel_, &ColorWheelGLWidget::ColorChanged, cvw, &ColorValuesWidget::SetColor);
connect(color_wheel_, &ColorWheelGLWidget::ColorChanged, this, &ColorDialog::UpdateValueGradient);
connect(color_wheel_, &ColorWheelGLWidget::DiameterChanged, hsv_value_gradient_, &ColorGradientGLWidget::setFixedHeight);
connect(hsv_value_gradient_, &ColorGradientGLWidget::ColorChanged, cvw, &ColorValuesWidget::SetColor);
connect(hsv_value_gradient_, &ColorGradientGLWidget::ColorChanged, this, &ColorDialog::UpdateWheelValue);
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
layout->addWidget(buttons);
UpdateValueGradient(start);
UpdateWheelValue(start);
cvw->SetColor(start);
}
void ColorDialog::UpdateValueGradient(const Color &c)
{
float h, s, v;
c.toHsv(&h, &s, &v);
Color start = Color::fromHsv(h, s, 1.0f);
Color end = Color::fromHsv(h, s, 0.0f);
hsv_value_gradient_->SetColors(start, end);
}
void ColorDialog::UpdateWheelValue(const Color &c)
{
float h, s, v;
c.toHsv(&h, &s, &v);
color_wheel_->SetHSVValue(v);
}
void ColorDialog::UpdateValueGradientSize(int diameter)
{
hsv_value_gradient_->setFixedHeight(diameter);
}
+16 -1
View File
@@ -3,17 +3,32 @@
#include <QDialog>
#include "colorvalueswidget.h"
#include "render/color.h"
#include "render/colormanager.h"
#include "widget/colorwheel/colorwheelwidget.h"
#include "widget/colorwheel/colorgradientwidget.h"
class ColorDialog : public QDialog
{
Q_OBJECT
public:
ColorDialog(ColorManager* color_manager, QWidget* parent = nullptr);
ColorDialog(ColorManager* color_manager, Color start = Color(1.0f, 1.0f, 1.0f), QWidget* parent = nullptr);
private:
ColorManager* color_manager_;
ColorWheelGLWidget* color_wheel_;
ColorGradientGLWidget* hsv_value_gradient_;
private slots:
void UpdateValueGradient(const Color& c);
void UpdateWheelValue(const Color& c);
void UpdateValueGradientSize(int diameter);
};
#endif // COLORDIALOG_H
+31
View File
@@ -0,0 +1,31 @@
#include "colorpreviewbox.h"
#include <QPainter>
ColorPreviewBox::ColorPreviewBox(QWidget *parent) :
QWidget(parent)
{
}
void ColorPreviewBox::SetColor(const Color &c)
{
color_ = c;
update();
}
void ColorPreviewBox::paintEvent(QPaintEvent *e)
{
QWidget::paintEvent(e);
QPainter p(this);
p.setPen(Qt::black);
QColor c;
c.setRedF(color_.red());
c.setGreenF(color_.green());
c.setBlueF(color_.blue());
p.setBrush(c);
p.drawRect(rect());
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef COLORPREVIEWBOX_H
#define COLORPREVIEWBOX_H
#include <QWidget>
#include "render/color.h"
class ColorPreviewBox : public QWidget
{
Q_OBJECT
public:
ColorPreviewBox(QWidget* parent = nullptr);
public slots:
void SetColor(const Color& c);
protected:
virtual void paintEvent(QPaintEvent* e) override;
private:
Color color_;
};
#endif // COLORPREVIEWBOX_H
+62
View File
@@ -0,0 +1,62 @@
#include "colorvalueswidget.h"
#include <QGridLayout>
ColorValuesWidget::ColorValuesWidget(QWidget *parent) :
QWidget(parent)
{
QGridLayout* layout = new QGridLayout(this);
int row = 0;
layout->addWidget(new QLabel(tr("Preview")), row, 0);
preview_ = new ColorPreviewBox();
preview_->setFixedHeight(fontMetrics().height() * 3 / 2);
layout->addWidget(preview_, row, 1);
row++;
layout->addWidget(new QLabel(tr("Red")), row, 0);
red_slider_ = CreateColorSlider();
layout->addWidget(red_slider_, row, 1);
row++;
layout->addWidget(new QLabel(tr("Green")), row, 0);
green_slider_ = CreateColorSlider();
layout->addWidget(green_slider_, row, 1);
row++;
layout->addWidget(new QLabel(tr("Blue")), row, 0);
blue_slider_ = CreateColorSlider();
layout->addWidget(blue_slider_, row, 1);
}
Color ColorValuesWidget::GetColor() const
{
return Color(red_slider_->GetValue(),
green_slider_->GetValue(),
blue_slider_->GetValue());
}
void ColorValuesWidget::SetColor(const Color &c)
{
red_slider_->SetValue(c.red());
green_slider_->SetValue(c.green());
blue_slider_->SetValue(c.blue());
preview_->SetColor(c);
}
FloatSlider *ColorValuesWidget::CreateColorSlider()
{
FloatSlider* fs = new FloatSlider();
fs->SetMinimum(0);
fs->SetDragMultiplier(0.01);
fs->SetMaximum(1);
return fs;
}
+32
View File
@@ -0,0 +1,32 @@
#ifndef COLORVALUESWIDGET_H
#define COLORVALUESWIDGET_H
#include <QWidget>
#include "colorpreviewbox.h"
#include "render/color.h"
#include "widget/slider/floatslider.h"
class ColorValuesWidget : public QWidget
{
Q_OBJECT
public:
ColorValuesWidget(QWidget* parent = nullptr);
Color GetColor() const;
public slots:
void SetColor(const Color& c);
private:
static FloatSlider* CreateColorSlider();
ColorPreviewBox* preview_;
FloatSlider* red_slider_;
FloatSlider* green_slider_;
FloatSlider* blue_slider_;
};
#endif // COLORVALUESWIDGET_H
+1 -1
View File
@@ -93,7 +93,7 @@ public:
/**
* Floating-point type
*
* Resolves to `QRgba64`.
* Resolves to `Color`.
*
* Colors passed around the nodes should always be in reference space and preferably use
*/
+1 -1
View File
@@ -205,7 +205,7 @@ void OpenGLProxy::RunNodeAccelerated(const Node *node, const TimeRange &range, c
vert_code = OpenGLShader::CodeDefaultVertex();
}
shader = std::make_shared<OpenGLShader>();
shader = OpenGLShader::Create();
shader->create();
shader->addShaderFromSourceCode(QOpenGLShader::Fragment, frag_code);
shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vert_code);
@@ -132,7 +132,13 @@ GLenum OpenGLRenderFunctions::GetPixelType(const PixelFormat::Format &format)
return GL_INVALID_VALUE;
}
void OpenGLRenderFunctions::Blit(OpenGLShaderPtr pipeline, bool flipped, QMatrix4x4 matrix) {
void OpenGLRenderFunctions::Blit(OpenGLShaderPtr pipeline, bool flipped, QMatrix4x4 matrix)
{
Blit(pipeline.get(), flipped, matrix);
}
void OpenGLRenderFunctions::Blit(OpenGLShader *pipeline, bool flipped, QMatrix4x4 matrix)
{
// FIXME: is currentContext() reliable here?
QOpenGLFunctions* func = QOpenGLContext::currentContext()->functions();
@@ -181,7 +187,12 @@ void OpenGLRenderFunctions::Blit(OpenGLShaderPtr pipeline, bool flipped, QMatrix
m_vao.destroy();
}
void OpenGLRenderFunctions::OCIOBlit(OpenGLShaderPtr pipeline,
void OpenGLRenderFunctions::OCIOBlit(OpenGLShaderPtr pipeline, GLuint lut, bool flipped, QMatrix4x4 matrix)
{
OCIOBlit(pipeline.get(), lut, flipped, matrix);
}
void OpenGLRenderFunctions::OCIOBlit(OpenGLShader *pipeline,
GLuint lut,
bool flipped,
QMatrix4x4 matrix)
@@ -46,8 +46,10 @@ public:
* Transformation matrix to use when drawing (defaults to no transform)
*/
static void Blit(OpenGLShaderPtr pipeline, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
static void Blit(OpenGLShader* pipeline, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
static void OCIOBlit(OpenGLShaderPtr pipeline, GLuint lut, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
static void OCIOBlit(OpenGLShader* pipeline, GLuint lut, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
static void PrepareToDraw(QOpenGLFunctions* f);
+6 -1
View File
@@ -7,9 +7,14 @@ OpenGLShader::OpenGLShader()
}
OpenGLShaderPtr OpenGLShader::Create()
{
return std::make_shared<OpenGLShader>();
}
OpenGLShaderPtr OpenGLShader::CreateDefault(const QString &function_name, const QString &shader_code)
{
OpenGLShaderPtr program = std::make_shared<OpenGLShader>();
OpenGLShaderPtr program = Create();
// Add shaders to program
program->addShaderFromSourceCode(QOpenGLShader::Vertex, CodeDefaultVertex());
+2
View File
@@ -17,6 +17,8 @@ class OpenGLShader : public QOpenGLShaderProgram {
public:
OpenGLShader();
static OpenGLShaderPtr Create();
static OpenGLShaderPtr CreateDefault(const QString &function_name = QString(),
const QString &shader_code = QString());
+95
View File
@@ -1,5 +1,46 @@
#include "color.h"
Color Color::fromHsv(const float &h, const float &s, const float &v)
{
float C = s * v;
float X = C * (1.0f - abs(fmod(h / 60.0f, 2.0f) - 1.0f));
float m = v - C;
float Rs, Gs, Bs;
if(h >= 0.0f && h < 60.0f) {
Rs = C;
Gs = X;
Bs = 0.0f;
}
else if(h >= 60.0f && h < 120.0f) {
Rs = X;
Gs = C;
Bs = 0.0f;
}
else if(h >= 120.0f && h < 180.0f) {
Rs = 0.0f;
Gs = C;
Bs = X;
}
else if(h >= 180.0f && h < 240.0f) {
Rs = 0.0f;
Gs = X;
Bs = C;
}
else if(h >= 240.0f && h < 300.0f) {
Rs = X;
Gs = 0.0f;
Bs = C;
}
else {
Rs = C;
Gs = 0.0f;
Bs = X;
}
return Color(Rs + m, Gs + m, Bs + m);
}
Color::Color(const char *data, const PixelFormat::Format &format)
{
OIIO::convert_type(PixelFormat::GetOIIOTypeDesc(format),
@@ -12,3 +53,57 @@ Color::Color(const char *data, const PixelFormat::Format &format)
set_alpha(1.0f);
}
}
void Color::toHsv(float *hue, float *sat, float *val) const
{
float fCMax = qMax(qMax(red(), green()), blue());
float fCMin = qMin(qMin(red(), green()), blue());
float fDelta = fCMax - fCMin;
if(fDelta > 0) {
if(fCMax == red()) {
*hue = 60 * (fmod(((green() - blue()) / fDelta), 6));
} else if(fCMax == green()) {
*hue = 60 * (((blue() - red()) / fDelta) + 2);
} else if(fCMax == blue()) {
*hue = 60 * (((red() - green()) / fDelta) + 4);
}
if(fCMax > 0) {
*sat = fDelta / fCMax;
} else {
*sat = 0;
}
*val = fCMax;
} else {
*hue = 0;
*sat = 0;
*val = fCMax;
}
if(*hue < 0) {
*hue = 360 + *hue;
}
}
float Color::hue() const
{
float h, s, v;
toHsv(&h, &s, &v);
return h;
}
float Color::saturation() const
{
float h, s, v;
toHsv(&h, &s, &v);
return s;
}
float Color::value() const
{
float h, s, v;
toHsv(&h, &s, &v);
return v;
}
+12
View File
@@ -25,6 +25,13 @@ public:
data_[3] = a;
}
/**
* @brief Creates a Color struct from hue/saturation/value
*
* Hue expects a value between 0.0 and 360.0. Saturation and Value expect a value between 0.0 and 1.0.
*/
static Color fromHsv(const float& h, const float& s, const float &v);
Color(const char *data, const PixelFormat::Format &format);
const float& red() const {return data_[0];}
@@ -32,6 +39,11 @@ public:
const float& blue() const {return data_[2];}
const float& alpha() const {return data_[3];}
void toHsv(float* hue, float* sat, float* val) const;
float hue() const;
float saturation() const;
float value() const;
void set_red(const float& red) {data_[0] = red;}
void set_green(const float& green) {data_[1] = green;}
void set_blue(const float& blue) {data_[2] = blue;}
+25
View File
@@ -0,0 +1,25 @@
#version 110
// Standard inputs
uniform vec2 ove_resolution;
varying vec2 ove_texcoord;
// Inputs
uniform int orientation;
uniform vec3 color_a;
uniform vec3 color_b;
void main(void) {
float t;
// This very roughly conforms to Qt::Orientation
if (orientation == 1) {
// Horizontal orientation
t = ove_texcoord.x;
} else {
// Vertical orientation
t = 1.0 - ove_texcoord.y;
}
gl_FragColor = vec4(mix(color_a, color_b, t), 1.0);
}
+91
View File
@@ -0,0 +1,91 @@
#version 110
// Standard inputs
uniform vec2 ove_resolution;
varying vec2 ove_texcoord;
// Custom inputs
uniform float hsv_value;
// Color wheel uses PI
#define M_PI 3.1415926535897932384626433832795
vec3 hsv_to_rgb(float H, float S, float V) {
float C = S * V;
float X = C * (1.0 - abs(mod(H / 60.0, 2.0) - 1.0));
float m = V - C;
float Rs, Gs, Bs;
if(H >= 0.0 && H < 60.0) {
Rs = C;
Gs = X;
Bs = 0.0;
}
else if(H >= 60.0 && H < 120.0) {
Rs = X;
Gs = C;
Bs = 0.0;
}
else if(H >= 120.0 && H < 180.0) {
Rs = 0.0;
Gs = C;
Bs = X;
}
else if(H >= 180.0 && H < 240.0) {
Rs = 0.0;
Gs = X;
Bs = C;
}
else if(H >= 240.0 && H < 300.0) {
Rs = X;
Gs = 0.0;
Bs = C;
}
else {
Rs = C;
Gs = 0.0;
Bs = X;
}
return vec3(Rs + m, Gs + m, Bs + m);
}
void main(void) {
vec2 center = vec2(0.5, 0.5);
float radius = 0.5;
vec2 flipped_texcoord = vec2(ove_texcoord.x, (1.0 - ove_texcoord.y));
// Calculate scale
if (ove_resolution.x != ove_resolution.y) {
// Scale around center
flipped_texcoord -= vec2(0.5, 0.5);
if (ove_resolution.x > ove_resolution.y) {
flipped_texcoord.x *= ove_resolution.x / ove_resolution.y;
} else {
flipped_texcoord.y *= ove_resolution.y / ove_resolution.x;
}
flipped_texcoord += vec2(0.5, 0.5);
}
float dist = distance(flipped_texcoord, center);
if (dist <= radius) {
float opposite = flipped_texcoord.y - center.y;
float adjacent = flipped_texcoord.x - center.x;
float hue = atan(opposite, adjacent) * 180.0 / M_PI + 180.0;
float sat = dist / radius;
// Extremely simple antialiasing, we taper off the edges between (radius) and (radius - 1)
float pixel_radius = min(ove_resolution.x, ove_resolution.y) * 0.5;
float pixel_dist = (pixel_radius / radius) * dist;
float alpha = min((pixel_radius - pixel_dist), 1.0);
gl_FragColor = vec4(hsv_to_rgb(hue, sat, hsv_value), alpha);
} else {
gl_FragColor = vec4(0.0);
}
}
+2
View File
@@ -4,6 +4,8 @@
<file>alphaover.xml</file>
<file>boxblur.frag</file>
<file>boxblur.xml</file>
<file>colorgradient.frag</file>
<file>colorwheel.frag</file>
<file>crossdissolve.frag</file>
<file>crossdissolve.xml</file>
<file>dropshadow.frag</file>
+3 -1
View File
@@ -5,11 +5,13 @@
ColorButton::ColorButton(QWidget *parent) :
QPushButton(parent)
{
color_ = Color(1.0f, 1.0f, 1.0f);
connect(this, &ColorButton::clicked, this, &ColorButton::ShowColorDialog);
}
void ColorButton::ShowColorDialog()
{
ColorDialog cd(nullptr);
ColorDialog cd(nullptr, color_, this);
cd.exec();
}
+5
View File
@@ -3,6 +3,8 @@
#include <QPushButton>
#include "render/color.h"
class ColorButton : public QPushButton
{
Q_OBJECT
@@ -15,6 +17,9 @@ signals:
private slots:
void ShowColorDialog();
private:
Color color_;
};
#endif // COLORBUTTON_H
+4
View File
@@ -16,6 +16,10 @@
set(OLIVE_SOURCES
${OLIVE_SOURCES}
widget/colorwheel/colorgradientwidget.h
widget/colorwheel/colorgradientwidget.cpp
widget/colorwheel/colorswatchwidget.h
widget/colorwheel/colorswatchwidget.cpp
widget/colorwheel/colorwheelwidget.h
widget/colorwheel/colorwheelwidget.cpp
PARENT_SCOPE
@@ -0,0 +1,57 @@
#include "colorgradientwidget.h"
#include "common/lerp.h"
#include "node/node.h"
ColorGradientGLWidget::ColorGradientGLWidget(Qt::Orientation orientation, QWidget *parent) :
ColorSwatchWidget(parent),
orientation_(orientation)
{
}
void ColorGradientGLWidget::SetColors(const Color &a, const Color &b)
{
a_ = a;
b_ = b;
update();
}
Color ColorGradientGLWidget::GetColorFromCursorPos(const QPoint &p) const
{
float t;
if (orientation_ == Qt::Horizontal) {
t = static_cast<float>(p.x()) / static_cast<float>(width());
} else {
t = static_cast<float>(p.y()) / static_cast<float>(height());
}
return Color(lerp(a_.red(), b_.red(), t),
lerp(a_.green(), b_.green(), t),
lerp(a_.blue(), b_.blue(), t));
}
bool ColorGradientGLWidget::PointIsValid(const QPoint &) const
{
return true;
}
OpenGLShader *ColorGradientGLWidget::CreateShader() const
{
OpenGLShader* s = new OpenGLShader();
s->create();
s->addShaderFromSourceCode(QOpenGLShader::Vertex, OpenGLShader::CodeDefaultVertex());
s->addShaderFromSourceCode(QOpenGLShader::Fragment, Node::ReadFileAsString(QStringLiteral(":/shaders/colorgradient.frag")));
s->link();
return s;
}
void ColorGradientGLWidget::SetShaderUniformValues(OpenGLShader *shader) const
{
shader->setUniformValue("orientation", orientation_);
shader->setUniformValue("color_a", a_.red(), a_.green(), a_.blue());
shader->setUniformValue("color_b", b_.red(), b_.green(), b_.blue());
}
@@ -0,0 +1,33 @@
#ifndef COLORGRADIENTGLWIDGET_H
#define COLORGRADIENTGLWIDGET_H
#include "colorswatchwidget.h"
#include "render/color.h"
class ColorGradientGLWidget : public ColorSwatchWidget
{
Q_OBJECT
public:
ColorGradientGLWidget(Qt::Orientation orientation, QWidget* parent = nullptr);
void SetColors(const Color& a, const Color& b);
protected:
virtual Color GetColorFromCursorPos(const QPoint& p) const override;
virtual bool PointIsValid(const QPoint& p) const override;
virtual OpenGLShader* CreateShader() const override;
virtual void SetShaderUniformValues(OpenGLShader* shader) const override;
private:
Qt::Orientation orientation_;
Color a_;
Color b_;
};
#endif // COLORGRADIENTGLWIDGET_H
@@ -0,0 +1,61 @@
#include "colorswatchwidget.h"
#include <QMouseEvent>
#include "render/backend/opengl/openglrenderfunctions.h"
ColorSwatchWidget::ColorSwatchWidget(QWidget *parent) :
QOpenGLWidget(parent),
shader_(nullptr)
{
// Render with transparent background
setAttribute(Qt::WA_AlwaysStackOnTop);
}
ColorSwatchWidget::~ColorSwatchWidget()
{
CleanUp();
}
void ColorSwatchWidget::initializeGL()
{
CleanUp();
shader_ = CreateShader();
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &ColorSwatchWidget::CleanUp);
}
void ColorSwatchWidget::paintGL()
{
shader_->bind();
shader_->setUniformValue("ove_resolution", width(), height());
SetShaderUniformValues(shader_);
shader_->release();
OpenGLRenderFunctions::Blit(shader_);
}
void ColorSwatchWidget::CleanUp()
{
delete shader_;
shader_ = nullptr;
}
void ColorSwatchWidget::mousePressEvent(QMouseEvent *e)
{
QOpenGLWidget::mousePressEvent(e);
if (PointIsValid(e->pos())) {
emit ColorChanged(GetColorFromCursorPos(e->pos()));
}
}
void ColorSwatchWidget::mouseMoveEvent(QMouseEvent *e)
{
QOpenGLWidget::mouseMoveEvent(e);
if (e->buttons() & Qt::LeftButton && PointIsValid(e->pos())) {
emit ColorChanged(GetColorFromCursorPos(e->pos()));
}
}
+45
View File
@@ -0,0 +1,45 @@
#ifndef COLORSWATCHWIDGET_H
#define COLORSWATCHWIDGET_H
#include <QOpenGLWidget>
#include "render/backend/opengl/openglshader.h"
#include "render/color.h"
class ColorSwatchWidget : public QOpenGLWidget
{
Q_OBJECT
public:
ColorSwatchWidget(QWidget* parent = nullptr);
virtual ~ColorSwatchWidget() override;
signals:
void ColorChanged(const Color& c);
protected:
virtual void initializeGL() override;
virtual void paintGL() override;
virtual void mousePressEvent(QMouseEvent* e) override;
virtual void mouseMoveEvent(QMouseEvent* e) override;
virtual void SetShaderUniformValues(OpenGLShader*) const {}
virtual Color GetColorFromCursorPos(const QPoint& p) const = 0;
virtual bool PointIsValid(const QPoint& p) const = 0;
virtual OpenGLShader* CreateShader() const = 0;
private slots:
void CleanUp();
private:
OpenGLShader* shader_;
};
#endif // COLORSWATCHWIDGET_H
+73 -10
View File
@@ -1,16 +1,81 @@
#include "colorwheelwidget.h"
#include <QPainter>
#include <QtMath>
#define RADIAN_TO_0_1_RANGE 0.15915494309188486110703542313983
#include "node/node.h"
ColorWheelWidget::ColorWheelWidget(QWidget *parent) :
QWidget(parent)
#define M_180_OVER_PI 57.295791433133264917914229473464
ColorWheelGLWidget::ColorWheelGLWidget(QWidget *parent) :
ColorSwatchWidget(parent),
hsv_value_(1.0f)
{
}
void ColorWheelGLWidget::SetHSVValue(float val)
{
hsv_value_ = val;
update();
}
Color ColorWheelGLWidget::GetColorFromCursorPos(const QPoint &p) const
{
QPoint center = rect().center();
qreal opposite = p.y() - center.y();
qreal adjacent = p.x() - center.x();
qreal distance = qSqrt(qPow(adjacent, 2) + qPow(opposite, 2));
qreal hue = qAtan2(opposite, adjacent) * M_180_OVER_PI + 180.0;
qreal sat = (distance / GetRadius());
qreal value = hsv_value_;
return Color::fromHsv(hue, sat, value);
}
bool ColorWheelGLWidget::PointIsValid(const QPoint &p) const
{
QPoint center = rect().center();
qreal distance = qSqrt(qPow(p.x() - center.x(), 2) + qPow(p.y() - center.y(), 2));
return (distance <= GetRadius());
}
OpenGLShader *ColorWheelGLWidget::CreateShader() const
{
OpenGLShader* s = new OpenGLShader();
s->create();
s->addShaderFromSourceCode(QOpenGLShader::Vertex, OpenGLShader::CodeDefaultVertex());
s->addShaderFromSourceCode(QOpenGLShader::Fragment, Node::ReadFileAsString(QStringLiteral(":/shaders/colorwheel.frag")));
s->link();
return s;
}
void ColorWheelGLWidget::SetShaderUniformValues(OpenGLShader *shader) const
{
shader->setUniformValue("hsv_value", hsv_value_);
}
void ColorWheelGLWidget::resizeEvent(QResizeEvent *e)
{
ColorSwatchWidget::resizeEvent(e);
emit DiameterChanged(GetDiameter());
}
int ColorWheelGLWidget::GetDiameter() const
{
return qMin(width(), height());
}
qreal ColorWheelGLWidget::GetRadius() const
{
return GetDiameter() * 0.5;
}
/* Software/QPainter-based color wheel
void ColorWheelWidget::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
@@ -20,12 +85,10 @@ void ColorWheelWidget::paintEvent(QPaintEvent *event)
qreal radius = qMin(width(), height()) / 2;
QPoint center = rect().center();
p.setPen(Qt::red);
int x_start = center.x() - radius;
int x_end= center.x() + radius;
int x_end = center.x() + radius;
int y_start = center.y() - radius;
int y_end= center.y() + radius;
int y_end = center.y() + radius;
for (int i=x_start;i<x_end;i++) {
for (int j=y_start;j<y_end;j++) {
@@ -46,4 +109,4 @@ void ColorWheelWidget::paintEvent(QPaintEvent *event)
}
}
}
}
}*/
+39 -4
View File
@@ -1,16 +1,51 @@
#ifndef COLORWHEELWIDGET_H
#define COLORWHEELWIDGET_H
#include <QWidget>
#include <QOpenGLWidget>
class ColorWheelWidget : public QWidget
#include "colorswatchwidget.h"
#include "render/backend/opengl/openglshader.h"
#include "render/color.h"
class ColorWheelGLWidget : public ColorSwatchWidget
{
Q_OBJECT
public:
ColorWheelGLWidget(QWidget* parent = nullptr);
void SetHSVValue(float val);
signals:
void DiameterChanged(int radius);
protected:
virtual Color GetColorFromCursorPos(const QPoint& p) const override;
virtual bool PointIsValid(const QPoint& p) const override;
virtual OpenGLShader* CreateShader() const override;
virtual void SetShaderUniformValues(OpenGLShader* shader) const override;
virtual void resizeEvent(QResizeEvent* e) override;
private:
int GetDiameter() const;
qreal GetRadius() const;
float hsv_value_;
};
/*class ColorWheelWidget : public QWidget
{
public:
ColorWheelWidget(QWidget* parent = nullptr);
protected:
virtual void paintEvent(QPaintEvent* event) override;
virtual void paintEvent(QPaintEvent* e) override;
};
};*/
#endif // COLORWHEELWIDGET_H